淺談NATS訊息系統

語言: CN / TW / HK

我用過很多訊息系統,比如:簡單的 Redis Streams ;高效的 Kafaka 等等,不過自從我把程式語言切換到 Golang 以後,總覺得必須找個用 Golang 開發的訊息系統才配得上門當戶對,原本我已經和小家碧玉的 NSQ 廝守終生,不過當我認識了上流社會  CNCF 欽定的大家閨秀 NATS 後,剎那間就彷彿徐志摩遇到了林徽因,扭頭就給結髮妻子寫了休書。

INSTALLATION

服務端 nats-server ,客戶端 nats ,監控工具 nats-top ,效能測試工具 nats-bench

shell> go get github.com/nats-io/nats-server/v2

shell> git clone https://github.com/nats-io/natscli.git
shell> cd natscli/nats
shell> go get .

shell> go get github.com/nats-io/nats-top

shell> git clone https://github.com/nats-io/nats.go.git
shell> cd nats.go/examples/nats-bench
shell> go get .

需要說明的是,關於 stream 有新舊兩種架構的服務端實現,其中舊的 NATS Streaming Server 架構已經過時,如果你是初學者,直接使用新的 NATS JetStream 架構即可。

BENCH

開多個命令列視窗,分別啟動 nats-server,nats-top,nats-bench:

shell> nats-server -js -m 8222
shell> nats-top
shell> nats-bench -n 100000000 -np 10 -ms 1 a

nats-top

如上所示,高達一千萬的 MPS,我就問你 OK 不 OK!Beautiful 不 Beautiful!

MODE

PUBLISH SUBSCRIBE

NATS 實現了一對多釋出訂閱訊息模型。當 publisher 往 subject 上釋出一條訊息後,此 subject 上所有 subscriber 都能收到 此訊息,屬於一種廣播。

Publish Subscribe

shell> nats sub source.subject
Subscribing on source.subject
[#1] Received on "source.subject"
ZNQz8dCWc5
[#2] Received on "source.subject"
d1EggZJYVT

shell> nats sub source.subject
Subscribing on source.subject
[#1] Received on "source.subject"
ZNQz8dCWc5
[#2] Received on "source.subject"
d1EggZJYVT

shell> nats pub source.subject "{{Random 10 10}}" --count 2
Published 10 bytes to "source.subject"
Published 10 bytes to "source.subject"

QUEUE GROUPS

如果我們把 subscriber 分組,那麼當 publisher 往 subject 上釋出一條訊息後,同一組裡只有一個 subscriber 會收到此訊息,從而實現了負載均衡。

Queue Groups

shell> nats sub source.subject --queue foo
Subscribing on source.subject
[#1] Received on "source.subject"
LFuJZBjnxV

shell> nats sub source.subject --queue foo
Subscribing on source.subject
[#1] Received on "source.subject"
76kAIoUYCI

shell> nats pub source.subject "{{Random 10 10}}" --count 2
Published 10 bytes to "source.subject"
Published 10 bytes to "source.subject"

REQUEST REPLY

一般來說,訊息系統是以非同步的形式工作,也就是說,publisher 往 subject 上釋出一條訊息後,並不在意 subscriber 的 reply 是什麼。如果 publisher 在意 subscriber 的 reply 是什麼的話,那麼訊息系統就應該以同步的形式工作,在具體實現中,是通過兩次釋出訂閱來完成的:當 publisher 釋出訊息後,它會訂閱一個特定的 subject,當 subscriber 處理完訊息後,它會把 reply 釋出到這個特定的 subject。當然,整個過程對使用者是透明的。

Request Reply

shell> nats reply 'weather.>' --command "curl -s wttr.in/{{1}}?format=1"
Listening on "weather.>" in group "NATS-RPLY-22"
[#0] Received on subject "weather.beijing":

shell> nats request weather.beijing ''
Sending request on "weather.beijing"
Received on "_INBOX.7mc3ox00ma7WYWyNjuBSsw.NBtCmYbp"
:sunny: +30°C

通過 weather 例子,我們可以發現 request reply 模式已經有了 RPC 的味道。

MICROSERVICE

正是因為 NATS 具備了 RPC 的能力,所以在微服務中採用 NATS 後,系統會更清晰。

傳統微服務架構

採用 NATS 的微服務架構

說明:以上圖片來自於「 The Zen of High Performance Messaging with NATS 」。

MONITOR

說到監控,除了前面提到的 nats-top 之外,還有諸如 natsboard 之類的 UI 可供選擇:

natsboard

現實中,大家都知道,徐志摩和林徽因的結局,終究還是錯付了,不過我對 NATS 的愛不會變,她是我的不二之選,至少在更好的訊息系統出現前如此。