OTP23から入るpgのコードを読む
最近は久しぶりにプロダクションでErlangのコードを書いたりしています. かなり小規模な物ですが.
そこでOTP23で新しく入るpg
のコードを読む機会があったので, pg
の実装についてまとめようと思います.
pg
(Process Group) とは
Erlang Cluster内で複数のプロセスが参加するグループを作成し, そのグループの全てのプロセスに対してメッセージを送信することを目的としたものです.
そもそもpg
というモジュールは昔存在しており, このページ では以下のように書かれています.
This module is deprecated and will be removed in Erlang/OTP 18.
その代わりとしてpg2
が現れ, そしてまたpg
が帰ってきました.
といっても名称が同じなだけで全く別物であり, WhatsApp IncのMaxim Fedorovが作成したもので, spgに軽微な修正が入った物です.
pg2
は誰も使っていないと揶揄される程一般的ではないようで, gproc, synといったプロセスグループを扱えるライブラリが乱立している状態でした.
私は新しいpg
の実装は素晴らしいものだと思いましたが, 必ずしも全てのケースで優位である訳ではありません. その点に注意する必要があります.
なお, pg2
はOTP23からdeprecatedになります.
pg2 will be deprecated in OTP 23 and scheduled for removal in OTP 24.
pg
の特徴
今回入ったpg
にはいくつか特徴的な点があります.
- 自ノードのプロセス一覧は常に正しい
- 他ノードのプロセス一覧は一時的に不整合になることは許容されるが, 整合状態に戻る
- グローバルロックは取らない
- プロセスの一覧の取得は高速 (プロセス間通信を行わない / ETS)
pg
が構成するOverlay Networkの構成は定義する必要がない (adhocに変更可能)
確実にメッセージを届けられる訳ではないので, RDBのように一貫性が必要なものには適しませんが, プロセスグループが必要な多くの場合で優れているように思います. (個人の感想です)
では、実際にpg
のフローを追っていきましょう.
pg
のメッセージフロー
グループ参加 / 離脱時
ローカルのpg
プロセスに対して同期メッセージ (call
) を送信しグループに追加した後, pg
プロセスは他ノードのpg
プロセスに通知を行います.
ノード間の接続がされている限りメッセージの送信を行う (noconnect
) ので, 同期していませんが, nodedownが発生しない限り状態がそのうち更新されることが期待されています.
また, ローカルのpg
プロセスはグループに参加したプロセスをmonitor
し, DOWN
時に自動的にグループ離脱処理を行います.
nodeup / nodedown時
nodeup
が発生した場合に, discover
とsync
のメッセージでpg
プロセスはノード間で相互に状態の更新を行います.
リモートのpg
プロセスをpg
プロセスはmonitor
し, DOWN
時に自動的にそのノードのプロセスを全グループから削除する処理を行います.
DOWN
時なので, リモートのpg
プロセスが異常終了した場合も対象になります.
pg
のパフォーマンス
本来であれば自分でパフォーマンスを測定したいのですが, spg
のレポジトリに記載されている内容を引用します.
Join/leave calls are routed through local spg scope process. Local processes joined the group are monitored. When spg scope detects monitored process exit, leave message is sent to all nodes of an overlay network.
Handling remote spg scope ‘DOWN’ includes removal of all processes owned by remote node from the scope.
Join/leave operations contain originating scope process. This speeds up handling of node/scope down/up notifications. Tests were performed on a cluster of 5,000 machines, and up to 150,000 processes joining ~5,000 different groups within a single scope.
If you need to handle more groups and processes, it is advised to run multiple scopes. It is more efficient to have 10 scopes with 100 groups than 1 scope with 1000 groups, due to concurrent processing allowed when running multiple scope processes.
Relies on message ordering done by Erlang distribution. All exchanges are happening only between corresponding spg gen_server processes.
spg - Join/leave protocolより引用
5kノード, 合計15kプロセス, 5kプロセスグループでテストしているようです.
また, スコープを分割することでパフォーマンスを向上させることが可能ですが, その場合はどのスコープに割り振るかを一意に決定する必要があります.
おわりに
OTP23で新たに追加される pg
(spg
) の紹介でした.
今後利用者が増えて, パフォーマンスに関する記事が出てくることを期待したいところです.
参考文献
記事が気に入ったらチップを送ることができます!
You can give me a cup of coffee :)
Kyash ID: soranoba
Amazon: Wish List
GitHub Sponsor: github.com/sponsors/soranoba
PayPal.Me: paypal.me/soranoba
(Updated: )