版本说明:nsq v1.2.0版本.
功能
安装
mac:
1 | $ brew install nsq |
测试
默认是foreground模式,需要在不同的shell下分别执行如下命令
1 | $ nsqlookupd //监听 tcp 4160,http 4161 |
Guarantees
- 默认不持久化,可配置
- delive-policy:at-least-once,客户端自己保证幂等性
- push模式
- 消息无序
- CAP中占CA,保证最终一致性
design
- topic描述数据,channel描述下游consumer的功能
- topic->channel,多播,一个topic中所有channel中都有相同的全量信息
- channel->consumers,负载均衡
- nsqd:服务节点,保存topic和data
- nsqlookupd:服务发现节点,client通过nsqlookupd发现某个topic属于哪个nsqd.启动多个但不会互相传递信息,只保证最终一致性
- nsqadmin:可视化查看服务和消息
- at-least-once:通过客户端发送FIN(finish)或者REQ(re-queue)确认是否处理成功.否则放入requeue继续重试
- –mem-queue-size通过该参数控制内存占用
- 通过客户端flow control,更新RDY状态控制nsqd push消息的条数
代码解析
nsq中的channel写为channel,go语言中的channel写为go-chan
结构体分析
关键结构体为:
- NSQD
- Topic
- Channel
- Message
NSQD管理Topic以及监听tcp和http端口,Topic管理Channel,Channel管理message.
NSQD
属性和方法见名思义,关键介绍一下queueScanLoop方法.
每个channel中有两个优先级队列,分别处理在途消息的超时和延迟消息的传递.queueScanLoop在一个单独的goroutine中执行,模仿redis的主动过期算法,每100ms随机选取20个channel查看在途和延迟的优先级队列,如果需要处理的channel个数超出25%,则继续处理其他channel的在途和延迟队列.否则等待下一个周期
Topic&Channel
关键介绍Topic的messagePump方法
该方法将一个topic中的所有数据写入该topic下的所有channel中.
Message
Message是每条消息的具体结构.
协议解析
context中保存一个NSQD实例指针,protocolV2具体执行协议的解析
协议解析参考链接2
protocolV2
protocal
说明
文中未对消息传递过程做进一步说明,例如起了多少goroutine,每个goroutine具体执行什么任务,goroutine之间如何传递信息(即一些关键的go channel).这些内容可以单独写一篇文章.本文重点是实践一种源代码阅读的方法:
- 了解nsqd的原理及设计思路(通过阅读参考链接中的文档)
- 通过每个文件的代码行数及关键结构体了解整体框架(阅读代码)
- 结构体之间的关系
如此,只需3-4小时即可快速掌握一个5000行左右代码的组件(gin/nsqd都是5000行左右代码)