socket_set_block After socket is set to blocking mode, IO operations (such as socket_read , socket_write ) will block the current process or thread until the data read is completed or the write is successful. This is very simple and effective in single-threaded or low-concurrency scenarios, but in high-concurrency scenarios, the risks are mainly reflected in the following points:
Blockage causes resource occupation <br> The blocking mode will make the program that handles a request unable to continue execution for a moment, especially when the network is delayed or the peer responds slowly, the process will "stuck" in the IO stage, causing a large number of processes to wait and resources to be occupied.
Decreased throughput, increased response latency <br> When a large number of connections are blocked, the server cannot process new connection requests in time, resulting in a longer response time and a worse user experience.
The number of threads/processes is limited <br> The concurrency capability of the server is limited by the number of available threads or processes. Blocking operations make these threads or processes in a waiting state, which is very easy to cause the thread pool to be exhausted.
Deadlock risk <br> If competition for mutually exclusive resources is involved during blocking and waiting, it is easy to cause deadlocks and cause program stuck.
By calling socket_set_nonblock to set socket to non-blocking mode, IO operations will not block the current process, but will return immediately. Combined with event-driven mechanisms (such as select , poll , or libevent in PHP extensions) can effectively improve concurrent processing capabilities.
<?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) {
// No new connection,Continue the loop
usleep(10000); // Have a break,reduceCPUOccupancy
continue;
}
// To the client socket Also set non-blocking
socket_set_nonblock($client);
// When reading or writing data,Combined socket_select Listening status
}
?>
socket_select can listen to the read and write status of multiple sockets, avoid blocking a single connection, and improve the efficiency of the server to process multiple connections.
<?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);
// Add to Listen
} else {
$data = socket_read($readSocket, 1024);
if ($data === false || $data === '') {
socket_close($readSocket);
// Remove from the List of List
} else {
// Processing data
}
}
}
}
?>
With the help of asynchronous frameworks such as Swoole and ReactPHP, blocking can be completely avoided, and a large number of concurrent connections can be processed asynchronously, greatly improving performance.
<?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();
?>
Use multi-process or multi-threading reasonably to assign blocking operations to independent worker threads or processes to avoid blocking of the main thread.
Risk points | Response measures |
---|---|
Blocking causes the process to wait for resource usage | Use non-blocking mode or event driver |
Response latency and throughput drop | Use socket_select to listen for multiple connections |
Thread pool exhausted | Use multi-threaded/multi-process pools to share stress |
Deadlock risk | Design a reasonable resource access strategy to avoid mutually exclusive deadlocks |
In a high concurrency environment, try to avoid using blocking sockets and make rational use of non-blocking, event-driven models and asynchronous frameworks to ensure the efficient and stable operation of PHP programs.