C/400

37. sendmsg/rcvmsg による理想的なクライアント/サーバー・モデル

iSeries/i5 でクライアント/サーバー・モデルを開発するときに
サーバー・デーモンは C/400によって開発されることが多い。
複数のクライアントからの要求を処理しようとすると
サーバー・デーモンは TCP/IP通信によってクライアントからの要求を
accept によって受け入れて、次に判断することは、どの子プロセスに
仕事を任せるかである。
古典的なクライアント/サーバー・モデルでは
予め、子プロセスから使用可能である子プロセスID を待ち行列から
順次に受け取って、仕事を任せる子プロセスを決定する。
子プロセスがクライアントの要求の処理が終えると、再び
親のサーバー・デーモンに待ち行列に投入して自分が使用可能であることを
通知する。

この手法は、いわゆる Apache などの HTTPサーバーにも利用される方法である。
しかし、この方法にはいくつか欠点がある。
待ち行列を介してプロセス間通信をしていることは待ち行列がいかに素早いものであっても
アクセス要求が多数に集中したときには、ひとつずつ処理されることによって
パフォーマンスの低下を招いてしまうボトルネックになるのである。
さらに親サーバー・デーモンが待ち状態のときに子プロセスのどれかひとつを強制終了させてしまうと
ストーリーは成り立たなくなってしまう。
親サーバー・デーモンは、子プロセスが生きているものと信じ込んで子プロセスからの応答を
永続的に待ち続けてしまう結果を生じるのである。
結果としてクライアントは無反応になってしまう。

この対策として適切であるのが sendmsg/rcvmsg である。
仕組みとしてまず最初にすべての子プロセスをペア・ソケットによる spawn によって生成しておき、
各子プロセスは recvmsg によって親サーバーからの指令を待機するようにしておく。
次に親サーバー・デーモンはクライアントからの要求を受け取るや否や、すべての子プロセスに
向かって sendmsg を発信する。
どの子プロセスが sendmsg によるメッセージを受け取るのかと親サーバー・デーモンには
全くわからない。
親サーバー・デーモンが sendmsg を発信すると、子プロセス達は一斉に我先にとメッセージを
受け取るように動き出す。その中でメッセージを受け取る子プロセスはただひとつだけである。
メッセージを受け取った子プロセスはクライアントの処理を開始する。
これは IBM が OS400 V5R4M0 で推奨している理想的なクライアント/サーバー・モデルである。
詳細とソース・サンプルは V5R4M0 のマニュアルで参照することができる。

【 参考 】

EnterpriseServer のHTTPサーバーである Alaska Ver4.0 も IBM 推奨に基づいて
sendmsg/recvmsg によるクライアント/サーバー・モデルにリエンジニアリングされている。