寫在前面:
NSQ版本 : v1.2.0
在源碼層面,完整閱讀了一個GO-Lang實際的項目-NSQ,目標是讓自己從學習邓萨、熟悉Go語法地梨,進階到深入理解GO,理解實現(xiàn)工程中GO的使用和組織〉蘅遥現(xiàn)把這大半個月閱讀的文章和學習筆記做一些整理宝剖。
一. NSQ官網(wǎng)(nsq.io)
這個沒啥好說的,官方文檔是最權威的.逐頁看就是,后來發(fā)現(xiàn)一個中文的:
其他介紹參考文檔
http://www.reibang.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已經(jīng)改成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官方提供的客戶端實現(xiàn) |
go-options | 讀取命令行配置工具 |
go-spew | 格式化打印 |
go-svc | 用于包裝為系統(tǒng)服務(會識別環(huán)境) |
http-router | 輕量級http請求路由 |
perks | 產(chǎn)生圖標的工具包 |
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都實現(xiàn)了ConnDelegate接口,用來把連接conn上的事件傳導給具體的
Consumer和Producer去完成.
Delegate使得它們之間的關系解耦,避免了Conn和Consumer雙向引用.
- 測試代碼:
- Config_test.go | Go語言可以很方便用數(shù)組形式構造測試案例
- Producer_test.go | 測試生產(chǎn)者
- Consumer_test.go | 測試消費者
四. nsq-internal
nsq-internal是幾個實現(xiàn)共用的一些工具包
package | 簡要說明 |
---|---|
app | 包含F(xiàn)loatArray和StringArray,用在解析命令參數(shù) |
auth | Authorization結構,用在權限控制(本次閱讀忽略) |
clusterinfo | 用來外呼http請求,獲取信息 |
dirlock | 鎖定目錄(windows無效) |
httpapi | 帶截止時間的http請求封裝(主要和go-nsq中的不同) |
lg | 日志工具 |
pqueue | 以Item為元素的優(yōu)先級隊列,其中Item.value是個空接口,用在diskBackend中.奇怪的是InflightQueue是用Message實現(xiàn)的一套. |
protocol | 用來表明自己能處理的tcp協(xié)議報文.(nsqd和nsqlookupd都有自己的實現(xiàn)) |
quanltile | 統(tǒng)計用的火焰圖數(shù)據(jù) |
statsd | 登記統(tǒng)計信息的服務器調(diào)用簡單包裝 |
stringy | nsq用的幾個字符串函數(shù)工具包 |
test | nsq對測試的工具包,其中FakeNetConn可以偽裝為一個連接 |
util | WaitGroupWrapper把普通的函數(shù)(無參數(shù),無返回值)同步調(diào)用包裝成異步調(diào)用 |
version | 表明版本號(目前1.2.1) |
writers | BoundaryBufferedWriter和SpreadWriter兩種實現(xiàn) |
五. nsq-apps
由nsq提供的可執(zhí)行程序的源碼,除了nsqd、nsqlookup歉甚、nsqadmin這幾個服務端封裝外万细,基本都是用go-nsq(客戶端)實現(xiàn)特定功能的命令行工具。
package | 簡要說明 |
---|---|
nsq_stat | 使用http_api實現(xiàn)對特定的topic,channel的監(jiān)控(打印控制臺) |
nsq_tail | 訂閱消費特定Topic消息,實現(xiàn)對特定的channel監(jiān)控(打印控制臺) |
nsq_to_file | 訂閱消費特Channel消息,記錄到文件 |
nsq_to_http | 把Nsq消息通過http發(fā)出 |
nsq_to_nsq | 橋接Nsq消息-轉發(fā) |
to_nsq | 讀取文件中message,發(fā)送到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(動態(tài)調(diào)整queueScanWorker的數(shù)目,處理in-flight和deffered queue的消息),lookupLoop(和nsqlookupd服務器連接),statsdLoop(和stasd服務器連接)消息處理:
略,上面文章講太多了..代碼閱讀中一些疑問:
Topic創(chuàng)建時機?
在Publish時,如果不存在,會自動創(chuàng)建.Channel創(chuàng)建時機?
在Sub是,如果不存在,會自動創(chuàng)建.deferredMessages與inFlightMessages
Channel內(nèi)部維護2個隊列,infight表示正在和client交互(等到client返回FIN才刪除,保證消息至少被接收一次),deferred表示可以提前給nsqd發(fā)送message,等到時間到才合法.BackendQueue與ephemeral
如果聲明為ephemera,則如果消息超過infight隊列長度,就會被丟棄.而BackendQueue可以用go-diskqueue包提供的方法保存到文件中.消息有序性?
NSQ不保證,可能無序(requeue機制,多節(jié)點機制)丟消息?
如果異常退出,infightMsg可能會丟RDY意義:
RDY是訂閱方告知NSQD服務器自身處理能力的方法,這樣避免服務器快速給客戶端發(fā)消息,客戶端處理不過來的情況(Rx中背壓)
七. nsq-nsqlookupd
與nsqd類似,nsqlookupd通過TCP和Http兩種方式向外提供服務.
- RegistrationDB
登記nsq信息的內(nèi)存DB,使用registrationMap,ProducerMap兩層MAP,并且實現(xiàn)了add,remove,find,這些操作,便于上層進行調(diào)用. - lookup_protocol_v1
提供tcp服務,只有Ping,Identify,Register,Unregister四個方法,也就是說,只有nsqd才會使用tcp和nsqlookupd連接通訊.(Category有topic和channel,client三種) - http
提供http服務,消費者使用nsqlookupd提供的方法感知,而producer是需要直連nsqd的.
提供了"/topic/create","/topic/delete"這種,不是給nsqd用的,是給go-nsq客戶端或者nqadmin手工刪除topic用的.
八. nsq-nsqadmin
admin相對比較簡單(go部分),通過notify構造AdminAction向外主動POST,或者通過http向外提供服務.而且,它本身并不存儲任何數(shù)據(jù),需要時,都是使用httpServer中的client向nslookupd或者nsqd查詢(類似于gateway).這里用了internal/clusterinfo,先調(diào)用nslookupd,不行就直接請求nsqd(需要遍歷所有的nsqd,為了效率,還是搭建nslookupd吧).
前端頁面部分用了backdone+jquery+gulp.未看...
九. 其他
- bench目錄: 用python寫的批量測試用例
- 有贊nsq (https://github.com/youzan/nsq)
發(fā)現(xiàn)有贊Fork了一個分支,并做了改進,有機會再細看一下...