iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
1
Software Development

服務開發雜談系列 第 22

NATS & NATS Streaming介紹

  • 分享至 

  • xImage
  •  

NATS

NATS是由CloudFoundry團隊開發的一個開源、輕量、高性能.
支持Publisher-Subscriber模式的分布式MQ系統, 可以實現約150萬/s的吞吐量.

NATS就昨天提的MQ服務, 主要是提供application和services之間的訊息交換.
讓彼此不需要知道彼此的網路位子, 這樣就提供了一個抽象層在application或service與實體網路之間.

服務只要知道MQ的URL連接到NATS服務上, 透過Publisher-Subscriber模式, 簡單易懂的設計, 讓開發者能簡易使用.

觀察者模式

觀察者模式是這樣定義的,

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

裡面有提到一個單字Subject, 這詞講的是一個對象, 它是"被觀察者".
這個Subject對象會維護著所有的Observers(觀察者), 並且notify by特定event.

生活案例:
公司有HR招聘經理, 這裡有一群求職者, 我們都給了HR履歷跟聯繫電話,
只要公司有空缺, HR會通知有興趣的候選人.
當然候選人如果答應, 就會進行面試.
這情境內, 公司就是Subject, 維護著Observers清單, 並且有空缺時(Event), 根據職位內容, 去Notify適合的候選人.

在這個情境(Conetext)下, 我們只有一個Subject.

Publisher-Subscriber模式

Publish-Subscribe模式(以下簡稱Pub/Sub), 提供了1對多的訊息分佈方式.
聽起來跟觀察者模式很相似對吧?
這個1對多指的不是只有一個具體的Subject.
在這模式下, Publisher就是觀察者中的Subject, 所有的Observer就是Subscriber.
主要區別在, Publisher並不會指定要送給哪些誰, 代碼內也不會有這些邏輯.
這就意味著兩方彼此不了解彼此的存在.
因為這裡面還有一個叫做Broker的代理, 夾在兩人之中, 就上面提及的抽象層. 它會根據Topic或者是訊息內容, 來決定把訊息發布給哪些Subscriber.
所以上面指的1對多, 就是講這publisher可以把訊息發給很多Topic上.


這圖就很好解釋場景了, Publisher X負責發送處理一些訊息發給TopicA&B(可能是好友上線下線通知), Publisher Y可能就是公告訊息的發布.

Topic A&B可以說是某兩個聊天室群組, Subscriber 1+2是某用戶, 它們關注這聊天室的任何事件, Subscriber2+3關注另一個聊天室.
三個也都關注著公告.

Publisher也完全跟Subscriber隔離, 可以彼此擴展組合.

參考:
發行者-訂閱者模式.

Message quality of service (QOS)

訊息的投遞保證, 有分成幾個等級
QOS 0 -> At Most Once
QOS 1 -> At Least Once
QOS 2 -> Exactly Once

At Most One

Publisher若是選擇QOS0, 則表示發送出訊息後, 訊息會被最多傳遞0-1次.
Subscriber若是選擇QOS0, 則MQ只要投遞給任意Subscriber, 就會把該訊息從MQ內丟棄.
這類設定, 通常用在不在意狀態一致性的情境上(Mail? 笑).
又或者是debug log.

At Least One(至少一次)

QOS1 通常是透過log(WAL, 前面提過)或任意的持久化方式來保證.
Publisher若是選擇QOS1, 就Publisher要等待MQ把資料寫到持久化的佇列上.
一旦失敗, 就Publisher自己handler囉, 反正會返回Error.
Subscriber若是選擇QOS1, 就必須回Ack給MQ, 它才會從持久化的佇列中刪除該訊息.
一旦失敗, MQ就會嘗試重新投遞.

這個模式最常被採用, 分析一下為什麼要最少一次?
就是希望這訊息成本的被完成處理至少一次, 這就表示服務本身要有辦法去重.
因為這模式下, 通常還是會設置一段時間該訊息沒被ack, MQ會把該訊息再次投遞; 但也許收到訊息的consumer只是處理的慢, 最終還是成功了.

大部分場景, 都希望請求都有被完整的處理, 不允許任何請求沒被處理就被彈指消失了.

Exactly Once

就為了防止上面的會發生請求被多次重複消費的問題...
Al least once + 冪等 = Exactly Once

這模式不是什麼MQ都有支持, Kafka是有支持中的其一; 因為這個要實現的代價頗高, 等於就是保證強一致性, 之前有提過這對於吞吐量是硬傷.

Publisher設定跟上面一次, 就要等MQ收到有回應就可.
主要是Consumer, Kafka主要也是內部產生一個TransactionlId, 來處理冪等寫入. 並且搭配Zookeeper, 來紀錄Consumer對於訊息的offset, 只要Counsumer沒有commit該訊息, 下次讀取的位子也會是最後一次commit之後的位置.

講這麼多XD
NATS到底是支援什麼?
NATS Server本身支援QOS0.
NATS Streaming 支援QOS1...
很暈我知道@@"

NATS Server & NATS Streaming

NATS Server與NATS Streaming的關係就像下圖

NAT Streaming以類似Sidecar服務的形式服務於NATS Server.
所以可以獨立佈署.

因為NATS Server只處理Publish-Subscribe, 並沒有持久化的動作, 沒法滿足QOS1.
所以透過Streaming module, 做持久化的動作和Ack, 滿足QOS1.
也因為有持久化了, 可以從指定的offset位子開始訂閱消費或是Replay.

NATS還能設定Publisher rate limiting, 透過MaxPubAcksInFlight.
能限制一個Publisher只要還沒Ack的發送數量到達這配置時, Publisher就會被阻塞, 直到Non-Ack Pub Message數量降到這配置數量以下.

NATS也可以對Subscriber做rate limiting, 透過MaxInFlight, 就能限制一個Subscriber的Non-Ack訊息也是達到這配置時, NATS Server將暫停分發訊息給它, 直到Non-Ack數量降到這配置數量以下為止.

NATS Streaming叢集也是採用Raft演算法來達成資料的複製同步, 官方也是建議叢集採用奇數(3or5個節點).


上一篇
Message Queue 訊息隊列淺談
下一篇
NATS & NATS Streaming 叢集安裝 By Docker Compose
系列文
服務開發雜談33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言