walkor / GatewayWorker

Distributed realtime messaging framework based on workerman.
MIT License
1.01k stars 296 forks source link

GatewayWorker 多进程长连接服务器会存在性能问题? #108

Closed twomiao closed 1 year ago

twomiao commented 1 year ago

阅读部分GatewayWorker 源码,Lib/Gateway::sendToGroup($group, $message, ...) 此接口就是把长连接进行分组。 举个例子,['群组1' => [连接1, 连接2, ...]],由于多进程Gateway 网关服务器进程都是内存隔离,每个websocket 客户端(用户)随机连接到不同Gateway网关服务器,拿上面那个例子,同一个群的成员(TCP连接)可能不在一个进程里面,这时候就需要通过广播消息给网关服所有内部TCP端口查找连接给客户端推送消息。

我的疑虑: 如果是多线程实现的长连接服务器性能是不是更好,内存共享,这样一个群成员发送一条消息业务服务器只发送一次,多进程就需要给每个进程发送一次消息。举个例子,32个Gateway进程,这时候某个群成员发消息,businessworker 会重复发送32次相同消息,如果进行分布式扩容,3台Gateway服务器,一条消息不就被转发3 * 32 = 96次。多线程就只需要转发3次消息,内网发送会存在性能问题? 逻辑多进程这样挺合理,但会存在性能问题?

源码部分:

public static function sendToGroup($group, $message, $exclude_client_id = null, $raw = false)
{
    ....... 此处省略代码
     $address_connection_array = static::clientIdArrayToAddressArray($exclude_client_id);
      // 如果有businessWorker实例,说明运行在workerman环境中,通过businessWorker中的长连接发送数据
      if (static::$businessWorker) {

          !!! 给每个进程转发一条消息 !!!!!
          foreach (static::$businessWorker->gatewayConnections as $address => $gateway_connection) {
              $gateway_data['ext_data'] = isset($address_connection_array[$address]) ?
                  json_encode(array('group'=> $group, 'exclude'=> $address_connection_array[$address])) :
                  $default_ext_data_buffer;
              /** @var TcpConnection $gateway_connection */
              $gateway_connection->send($gateway_data);
          }
      } // 运行在其它环境中,通过注册中心得到gateway地址
      else {
          $addresses = static::getAllGatewayAddressesFromRegister();
          foreach ($addresses as $address) {
              $gateway_data['ext_data'] = isset($address_connection_array[$address]) ?
                  json_encode(array('group'=> $group, 'exclude'=> $address_connection_array[$address])) :
                  $default_ext_data_buffer;
              static::sendToGateway($address, $gateway_data);
          }
      }
  }
walkor commented 1 year ago

对,多线程性能会更好,但是php本身没有多线程相关的接口。 gatewayWorker适合聊天或者物联网这种维持大量连接,但是通讯不频繁的业务。 例如聊天业务,1万人的群,每秒10条消息就刷屏了,通讯量很低,没有问题。 如果gatewayWorker需要大量的通讯,每个服务器只开一个gateway进程也可以,性能会更好。

twomiao commented 1 year ago

对,多线程性能会更好,但是php本身没有多线程相关的接口。 gatewayWorker适合聊天或者物联网这种维持大量连接,但是通讯不频繁的业务。 例如聊天业务,1万人的群,每秒10条消息就刷屏了,通讯量很低,没有问题。 如果gatewayWorker需要大量的通讯,每个服务器只开一个gateway进程也可以,性能会更好。

感谢解答疑惑! PHP 多进程服务器最适合的场景还是作为web服务器,长连接确实存在和多线程服务器性能差别。