Serf:Gossip Protocol


Serf使用Gossip Protocol來廣播消息到集群中。本文介紹這個內部協議的細節。gossip協議基於“SWIM: Scalable Weakly-consistent Infection-style Process Group Membership Protocol”,有一寫小的適配,很大程度上增加了傳播速度和收斂速率。

SWIM Protocol Overview

  Serf以加入一個已存在的集群或者啟動一個新集群開始。如果啟動一個新集群,其他節點則會加入它。為了加入現有集群,新節點必須至少分配一個已經存在的節點的地址。新的成員與現有成員通過TCP做一個完整的狀態同步並且開始gossip它的存在到集群中。

  Gossip基於UDP並且具有一個可配但是固定的扇出(fanout)和間隔。這保證網絡資源使用是固定的,不論節點數有多少。通過TCP隨機的與一個節點周期的進行完整狀態交換,但是遠遠少於gossip消息。全狀態交換和合並會增加成員關系列表收斂的可能性。全狀態交換的間隔是可配的或者完全停止。

  故障檢測通過可配間隔的周期性的隨機探測實現。如果節點在一個響應時間內(通常是RTT時間的倍數)沒有進行ack,會嘗試間接探測。間接探測要求可配數量的節點來探測相同的節點,以防網絡問題導致我們的節點探測失敗。如果我們的探測和間接探測都在響應時間內失敗,則該節點被標記為“suspicious”並且會被gossip到集群中。一個可疑節點仍然視為集群的成員。如果集群的可以節點在一個可配的周期時間內對懷疑沒有爭論,則節點最終被認為死亡,這個狀態被gossip到集群中。

  這是對協議的一個簡短和不完整的描述。更好的方式是完整閱讀 SWIM論文和Serf的源代碼。

SWIM Modifications

  如前所述,gossip協議基於SWIM,但是包含小的變化,很大程度上增加了傳播速度和收斂速率。

  SWIM的變化都記錄在這:

  • Serf通過TCP定期的做完整狀態同步。SWIM只通過gossip傳遞消息。雖然最終都是一致的,但是Serf可以更快速的收斂,以及優雅的從網絡分區中恢復。
  • Serf有一個從故障檢測協議分離出來的gossip層。SWIM只通過在probe/ack消息上附帶gossip消息。Serf基於專用的gossip消息傳遞。這個特征允許你有一個更高的gossip速率(例如200ms一次)和更低的故障檢測速率(例如每秒一次),使得整體更快的收斂速率和數據傳播速度。
  • Serf保持死亡節點設置為死亡的時間,所以當完整的同步請求時,請求者也接收死亡節點的信息。因為SWIM不做完整同步,並且SWIM一旦知道節點死亡則立即刪除節點狀態。這個改變再一次幫助集群收斂更快。

Lifeguard Enhancements

  SWIM假設本地節點是健康的,也就是說可以軟實時處理數據包是可能的。然而,在本地節點正在經歷CPU或者網絡資源耗盡的情況下,這個假設就不成立了。結果是會導致節點健康偶爾振動,導致錯誤的監控報警,增加遙測噪聲,並且直接導致整個集群浪費CPU和網絡資源來診斷一個可能並不存在的故障。

  Serf 0.8版本添加了Lifeguard,它完全解決了這個問題通過增強SWIM。

  第一個擴展是引入了“nack”消息來探測查詢。 If the probing node realizes it is missing "nack" messages then it becomes aware that it may be degraded and slows down its failure detector. As nack messages begin arriving, the failure detector is sped back up.

  第二個變化是引入了在聲明另一個結點故障之前動態改變懷疑超時時間的功能。探測結點初始化時有一個很長的懷疑超時。只有集群中的其他節點確認一個節點是可以的,計時器加速。在正常操作期間檢測時間實際上與早期版本的Serf一樣。然而,如果一個節點被退化,並且沒有得到確認,則會有一個很長的超時時間來允許被懷疑的節點來反駁它的狀態並且保持健康。

  這兩個機制聯合使得Serf對於集群中退化的節點更加健壯,同時保持故障檢測性能不變。Lifeguard沒有額外的配置,它自動調節。

Serf-Specific Messages

  在基於SWIM的gossip層上,Serf發送一些自定義的消息類型。

  Serf大量使用Lamport clocks來維護消息的順序,雖然最終是一致的。每個由Serf發出的消息都包含一個Lamport clock時間。

  當一個節點優雅的離開集群時,Serf通過gossip層發送一個leave intent。因為gossip層以下不區分節點離開集群和一個節點被檢測為故障的,這允許更高級別的Serf層來檢測故障與優雅的離開。

  當一個節點加入集群時,Serf發送一個join intent。這個意圖的目的僅僅是綁定一個Lamport clock時間到join上使得在leave亂序來臨時,join可以被正確的排序。

  對於自定義的事件和查詢,Serf發送user event或者user query消息。這個消息包含Lamport時間,事件名稱和事件負載。因為user event是沿着使用UDP的gossip層發送,負載和整個消息幀必須滿足在單個UDP包內


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM