みなさまこんにちは。
エルメスの大型ビーズクッションいいな・・・

さて、前回の記事でRaftのお話をさせていただきましたが、
今回はもう1つの技術であるSWIMについてまとめておきます。
Serfで使われているGossipProtocolはSWIMに基づいて作られており、Consul全体のクラスター管理に使われています。

以下の図の全部が繋がっている部分です。

SWIM
(Scalable Weakly-consistent Infection-style process group Membership protocol)

SWIMは、GossipProtocolの一種でSerfというソフトウェアで使われていた技術でした。
Serfは、Consulより前にHashiCorp社が出していたクラスタ管理ツールです。
Consulは、このSerfのライブラリをしようしてクラスターの管理をしています。

なお、
GossipProtocolというのは、うわさ話(Gossip)のようにノードがランダムにいつくかの隣接ノードにメッセージを伝えることを繰り返すことで全体に情報を伝達させるプロトコルです。
個々のノードがランダムな隣接ノードに情報を伝えるため、信頼性のない通信路上でも、多数のノードが耐障害性の高い情報共有を行うことができます。

主な機能としては、以下です。
– クラスターのメンバー管理
– メンバーの障害検出
– イベント伝播

この機能を実現するのによくあるのは、中央管理サーバを作ってそのサーバで管理することが考えられると思います。
全台に送る方法も考えられますが、負荷が高くなってしまいますね。
しかし、GossipProtocolの場合、そう言ったサーバは持たず、個々のノードが情報を管理しています。
よく見かけるトポロジ図で見ると、以下のような感じです。
集中型アプローチは、中央管理サーバを使って情報を集約するアプローチ
ゴシップベースアプローチは、前述でも書いている通りランダムな隣接ノードに情報を伝えることで個々のノードが情報を持つようにするアプローチ
ゴッシプはUDPで通信される。
これにより,ネットワークの容量はノードの数に比例して一定になる。
ゴシップよりも頻度は低いが、定期的にTCPによるランダムなノード間で完全な状態同期が行われる。

メンバーの障害検出

SWIMの障害検知は、決められた時間T毎にメンバー内の他のランダムなノードの死活監視を行なっています。
また、各ノードはクラスタメンバーのリストを保持しています。

この障害検知フローを表した図で以下がよく使われている。
ref: http://www.antonkharenko.com/2015/09/swim-distributed-group-membership.html
ん〜ちょっと自分なりに噛み砕いてみる。

まず、SWIMは、ランダムに選択したNodeにPingを送ることでクラスターの状態を管理しています。
このPingにはメンバシップの情報を一緒に乗せられています。

正常系

1. NodeAがランダムに選択したNode(今回はNodeE)にPingを送る
2. Ackが返ってくる
3. このPingを定期的に繰り返す

異常系

1. NodeAがランダムに選択したNode(今回はNodeE)にPingを送る
2. Ackが返って来ずTimeout
3. NodeAがN個のランダムなノードを選択し、NodeEにPingを送るようにリクエスト
4. 選択されたNodeBとDは、NodeEにPingを送る
5. NodeEからAckが返ってきたら、そのことをNodeAに通知

このN個の全てのノードからAckが返って来なかった場合、故障していると判断します。

SWIMでの改良点

GossipProtocolのSWIMからの変更点は大きく以下の3点
  • SerfはTCPで全状態の同期を行うが、SWIMは変更をGossipすることしかしない。最終的には、どちらも一貫性を持つが、Serfは状態の収束が速い。
  • SerfはGossipingのみを行うレイヤーと障害検出を行うプロトコルを分離しているが,SWIMは,障害検出にGossipingが上乗りしている.Serfは上乗りもしている.これによりSerfはより速いGossipingを可能にする.
  • Serfは落ちたノードを一定期間保持するため,全状態の同期の際にそれも伝搬される.SWIMはTCPによる状態の同期を行わない.これにより障害からの復帰が速くなる.

Serfの動作

SWIMはSerfで使われているProtocolですが、 Serfは新しいクラスタの形成、既存のクラスタへ参入のどちらかで起動する。
新しいクラスタが形成されると、そこには新しいノードが参入してくることが期待される。
既存のクラスタに参入するには、既存クラスタのメンバーのIPアドレスが必要になる。
新しいメンバーはTCPで既存クラスタのメンバーと状態が同期され、Gossiping(噂,情報のやりとり)が始まる。

Serfの状態確認

下記コマンドで確認できます
# consul members

ここなんですが、ConsulはSerfのライブラリを使っています。
そのSerfはmemberlistというライブラリを使っています。
このmemberlistは、ゴシップベースのプロトコルを使用して、クラスターメンバーシップとメンバー障害検出を管理するライブラリです。
https://godoc.org/github.com/hashicorp/memberlist

まとめ

今回は、Consulで使われているSWIMというプロトコルについてまとめさせてもらいました。
Consulは、Serfのライブラを使っており、Serfで使われているGossipProtocolはSWIMに基づいて作られており、Consul全体のクラスター管理に使われているということでした。
これにより、Consulはノードの参加や障害検知からのノードの切り離しをいい感じにやってくれている事をまとめられたかと思います。
この記事が何かのお役に立てば嬉しいです。
ではでは。