Go-Nsq资料整理和学习笔记

写在前面:

NSQ版本 : v1.2.0
在源码层面,完整阅读了一个GO-Lang实际的项目-NSQ,目标是让自己从学习、熟悉Go语法,进阶到深入理解GO,理解实现工程中GO的使用和组织。现把这大半个月阅读的文章和学习笔记做一些整理。

一. NSQ官网(nsq.io)

这个没啥好说的,官方文档是最权威的.逐页看就是,后来发现一个中文的:

中文文档-0.3.5

其他介绍参考文档
https://www.jianshu.com/p/c47e0350bb2e
https://www.cnblogs.com/li-peng/category/1537661.html
https://segmentfault.com/a/1190000012362544
http://blog.rayxxzhang.com/index.html
http://luodw.cc/2017/04/14/nsqd/
https://www.cnblogs.com/li-peng/p/11435083.html


二. NSQ依赖

NSQ已经改成go modules来管理包.


module github.com/nsqio/nsq

require (
    github.com/BurntSushi/toml v0.3.1
    github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932
    github.com/bitly/timer_metrics v0.0.0-20170606164300-b1c65ca7ae62
    github.com/blang/semver v3.5.1+incompatible
    github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b
    github.com/davecgh/go-spew v1.1.1 // indirect
    github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
    github.com/judwhite/go-svc v1.0.0
    github.com/julienschmidt/httprouter v1.2.0
    github.com/mreiferson/go-options v0.0.0-20190302015348-0c63f026bcd6
    github.com/nsqio/go-diskqueue v0.0.0-20180306152900-74cfbc9de839
    github.com/nsqio/go-nsq v1.0.7
    github.com/pmezard/go-difflib v1.0.0 // indirect
    github.com/stretchr/testify v1.2.2 // indirect
    golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6 // indirect
)

可以看出基本大部分都是自己的依赖(其中nsqio和bilty部分),都是一些小的工具包.
唯一需要注意的是httprouter,nsq用它来装饰处理http请求.

package 简要说明
go-difflib python迁移的对比包
go-diskqueue 官方提供的文件记录包-用于在channel满的时候,作为backendQueue保存到文件中
go-hostpool 把主机信息池化
go-nsq NSQ官方提供的客户端实现
go-options 读取命令行配置工具
go-spew 格式化打印
go-svc 用于包装为系统服务(会识别环境)
http-router 轻量级http请求路由
perks 产生图标的工具包
semver 解析版本字符串的工具(如1.0.3-beta)
snappy 压缩算法包
x/sys GO官方扩展包
timer_metrics 计时测量
toml nsq使用toml文件格式作为配置持久化

三. Go-nsq (V1.0.7)

  • 首先要理解go-nsq作为官方提供的客户端,怎么使用,先堆一堆参考文档:

https://nicksors.cc/2018/08/15/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97%E4%B9%8B%E3%80%8A02-NSQ%E5%AE%9E%E8%B7%B5%E7%AF%87%E3%80%8B.html
https://cloud.tencent.com/developer/article/1070860
https://segmentfault.com/a/1190000009194607
https://lihaoquan.me/2016/6/20/using-nsq.html
https://juejin.im/post/5d3e3a44f265da1bae39439a
https://www.cnblogs.com/li-peng/p/11435083.html

  • 其次是看源码,代码不多.我理解核心还是搞懂Conn,Delegate,Consumer,Producer之间的关系.默认的Consumer和Producer都实现了ConnDelegate接口,用来把连接conn上的事件传导给具体的
    Consumer和Producer去完成.

Delegate使得它们之间的关系解耦,避免了Conn和Consumer双向引用.

  • 测试代码:
    1. Config_test.go | Go语言可以很方便用数组形式构造测试案例
    2. Producer_test.go | 测试生产者
    3. Consumer_test.go | 测试消费者

四. nsq-internal

nsq-internal是几个实现共用的一些工具包

package 简要说明
app 包含FloatArray和StringArray,用在解析命令参数
auth Authorization结构,用在权限控制(本次阅读忽略)
clusterinfo 用来外呼http请求,获取信息
dirlock 锁定目录(windows无效)
httpapi 带截止时间的http请求封装(主要和go-nsq中的不同)
lg 日志工具
pqueue 以Item为元素的优先级队列,其中Item.value是个空接口,用在diskBackend中.奇怪的是InflightQueue是用Message实现的一套.
protocol 用来表明自己能处理的tcp协议报文.(nsqd和nsqlookupd都有自己的实现)
quanltile 统计用的火焰图数据
statsd 登记统计信息的服务器调用简单包装
stringy nsq用的几个字符串函数工具包
test nsq对测试的工具包,其中FakeNetConn可以伪装为一个连接
util WaitGroupWrapper把普通的函数(无参数,无返回值)同步调用包装成异步调用
version 表明版本号(目前1.2.1)
writers BoundaryBufferedWriter和SpreadWriter两种实现

五. nsq-apps

