3

PHPソケット拡張機能(基本的には関連するLinuxシステムコールのラッパー)を使用してsocket(2)おり、後続のリクエストで1つのリクエストを処理しているときに開いたソケットを再利用したいと考えています。パフォーマンスは重要な要素です。

私が開いているソケットはすべて同じIPであるため、他の機能を使用pfsockopen()できなくなり(毎回同じ単一のソケットを再利用するため)、一度に複数のソケットが必要になります。

質問

あるリクエストを処理するために開いたソケットを意図的に開いたままにして(またはを呼び出さsocket_close()ないsocket_shutdown())、まったく同じパラメーターを持つソケットを次のリクエストを処理する同じIPに接続します。Linuxは以前に開いたソケット/ファイル記述子を再利用しますか?

私が最後にやりたいのは、すべてのリクエストでTCPハンドシェイクを回避することです。

追加情報

  • 私はapacheワーカーMPMを使用しています。つまり、異なる要求が異なるプロセスから提供される可能性がありますが、必ずしも提供されるとは限りません。簡単にするために、すべてのリクエストが同じプロセスから提供されると仮定しましょう。

  • PHPで開いて接続されているソケットのファイル記述子IDを取得できます。開いたり、読み書きしたりすることはできますが/dev/fd/{$id}、目的はありません。リモートサーバーと通信していません(これは単純なアプローチかもしれません)。誰かがこの仕事をする方法を知っていれば、私はそれも受け入れられる答えだと思います。

4

3 に答える 3

5

同じプロセスでソケットを再利用したい場合は、単に接続を開いたままにします。それが実際には、TCP ハンドシェイクを回避する唯一のオプションです。キープアライブがオンになっていることを確認します。

s.setsockopt( socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)

新しいプロセスを生成してそれらに接続を渡したい場合、はい、書き込みが可能になり/dev/fd/{$id}、ネットワーク経由でデータが送信されます。exec 中にソケットが閉じられていないことを確認してください (詳細については、 を参照してSOCK_CLOEXECください)。

無関係なプロセスにソケットを渡すことはできません。それを達成するには、何らかの形式のプロセス間通信を使用する必要があり、イントラネットまたはインターネットの条件での TCP ハンドシェイクのオーバーヘッドが、それに関連する複雑さとその他のオーバーヘッドを正当化するのに十分かどうかはわかりません。

于 2012-06-19T21:05:14.440 に答える
0

ソケットを開いたままにして、1つの要求を意図的に開いたままにして(socket_close()またはsocket_shutdown()を呼び出さない)、まったく同じパラメーターを持つソケットを次の要求を処理する同じIPに接続します。Linuxは以前に開いたソケット/ファイル記述子を再利用しますか?

いいえ。ただし、同じプロセスを使用している場合は、いつでも元のファイルを使用できます。あなたが話しているのは、実際には接続プールです。

于 2012-06-19T21:43:52.940 に答える
0

Jirka Hanikaによる回答はほとんどのシステムで正しいものですが、残念ながら PHP には当てはまらないという結論に達しました。PHPソケット拡張機能を使用したソケットの再利用は、ユーザー空間からは実現できません。

この結論に至ったコードは次のとおりです。

function statDescriptors() {
    foreach (glob('/proc/self/fd/*') as $sFile) {
        $r = realpath($sFile);
        // ignore local file descriptors
        if($r === false) {
            echo `stat {$sFile}`, "\n";
        }
    }       
}

header('Content-Type: text/plain');

statDescriptors();

$oSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_option($oSocket, SOL_SOCKET, SO_KEEPALIVE, 1);
socket_set_option($oSocket, SOL_SOCKET, SO_REUSEADDR, 1);

socket_connect($oSocket, '173.194.35.33', 80); // Google IP

socket_write($oSocket, 'GET / HTTP/1.0' . "\r\n");
socket_write($oSocket, 'Connection: Keep-Alive' . "\r\n\r\n");

socket_read($oSocket, 1024 * 8);

// socket_close($oSocket); // toggle this line comment during test

echo 'PID is: ', getmypid(), "\n";

statDescriptors();

このコードはstat()、その実行の開始時と終了時に、現在のプロセスのソケット ファイル記述子を開きます。その間に、set でソケットを開き、SO_KEEPALIVEそれにリクエストを書き込み、レスポンスを読み取ります。次に、オプションでソケットを閉じ (行コメントを切り替え)、現在のプロセスの PID をエコーし​​ます (同じプロセスにいることを確認するため)。

ソケットを閉じるかどうかに関係なく、前の要求を処理するために作成されたファイル記述子は、このサイクルの実行の開始時に存在しなくなり、完全に新しいソケットが作成されて接続されることがわかります。

SOCK_CLOEXEC拡張機能には (まだ?) 実装されていないため、テストできませんでした。

(これは PHP 5.4.0 を使用してテストされました)

于 2012-06-20T18:44:31.260 に答える