项目作者: devweyes

项目描述 :
swoft集群版websocket
高级语言: PHP
项目地址: git://github.com/devweyes/swoft-ws-server-cluster.git
创建时间: 2020-01-07T10:11:02Z
项目社区:https://github.com/devweyes/swoft-ws-server-cluster

开源协议:Apache License 2.0

下载


swoft websocket cluster

1. 介绍

基于swoole websocket server的swoft websocket已经很方便的开箱即用,但其无法直接支持多机器集场。

本组件可支持大多数web推送场景,IM互聊场景,IM群发场景等。

使用前请通读Swot webdocket Server文档,配置习惯与其并无任何变化。

流程请参见下图

avatar

  • ① 客户端发起握手请求并建立连接
  • ② 当前服务端向资源管理State注册并绑定当前用户信息
  • ③ 服务端A向服务B所在消息队列推送消息
  • ④ 服务端B消费消息并接收
  • ⑤ 服务端B向客户端推送消息

2. 特性

  • 高性能,水平扩容
  • 高可用,所有机器都为master,相互心跳检测
  • 消息队列与状态管理均采用适配器模式,默认均为redis驱动,拓展性强
  • 事件均采用Aop切面技术,无感知,解耦
  • 与原Swoft Webdocket使用起来基本一致,习惯保持

3. 安装

composer

  1. composer require devweyes/ws-server-cluster

redis

默认使用redis内存服务器作为状态保存,消息队列。所以你还需至少一台redis服务器或集群

4. 使用

基本使用

使用命令,WsModule消息控制器消息解析器 请参见Swot webdocket Server文档

一个完整的WsModule需配置全部已知方法注解,用于实现切面。包括@OnHandshake().@OnOpen().@OnMessage().@OnClose() ,@OnMessage()可由消息控制器代替,否则可能无法正常使用。

集群配置

默认配置,如需自定义可覆盖。

  1. <?php
  2. return [
  3. Cluster::MANAGER => [ //主配置
  4. 'class' => ClusterManager::class,
  5. 'state' => bean(Cluster::STATE), //状态选择
  6. 'onHandshakeMiddleware' => [ //握手阶段中间键
  7. bean(DefaultAllowMiddleware::class)
  8. ],
  9. 'onOpenMiddleware' => [ //onOpen阶段中间键
  10. bean(DefaultAuthMiddleware::class)
  11. ],
  12. 'heartbeat' => 60 //服务器心跳检测,相互检测
  13. ],
  14. Cluster::STATE => [ //状态保存配置
  15. 'class' => RedisState::class,
  16. 'redis' => bean('redis.pool'),
  17. 'serializer' => bean(Cluster::SERIALIZER),
  18. 'prefix' => 'swoft_ws_server_cluster',
  19. ],
  20. Cluster::SERIALIZER => [ //序列化配置
  21. 'class' => PhpSerializer::class
  22. ]
  23. ];

bean.php添加异步进程消息处理

  1. <?php
  2. use Jcsp\WsCluster\Helper\Tool;
  3. ...
  4. 'wsServer' => [
  5. 'class' => \Swoft\WebSocket\Server\WebSocketServer::class,
  6. ...
  7. //可配置多个消息消费,视业务量而定
  8. 'process' => array_merge(
  9. Tool::moreProcess('recvMessageProcess', bean(\Jcsp\WsCluster\Process\RecvMessageProcess::class), 3),
  10. [
  11. //自定义进程
  12. ]
  13. )
  14. ]
  15. ...

bean.php添加消息控制器中间键(如有用到消息控制器,此选项必须

  1. <?php
  2. ···
  3. 'wsMsgDispatcher' => [
  4. 'preMiddlewares' => [
  5. \Jcsp\WsCluster\Middleware\RecvMessageMiddleware::class
  6. ]
  7. ],
  8. ···

新增中间键概述

avatar

onHandshakeMiddleware 中间键

  • 只需在主配置添加onHandshakeMiddleware集合,即可优雅完成@OnHandshake处的处理。此中间键集合一般可用作请求过滤等业务。
  • 类需继Jcsp\WsCluster\Middleware\AbstracHandshakeMiddleware

  • 方法before为入,after为出,所有中间键先入后出顺序,参数与@OnOpen一致。

  • 如需阻断,则需return [false, $response],$response可垮中间键传输
  1. <?php
  2. namespace Jcsp\WsCluster\Middleware;
  3. use Swoft\Bean\Annotation\Mapping\Bean;
  4. use Swoft\Http\Message\Request;
  5. use Swoft\Http\Message\Response;
  6. /**
  7. * @Bean()
  8. * Class DefaultAllowMiddleware
  9. * @package Jcsp\WsCluster\Middleware
  10. */
  11. class DefaultAllowMiddleware extends AbstracHandshakeMiddleware
  12. {
  13. /**
  14. * @param Request $request
  15. * @param int $fd
  16. */
  17. public function before(Request $request, Response $response)
  18. {
  19. if(!$request->getHeaderLine('auth')) {
  20. //return [false, $response];
  21. }
  22. return [true, $response->withAttribute('allow','true')];
  23. }
  24. /**
  25. * @param Request $request
  26. * @param int $fd
  27. */
  28. public function after(Request $request, Response $response)
  29. {
  30. }
  31. }

onOpenMiddleware 中间键

  • 只需在主配置添加onOpenMiddleware集合,即可优雅完成@OnOpen处的处理。此中间键一般用作处理用户绑定,头部token解析等逻辑。
  • 类需继Jcsp\WsCluster\Middleware\AbstractOpenMiddleware

  • 方法before为入,after为出,所有中间键先入后出顺序,参数与@OnOpen一致。

内置用户绑定中间键,替换此中间键一般需实现Cluster::register用于用户绑定

  1. <?php
  2. namespace Jcsp\WsCluster\Middleware;
  3. use Jcsp\WsCluster\Cluster;
  4. use Swoft\Bean\Annotation\Mapping\Bean;
  5. use Swoft\Http\Message\Request;
  6. /**
  7. * @Bean()
  8. * Class DefaultAuthMiddleware
  9. * @package Jcsp\WsCluster\Handle
  10. */
  11. class DefaultAuthMiddleware extends AbstractOpenMiddleware
  12. {
  13. /**
  14. * @param Request $request
  15. * @param int $fd
  16. */
  17. public function before(Request $request, int $fd)
  18. {
  19. //token解析+用户绑定
  20. $auth = $request->getHeaderLine('auth');
  21. if ($auth) {
  22. Cluster::register($fd, $this->decodeToken($auth));
  23. }
  24. }
  25. /**
  26. * @param Request $request
  27. * @param int $fd
  28. */
  29. public function after(Request $request, int $fd)
  30. {
  31. //出
  32. }
  33. private function decodeToken(string $auth)
  34. {
  35. return $auth;
  36. }
  37. }

消息推送Api

Swoft对单机推送的支持,详见 Swot webdocket Server消息推送Api

Cluster支持对所有服务器的任意客户端直推消息

  1. <?php
  2. //对绑定的uid精准推送,@onOpen中间键绑定
  3. Cluster::transport(string $message, $uid = null)
  4. Cluster::transportToUid(string $message, ...$uid)
  1. <?php
  2. //对所有在役服务端的客户端广播消息
  3. Cluster::transportToAll(string $message)

内置事件

消息接收

  1. 用户注册
  2. ```Jcsp\WsCluster\Event::REGISTER

用户注销

  1. server服务心跳
  2. ```Jcsp\WsCluster\Event::DISCOVER

server服务离线
Jcsp\WsCluster\Event::SHUTDOWN