クラスター
単一のWippyノードは完結したランタイムです。クラスターは複数のノードを1つの協調システムに結合します。プロセスは任意のノードから名前で識別・到達でき、ロックやグループを通じて協調し、共有コンセンサスコアに依存できます。コードの側では、生成・送信・監督の方法を変える必要はありません。
クラスタリングはオプトイン(cluster.enabled)です。このページではコードから見えるモデルを説明します。トポロジー、設定、運用についてはクラスターガイドを参照してください。
モデル
ノードはgossip(SWIM)を通じて互いを発見します。ノードはシードを指定して参加し、メンバーシップと障害検知はコーディネーターなしに収束します。gossipの上に小さく境界が定まったRaftコアが置かれます。固定された投票者セットが線形化可能なコンセンサスを提供し、残りのフリートはgossipで動作します。ほとんどのノードはコンセンサス負荷を担わないため、クラスターはスケールアウトしつつ、必要なものに対する唯一の真実の源を維持します。
クラスターがコードに提供するものは3つの概念に集約されます:名前、ルーティング、協調プリミティブ。
命名
プロセスは通常PIDでアドレス指定されます。クラスター内では名前で登録し、どこからでもその名前で到達できます。重要な決定はスコープです。コストとのトレードオフとして、どの整合性保証を求めるかを選択します。
| スコープ | 可視範囲 | 保証 | 用途 |
|---|---|---|---|
| Local | このノード | 即時、調整なし | ノードローカルなヘルパー |
| Eventual | クラスター全体 | gossip後に収束。競合は解決され、敗者に通知される | サービス名・グループ名・限定的なプレゼンス名 |
| Consistent | クラスター全体 | Raftによる線形化可能なシングルトン | 標準的なクラスター全体の名前付きサービス |
| Strong | クラスター全体 | Consistentに加え、名前がアクティブになる前にすべてのライブノードが確認応答 | コントロールプレーンのシングルトンとロック |
スコープは整合性対コストの軸で厳密な順序を形成します。Local < Eventual < Consistent < Strong。必要な保証を満たす最も弱いスコープを選択してください。名前はprocess.registryを通じて登録され、所有プロセスが終了する(またはそのノードが離脱する)と自動的に解放されます。
ルーティング
命名は名前が確実に正しいプロセスに到達できて初めて有用です。ルーティングはその2つをつなぐものであり、いくつかの一貫したルールに従います。
- 読み取りはローカルです。 各ノードは自身のレプリカまたはgossipで配布されたキャッシュから名前を解決します。名前の解決にネットワークのラウンドトリップは不要です。これにより解決を高速に保ち、パーティション中も動作し続けます。
- 解決には固定の順序があります。 名前はプレーン順に解決されます。Consistent(Raft)、次にEventual(gossip)、次にLocal。クラスター全体の名前は同じ文字列のローカル名よりも優先されます。
- 書き込みは権威者にルーティングされます。 ConsistentまたはStrongの登録はRaftリーダーを経由します。リーダーでないノードは書き込みを転送し結果を待ちます。コミットされると、アクティブなバインディングはgossipで伝播し、Raftコアに属さないノードを含むすべてのノードがその後ローカルで名前を解決できます。
- メッセージングはPIDでルーティングされます。 名前に
process.sendすると、PIDに解決されリレーが所有ノードにメッセージを配信します。プロセスが同じノードにあっても別のノードにあっても、コードからは同じ方法でアドレス指定できます。ロケーションは透過的です。
結果として、どのノードが権威者かを意識せずに名前の登録と検索が行え、メッセージはローカルと同じ方法でクラスター全体のターゲットに到達します。
プリミティブ
クラスタリングは小さなビルディングブロックのセットを公開します。各プリミティブはそれぞれのページで詳しく説明されています。ここではそれらで何を構築できるかという概念を示します。
- メンバーシップとアイデンティティ — ライブノードのセット、このノードのアイデンティティとロール。ピアの発見や作業のシャーディングに使用します。
system.clusterとsystem.nodeを参照してください。 - コンセンサス状態 — Raftリーダー、ターム、このノードのロール。診断やリーダーを意識したロジックに使用します。
system.raftを参照してください。 - クラスター全体の名前 — スコープを指定してプロセスを名前で登録・解決します。他のすべての基盤となります。
process.registryを参照してください。 - 分散ロック — クラスター全体の相互排他。保持者は最大1つで、保持プロセスが死ぬと自動的に解放されます。
system.lockを参照してください。 - プロセスグループ — Erlangスタイルで名前付きグループに参加し、全ノードのすべてのメンバーにブロードキャストします。プロセスグループを参照してください。
これらは意図的にプリミティブです。ロックと名前付きシングルトンはStrongスコープの上に構築され、プロセスグループはgossipの上に構築され、すべてが上述の同じメンバーシップとルーティングの上にあります。そのため、それぞれが独自の分散方式を発明するのではなく、予測可能な方法で組み合わせることができます。