请求是怎么打到不同的worker进程的

yzmdd

问题描述

版主请帮忙解惑
1.我测试的是workerman
2.实例化Worker对象,schema:http,端口号9999,设置4个进程,端口复用参数默认false,设置onMessage回调,回调里面打印worker对象的id,然后启动脚本
3.在多个浏览器当中访问,chrome,Microsoft Edge里面访问,打印出来的worker对象的id不同
4.请求被不同的worker进程处理,但是没有在workerman中没看见master进程调度worker来处理请求
5.那请求是怎么打到对应的进程上的
6.因为之前我fork处理数据的时候都是在master进程将任务发给子进程,每个子进程处理部分数据,所以对于没看见master调度worker来处理请求感到困惑
7.master进程接受新的连接,代码里面没看见分发给哪个进程处理的

$worker = new \Workerman\Worker('http://0.0.0.0:9999');
$worker->count = 4;
$worker->onMessage = function (\Workerman\Connection\TcpConnection $tcpConnection,\Workerman\Protocols\Http\Request $request){
    $id = $tcpConnection->worker->id;
    $tcpConnection->send("$id");
};

以下是workerman接受连接的源码
public function acceptConnection($socket)
    {
        // Accept a connection on server socket.
        \set_error_handler(function(){});
        $new_socket = \stream_socket_accept($socket, 0, $remote_address);
        \restore_error_handler();

        // Thundering herd.
        if (!$new_socket) {
            return;
        }

        // TcpConnection.
        $connection                         = new TcpConnection($new_socket, $remote_address);
        $this->connections[$connection->id] = $connection;
        $connection->worker                 = $this;
        $connection->protocol               = $this->protocol;
        $connection->transport              = $this->transport;
        $connection->onMessage              = $this->onMessage;
        $connection->onClose                = $this->onClose;
        $connection->onError                = $this->onError;
        $connection->onBufferDrain          = $this->onBufferDrain;
        $connection->onBufferFull           = $this->onBufferFull;

        // Try to emit onConnect callback.
        if ($this->onConnect) {
            try {
                \call_user_func($this->onConnect, $connection);
            } catch (\Exception $e) {
                static::stopAll(250, $e);
            } catch (\Error $e) {
                static::stopAll(250, $e);
            }
        }
    }
546 1 0
1个回答

yzmdd

我刚刚测试了,只设置两个进程,然后其中一个在onMessage回调里面fclose _mainSocket (我把protected 改成了public) ,然后其中一个进程就不能接受连接了,但是另外一个还能接受请求;说明fork的时候_mainSocket被深拷贝了一份,这与我以往理解的不太一样,我一直以为fork的话对应source类型的是浅拷贝,这是因为在yii2使用fork多个进程然后其中一个进程退出了mysql链接对象被释放了,其他的进程用不了那个连接对象了,造成了这么个误区。反过来想如果其中一个worker挂了,如果没有深拷贝_mainSocket那么其他的进程也不能接受新的连接了;这样每个进程都有自己的_mainSocket来负责接收连接,所以不存在master进程接收到连接然后再分配给worker进程处理对应的请求,其实就是哪个进程建立连接哪个请求处理。至于哪个请求打到哪个worker进程上,那是操作系统的调度了

  • chaz6chez 2022-11-25

    mysql的连接作为的是客户端连接,和作为服务端的连接在处理上是不同的,socket server在这个情况下是交给系统内核来进行处理分配的,如果仅仅是浅拷贝,达不到这个效果,毕竟是不同进程

  • yzmdd 2022-11-25

    感谢

年代过于久远,无法发表回答
🔝