socket_set_blockソケットがブロッキングモードに設定された後、IO操作( socket_read 、 socket_writeなど)は、データの読み取りが完了するか、書き込みが成功するまで現在のプロセスまたはスレッドをブロックします。これは非常にシンプルで効果的であり、シングルスレッドまたは低電流のシナリオでは効果的ですが、高電流シナリオでは、リスクは主に次のポイントに反映されています。
閉塞はリソースの職業を引き起こします<br> ブロッキングモードにより、特にネットワークが遅延したり、ピアがゆっくりと応答したりする場合、リクエストを処理するプログラムが一瞬実行できません。プロセスはIO段階で「立ち往生」し、多数のプロセスを待機させ、リソースを占有します。
スループットの減少、応答レイテンシーの増加<br> 多数の接続がブロックされている場合、サーバーは新しい接続要求を時間内に処理できず、応答時間が長くなり、ユーザーエクスペリエンスが低下します。
スレッド/プロセスの数は制限されています<br> サーバーの並行性機能は、利用可能なスレッドまたはプロセスの数によって制限されます。ブロッキング操作により、これらのスレッドまたはプロセスが待機状態になります。これにより、スレッドプールを使い果たすのは非常に簡単です。
デッドロックリスク<BR> ブロッキングや待機中に相互に排他的なリソースの競争が関与している場合、デッドロックを引き起こし、プログラムが固執するのは簡単です。
socket_set_nonblockを呼び出してソケットを非ブロッキングモードに設定することにより、IO操作は現在のプロセスをブロックせず、すぐに戻ります。イベント駆動型メカニズム(PHP拡張の選択、投票、 libeventなど)と組み合わせることで、同時処理機能を効果的に改善できます。
<?php
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($socket, '0.0.0.0', 8080);
socket_listen($socket);
socket_set_nonblock($socket);
while (true) {
$client = @socket_accept($socket);
if ($client === false) {
// 新しい接続はありません,ループを続けます
usleep(10000); // 休憩してください,減らすCPU占有
continue;
}
// クライアントに socket また、非ブロッキングを設定します
socket_set_nonblock($client);
// データを読んだり書いたりするとき,組み合わせた socket_select リスニングステータス
}
?>
Socket_Selectは、複数のソケットの読み取りおよび書き込みステータスを聞き、単一の接続のブロックを避け、サーバーの効率を改善して複数の接続を処理できます。
<?php
$read = [$socket];
$write = null;
$except = null;
if (socket_select($read, $write, $except, 0, 200000)) {
foreach ($read as $readSocket) {
if ($readSocket === $socket) {
$client = socket_accept($socket);
socket_set_nonblock($client);
// 聞くために追加します
} else {
$data = socket_read($readSocket, 1024);
if ($data === false || $data === '') {
socket_close($readSocket);
// リストのリストから削除します
} else {
// データの処理
}
}
}
}
?>
SwooleやReactPhpなどの非同期フレームワークの助けを借りて、ブロッキングは完全に回避でき、多数の同時接続を非同期に処理し、パフォーマンスを大幅に改善できます。
<?php
use Swoole\Coroutine\Http\Server;
$server = new Server("0.0.0.0", 9501);
$server->handle('/', function ($request, $response) {
$response->end("Hello, Swoole!");
});
$server->start();
?>
マルチプロセスまたはマルチスレッドを合理的に使用して、ブロッキング操作を独立したワーカースレッドまたはプロセスに割り当てて、メインスレッドのブロックを避けます。
リスクポイント | 応答測定 |
---|---|
ブロックすると、プロセスがリソースの使用を待つことになります | 非ブロッキングモードまたはイベントドライバーを使用します |
応答レイテンシとスループットドロップ | Socket_Selectを使用して、複数の接続をリッスンします |
スレッドプールが使い果たされました | マルチスレッド/マルチプロセスプールを使用して、ストレスを共有します |
デッドロックリスク | 相互に排他的なデッドロックを避けるための合理的なリソースアクセス戦略を設計する |
高い並行性環境では、ブロッキングソケットの使用を避け、非ブロッキング、イベント駆動型モデル、非同期フレームワークを合理的に使用して、PHPプログラムの効率的で安定した操作を確保してください。