7.2. クライアント接続の管理

受け付けるクライアント接続数が増えると、新しい接続を受け付けるPgpool-II子プロセスの数は減少し、ついには0になります。 こうなると、子プロセスの一つが空くまでクライアントは待たされます。 高負荷状況では、待機状態の待ち行列が長くなり、ついにはシステム設定の上限を超えてしまいます("535 times the listen queue of a socket overflowed" エラーをご覧になったことがあるかも知れません)。 この場合、待ち行列の制限を大きくする必要があります。 この問題に対処するための方法がいくつかあります。

7.2.1. num_init_childrenの調整

この問題に対処するための明らかな方法は、子プロセスの数を増やすことです。 num_init_childrenを調整することにより、これは可能です。 しかし、子プロセスを増やすと。より多くのCPU、メモリリソースが必要になります。 また、ひとたび子プロセスの数がmax_connectionsを超えると、PostgreSQLは接続を受け付けなくなり、フェイルオーバが起きるきっかけになるので、PostgreSQLのmax_connectionsパラメータについては非常に慎重に検討する必要があります。

num_init_childrenを増やすもう一つの欠点は、「大規模な群れ問題(thundering herd problem)」です。 新しい接続要求が到達すると、カーネルはaccept()システムコールを発行するために休眠中のプロセスをすべて起こします。 これはプロセス同士がソケットを奪い合うきっかけとなり、システムに高負荷を与えます。 serialize_acceptをonにすることにより、接続を受け付けるソケットを確保するプロセスをひとつだけにすることができます。 ただし、この方法では、同時に接続するクライアント数が少ない時に、性能が低下する可能性があることに注意してください

Pgpool-II 4.4以降では、process_management_modeを使ってより効果的な対処が可能です。 process-management-modedynamicにすることにより、同時に接続するクライアント数が少ない時にはPgpool-IIの子プロセスの数を削減し、システムのリソースの消費を抑えます。 一方、同時に接続するクライアント数が増えてくると、必要に応じて子プロセスの数を増やすので、増大する接続要求にも応えられます。 ただし、子プロセスを増やすには新たなプロセスの起動が必要となり、接続に要する時間が増えることに留意してください。

process-management-modeについては、項3.3.3もご覧ください。

7.2.2. listen_backlog_multiplierの制御

別な解決方法は、接続要求待ち行列を長くすることです。 listen_backlog_multiplierを大きくすることによりこれは可能です。

7.2.3. どのような時にreserved_connectionsを使うべきか

しかし、上記の方法では待ち行列が満杯にならないことを保証することはできません。 クエリを処理する速度を上回ってクライアントからの接続要求が到達すれば、いつかは待ち行列が満杯になります。 たとえば、処理に時間を要する重いクエリがあると、容易にこの問題の引き金になります。

解決方法は、reserved_connectionsを使って、すでにPostgreSQLが行っているように、溢れてしまうような接続要求は拒否することです。 これはアプリケーションから見える"Sorry max_connections already"エラーを起こすので、アプリケーションは処理を再実行する必要があります。 ですから、この方法はシステムの負荷を事前に予測できないときにだけ使用するべきです。