由nsq提供的可执行程序的源码,除了nsqd、nsqlookup、nsqadmin这几个服务端封装外,基本都是用go-nsq(客户端)实现特定功能的命令行工具。

package 简要说明
nsq_stat 使用http_api实现对特定的topic,channel的监控(打印控制台)
nsq_tail 订阅消费特定Topic消息,实现对特定的channel监控(打印控制台)
nsq_to_file 订阅消费特Channel消息,记录到文件
nsq_to_http 把Nsq消息通过http发出
nsq_to_nsq 桥接Nsq消息-转发
to_nsq 读取文件中message,发送到nsqd中

六. nsq-nsqd

NSQD是整个消息中间件的核心,所幸很多人都分析了,这里不需要再累述,看代码的同时,结合牛人的文章即可:

NSQ源码分析之概述(不错)
http://luodw.cc/2016/12/08/nsq01/
http://luodw.cc/2016/12/13/nsqlookupd/
http://luodw.cc/2017/04/14/nsqd/
nsq源码分析
https://www.cnblogs.com/hlxs/p/11445103.html
nsq源码学习
https://segmentfault.com/a/1190000012362544
NSQ源码剖析之nsqd(不错)
http://shanks.leanote.com/post/NSQ%E6%BA%90%E7%A0%81%E5%89%96%E6%9E%90%E4%B9%8BNSQD
nsq源码阅读(nsqd)(不错)
http://sksun.com.cn/2018/06/13/nsq%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-nsqd/
http://sksun.com.cn/2018/06/12/nsq%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB-nsqlookupd/

  • 结构:
    NSQ结构是多层次的,NSQD有个topicMap,记录所有的Topic;topic有个channelMap,记录所有的Channel,Channel有个clients,记录所有的消费者.这些结构都有一个ctx指针,指向NSQD自身.

  • 启动:
    先启动TcpServer,HttpServer,处理报文
    再启动queueScanLoop(动态调整queueScanWorker的数目,处理in-flight和deffered queue的消息),lookupLoop(和nsqlookupd服务器连接),statsdLoop(和stasd服务器连接)

  • 消息处理:
    略,上面文章讲太多了..

  • 代码阅读中一些疑问:

  1. Topic创建时机?
    在Publish时,如果不存在,会自动创建.

  2. Channel创建时机?
    在Sub是,如果不存在,会自动创建.

  3. deferredMessages与inFlightMessages
    Channel内部维护2个队列,infight表示正在和client交互(等到client返回FIN才删除,保证消息至少被接收一次),deferred表示可以提前给nsqd发送message,等到时间到才合法.

  4. BackendQueue与ephemeral
    如果声明为ephemera,则如果消息超过infight队列长度,就会被丢弃.而BackendQueue可以用go-diskqueue包提供的方法保存到文件中.

  5. 消息有序性?
    NSQ不保证,可能无序(requeue机制,多节点机制)

  6. 丢消息?
    如果异常退出,infightMsg可能会丢

  7. RDY意义:
    RDY是订阅方告知NSQD服务器自身处理能力的方法,这样避免服务器快速给客户端发消息,客户端处理不过来的情况(Rx中背压)


七. nsq-nsqlookupd

与nsqd类似,nsqlookupd通过TCP和Http两种方式向外提供服务.

  1. RegistrationDB
    登记nsq信息的内存DB,使用registrationMap,ProducerMap两层MAP,并且实现了add,remove,find,这些操作,便于上层进行调用.
  2. lookup_protocol_v1
    提供tcp服务,只有Ping,Identify,Register,Unregister四个方法,也就是说,只有nsqd才会使用tcp和nsqlookupd连接通讯.(Category有topic和channel,client三种)
  3. http
    提供http服务,消费者使用nsqlookupd提供的方法感知,而producer是需要直连nsqd的.
    提供了"/topic/create","/topic/delete"这种,不是给nsqd用的,是给go-nsq客户端或者nqadmin手工删除topic用的.

八. nsq-nsqadmin

admin相对比较简单(go部分),通过notify构造AdminAction向外主动POST,或者通过http向外提供服务.而且,它本身并不存储任何数据,需要时,都是使用httpServer中的client向nslookupd或者nsqd查询(类似于gateway).这里用了internal/clusterinfo,先调用nslookupd,不行就直接请求nsqd(需要遍历所有的nsqd,为了效率,还是搭建nslookupd吧).
前端页面部分用了backdone+jquery+gulp.未看...

九. 其他

  1. bench目录: 用python写的批量测试用例
  2. 有赞nsq (https://github.com/youzan/nsq)
    发现有赞Fork了一个分支,并做了改进,有机会再细看一下...

How we redesign the NSQ-Smart Client

How we redesigned the NSQ - NSQ重塑之详细设计
视频观看

How we redesigned the NSQ - 其他特性及未来计划

有赞NSQ多集群多机房设计

你可能感兴趣的:(Go-Nsq资料整理和学习笔记)