Home  >  Article  >  PHP Framework  >  The attribute reusePort in Workerman that you have to know

The attribute reusePort in Workerman that you have to know

醉折花枝作酒筹
醉折花枝作酒筹Original
2021-07-23 16:01:352982browse

Workerman is an open source, high-performance asynchronous PHP socket framework developed purely in PHP. Supports TCP long connections and many protocols such as websocket and MQTT. Today we will introduce the reusePort attribute in Workerman. You can refer to it if necessary.

The attribute reusePort in Workerman that you have to know

Workerman is a high-performance PHP Socket server framework. You can use Workerman to program directly at the TCP layer. The basic programming routine is:

$w = new Workerman\Worker('tcp://0.0.0.0:80');
$w->count = 4;
$w->onMessage = function(Workerman\COnnection\TcpConnection $connection, array $data) {
    $connection->send('Hello World');
};
Worker::runAll();

During the use process, I wonder if you have paid attention to the reusePort parameter. It is set to # by default. ##false. What is the use of this parameter? Under what circumstances do we need to set it to true to improve performance?

1. The role of reuseport

Regarding the reusePort parameter, Workerman’s official document explains it this way:

Allows multiple unrelated people after turning on listening port reuse Related processes listen to the same port, and the system kernel performs load balancing and determines which process to hand over the socket connection for processing. This avoids the thundering herd effect and improves the performance of multi-process short connection applications.

If you have not studied Linux network programming in depth, it is difficult to understand this sentence. Here is a brief explanation:

The server program usually receives client requests by listening to a certain port number on the server. In Linux, the server network card port number is abstracted into a

Socket.

In order to improve performance, general server programs have multiple processes (commonly known as

Worker) listening to the same Socket when running. When no client connection comes, these Workers are In the suspended state, no CPU resources are consumed.

If a client connection arrives at a certain moment, the Linux kernel will wake up these Workers at the same time and let them compete to handle the connection.

As a result, only one Worker will get the chance to handle the connection. , other Workers continue to return to the suspended state after the competition fails. The process of waking up a Worker consumes CPU resources. The greater the number of Workers, the more CPU resources are consumed, resulting in a waste of resources. This is often referred to as the

Shocking Herd Effect.

You may ask: Why not only wake up one Worker at a time? Unfortunately, the Linux kernel does not have such a feature.

Fortunately, in Linux 3.9 and later versions, the reuseport feature is added. What is the use of this feature?

Before reuseport, a port number could only be monitored by one Socket. With reuseport, this restriction is broken: a port number can be monitored by multiple Sockets at the same time.

As mentioned earlier, the Linux kernel cannot wake up only one Worker at a time, but the kernel can evenly send client connections to a group of Sockets listening on the same port.

As shown in the figure, each Worker has its own Socket, all listening on the same port. When a client connection arrives, the kernel forwards the connection to a Socket, and this Socket will only wake up the Worker to which it belongs. This cleverly solves the

Thundering Herd Effect and improves the overall performance.

From this, we can conclude: If your Linux kernel version is 3.9 and above, then when using Workerman, you can set reusePort to true to improve program running efficiency.

2. How Workerman uses reuseport

Although you only need to set reusePort to

true in Workerman, you can enjoy this advanced feature of Linux. But in Workerman's source code, it's not just as simple as turning on a kernel parameter. Workerman hides a lot of design details for you, let’s take a look. The

Worker class is the most important class in Workerman, among which there is a listen() function:

protected function listen()
{
    ...
    if (!$this->_mainSocket) {
        ...
        $this->_mainSocket = stream_socket_server(...);
        ...
    }
    ...
}

listen() The function of the function is to create a Socket in the current process and start listening for requests.

When reusePort is

false, the main process calls the listen() function before creating the Worker:

protected function initWorkers() {
    ....
    if (!$worker->reusePort) {
        $worker->listen();
    }
    ....
}

Then the main process passes pcntl_fork () Create Worker. pcntl_fork() has a feature: the variables in the created child process (Worker) are copied from the parent process, including the mainSocket created by the parent process. Therefore, when reusePort is **false**, all Workers copy the mainSocket of the parent process. Therefore, when reusePort is ∗∗false∗∗, all Workers copy the _mainSocket of the parent process, that is, share one Socket.

When reusePort is

true, the situation is different. The main process will not call listen() before creating a Worker. Instead, after creating a Worker, each Worker will initiate a listen() call:

protected static function forkOneWorkerForLinux($worker) {
    ...
    $pid = pcntl_fork();
    if ($pid === 0) {
        if ($worker->reusePort) {
            $worker->listen();
        }
        ...
    }
    ...
}

The result is that each child process (Worker) creates its own Socket.

Finally, if you want the kernel to enable the reuseport function, you need to manually set the Socket context:

if ($this->reusePort) {
    $context = stream_context_create();
    stream_context_set_option($context, 'socket', 'so_reuseport', 1);
}

推荐学习:php视频教程

The above is the detailed content of The attribute reusePort in Workerman that you have to know. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn