16

私はApacheのMPMプリフォークサーバーでモデル化されたいくつかのPythonコードに取り組んでいます。私はネットワークプログラマーというよりもアプリケーションプログラマーであり、スティーブンスを読んでから10年が経ちました。そのため、コードの理解に慣れようとしています。

Sander Temmeによる、Apacheのプリフォークコードがどのように機能するかについての簡単な説明を見つけました。

通常rootとして実行される親プロセスは、ソケット(通常はポート80または443)にバインドします。ソケットのオープンファイル記述子を継承する子を生成し、uidとgidを非特権ユーザーとグループに変更します。子は、リスナーファイル記述子のポーリングセットを作成し(複数のリスナーがある場合)、その上でのアクティビティを監視します。アクティビティが見つかった場合、子はアクティブなソケットでaccept()を呼び出し、接続を処理します。それが完了すると、ポーリングセット(またはリスナーファイル記述子)の監視に戻ります。

複数の子がアクティブであり、それらはすべて同じソケットファイル記述子を継承しているため、同じポーリングセットを監視します。ミューテックスを受け入れると、実際にポーリングセットを監視できるのは1人の子だけになり、アクティブなソケットが見つかると、ミューテックスのロックが解除され、次の子がポーリングセットの監視を開始できるようになります。リスナーが1つしかない場合、そのaccept mutexは使用されず、すべての子がaccept()でハングします。

これは私が見ているコードの動作とほぼ同じですが、いくつかのことを理解していません。

1)「子供」と「リスナー」の違いは何ですか?私が見ているコードには、それぞれの子がリスナーであると思いましたが、Temmeの説明では、「単一のリスナー」と「子」が存在する可能性があります。子供にはいつ複数のリスナーがいますか?

2)(1に関連)これはプロセスごとのミューテックスですか、それともシステムミューテックスですか?さらに言えば、なぜミューテックスがあるのですか?accept(2)は、すべてのリスナーにわたって独自のミューテックスを実行しませんか?私の調査によると、ミューテックスが必要であり、ミューテックスはシステム全体に存在する必要があります。(群れ、セマフォなど)

Temmeは続けて次のように述べています。

子供は、最後にリクエストを処理したときに共有メモリ領域(スコアボード)に記録します。MaxSpareServersを満たすために、アイドル状態の子が親プロセスによって強制終了される場合があります。アイドル状態の子が少なすぎる場合、親はMinSpareServersを満たすために子を生成します。

3)この実装(できればPython)に適したリファレンスコードはありますか?PerlのNet::Server :: Preforkを見つけました。これは、スコアボードに共有メモリの代わりにパイプを使用します。ランダル・シュワルツの記事を見つけました。これは、プリフォークのみを実行し、スコアボードは実行しません。

Perl Cookbookのpre-forkの例には、selectに関するロックはありません。また、Chris SiebenmannのPythonの例では、Apacheに基づいていますが、共有メモリではなくスコアボードにペアのソケットを使用し、コントロールにソケットを使用しています。与えられた子を'a'cceptに制御します。これは、Apacheの説明とはまったく一致しません。

4

1 に答える 1

16

(1) に関しては、リスナーは、接続を受け入れるソケットの存在への単なる参照です。Apache は同時に複数のソケット (80/443 など) で接続を受け入れることができるため、複数のリスナー ソケットが存在します。各子プロセスは、必要なときにこれらすべてのソケットをリッスンする必要があります。accept() は一度に 1 つのソケットでしか実行できないため、その前に poll/select があるため、どのリスナー ソケットで受け入れを実行する必要があるかがわかります。

(2)に関しては、グローバルまたはクロスプロセスミューテックスです。つまり、1 つのプロセスがそれをロックすると、同じロックを取得しようとする他のプロセスがブロックされます。accept() は技術的にプロセスをシリアル化しますが、複数のリスナーソケットが存在するということは、どのソケットで受け入れを実行するかを事前に知らないため、それに依存できないことを意味します。単一のリスナー ソケットであっても、受け入れミューテックスの理由は、要求を処理するプロセスが多数ある場合、オペレーティング システムがすべてのプロセスを起動して、accept() が返されるプロセスを確認すると、非常にコストがかかる可能性があるためです。prefork モードの Apache には 100 以上のプロセスがある可能性があるため、問題が発生する可能性があります。

したがって、リスナー ソケットが 1 つしかなく、accept() 呼び出しを実行したいプロセスが少数しかないことがわかっている場合は、クロス プロセスの受け入れミューテックスを廃止できる可能性があります。

于 2009-10-18T22:32:47.937 に答える