nsq 源码解读(4): pub msg

41 阅读1分钟

一、概览

nsqd 处理pub 入口函数是

func (p *protocolV2) PUB(client *clientV2, params [][]byte) ([]byte, error) {
   ///
   err = topic.PutMessage(msg)
   ///
}

源码

nsq topic实际处理 msg函数为

// PutMessage writes a Message to the queue
func (t *Topic) PutMessage(m *Message) error {
        ///
	err := t.put(m)
        ///
	return nil
}

func (t *Topic) put(m *Message) error {

        t.memoryMsgChan <- m:
	return nil
}

源码

二、消息队列

func (t *Topic) put(m *Message) error {
	// If mem-queue-size == 0, avoid memory chan, for more consistent ordering,
	// but try to use memory chan for deferred messages (they lose deferred timer
	// in backend queue) or if topic is ephemeral (there is no backend queue).
	if cap(t.memoryMsgChan) > 0 || t.ephemeral || m.deferred != 0 {
		select {
		case t.memoryMsgChan <- m:
			return nil
		default:
			break // write to backend
		}
	}
	err := writeMessageToBackend(m, t.backend)
	t.nsqd.SetHealth(err)
	if err != nil {
		t.nsqd.logf(LOG_ERROR,
			"TOPIC(%s) ERROR: failed to write message to backend - %s",
			t.name, err)
		return err
	}
	return nil
}

2.1 写入 msg 到消息队列

2.1.1 首先考虑将消息,写入到 topic 内存队列

当满足下面的条件时候,

(1)topic 当前的内存队列还没有写满,

(2)当前的 topic 是临时 topic

(3)当前消息是延迟消费

使用 select default 分支可以保证如果内存队列已经满了,msg 数据写入到后端存储

2.1.2 消息写入到 磁盘

当内存队列已经满了,msg 将写入到磁盘中

2.2 消费 msg