一、概览
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 将写入到磁盘中