1. 介紹
基於swoole websocket server的swoft websocket已經很方便的開箱即用,但其無法直接支援多機器集場。
本元件可支援大多數web推送場景,IM互聊場景,IM群發場景等。
使用前請通讀Swot webdocket Server文件,配置習慣與其並無任何變化。
流程請參見下圖
- ① 客戶端發起握手請求並建立連線
- ② 當前服務端向資源管理State註冊並繫結當前使用者資訊
- ③ 服務端A向服務B所在訊息佇列推送訊息
- ④ 服務端B消費訊息並接收
- ⑤ 服務端B向客戶端推送訊息
2. 特性
- 高效能,水平擴容
- 高可用,所有機器都為master,相互心跳檢測
- 訊息佇列與狀態管理均採用介面卡模式,預設均為redis驅動,擴充性強
- 事件均採用Aop切面技術,無感知,解耦
- 與原
Swoft Webdocket
使用起來基本一致,習慣保持
3. 安裝
composer
composer require devweyes/ws-server-cluster
redis
預設使用redis記憶體伺服器作為狀態儲存,訊息佇列。所以你還需至少一臺redis伺服器或叢集
4. 使用
基本使用
使用命令,WsModule
,訊息控制器
,訊息解析器
請參見Swot webdocket Server文件
一個完整的WsModule
需配置全部已知方法註解,用於實現切面。包括@OnHandshake()
.@OnOpen()
.@OnMessage()
.@OnClose()
,@OnMessage()
可由訊息控制器
代替,否則可能無法正常使用。
叢集配置
預設配置,如需自定義可覆蓋。
<?php
return [
Cluster::MANAGER => [ //主配置
'class' => ClusterManager::class,
'state' => bean(Cluster::STATE), //狀態選擇
'onHandshakeMiddleware' => [ //握手階段中間鍵
bean(DefaultAllowMiddleware::class)
],
'onOpenMiddleware' => [ //onOpen階段中間鍵
bean(DefaultAuthMiddleware::class)
],
'heartbeat' => 60 //伺服器心跳檢測,相互檢測
],
Cluster::STATE => [ //狀態儲存配置
'class' => RedisState::class,
'redis' => bean('redis.pool'),
'serializer' => bean(Cluster::SERIALIZER),
'prefix' => 'swoft_ws_server_cluster',
],
Cluster::SERIALIZER => [ //序列化配置
'class' => PhpSerializer::class
]
];
bean.php新增非同步程式訊息處理
<?php
use Jcsp\WsCluster\Helper\Tool;
...
'wsServer' => [
'class' => \Swoft\WebSocket\Server\WebSocketServer::class,
...
//可配置多個訊息消費,視業務量而定
'process' => array_merge(
Tool::moreProcess('recvMessageProcess', bean(\Jcsp\WsCluster\Process\RecvMessageProcess::class), 3),
[
//自定義程式
]
)
]
...
bean.php新增訊息控制器中間鍵(如有用到訊息控制器,此選項必須
)
<?php
···
'wsMsgDispatcher' => [
'preMiddlewares' => [
\Jcsp\WsCluster\Middleware\RecvMessageMiddleware::class
]
],
···
新增中間鍵概述
onHandshakeMiddleware 中間鍵
-
只需在主配置新增
onHandshakeMiddleware
集合,即可優雅完成@OnHandshake
處的處理。此中間鍵集合一般可用作請求過濾等業務。 -
類需繼
Jcsp\WsCluster\Middleware\AbstracHandshakeMiddleware
-
方法
before
為入,after
為出,所有中間鍵先入後出順序,引數與@OnOpen
一致。 -
如需阻斷,則需
return [false, $response]
,$response
可垮中間鍵傳輸
<?php
namespace Jcsp\WsCluster\Middleware;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Http\Message\Request;
use Swoft\Http\Message\Response;
/**
* @Bean()
* Class DefaultAllowMiddleware
* @package Jcsp\WsCluster\Middleware
*/
class DefaultAllowMiddleware extends AbstracHandshakeMiddleware
{
/**
* @param Request $request
* @param int $fd
*/
public function before(Request $request, Response $response)
{
if(!$request->getHeaderLine('auth')) {
//return [false, $response];
}
return [true, $response->withAttribute('allow','true')];
}
/**
* @param Request $request
* @param int $fd
*/
public function after(Request $request, Response $response)
{
}
}
onOpenMiddleware 中間鍵
-
只需在主配置新增
onOpenMiddleware
集合,即可優雅完成@OnOpen
處的處理。此中間鍵一般用作處理使用者繫結,頭部token解析等邏輯。 -
類需繼
Jcsp\WsCluster\Middleware\AbstractOpenMiddleware
-
方法
before
為入,after
為出,所有中間鍵先入後出順序,引數與@OnOpen
一致。
內建使用者繫結中間鍵,替換此中間鍵一般需實現Cluster::register
用於使用者繫結
<?php
namespace Jcsp\WsCluster\Middleware;
use Jcsp\WsCluster\Cluster;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Http\Message\Request;
/**
* @Bean()
* Class DefaultAuthMiddleware
* @package Jcsp\WsCluster\Handle
*/
class DefaultAuthMiddleware extends AbstractOpenMiddleware
{
/**
* @param Request $request
* @param int $fd
*/
public function before(Request $request, int $fd)
{
//token解析+使用者繫結
$auth = $request->getHeaderLine('auth');
if ($auth) {
Cluster::register($fd, $this->decodeToken($auth));
}
}
/**
* @param Request $request
* @param int $fd
*/
public function after(Request $request, int $fd)
{
//出
}
private function decodeToken(string $auth)
{
return $auth;
}
}
訊息推送Api
Swoft對單機推送的支援,詳見 Swot webdocket Server訊息推送Api。
Cluster支援對所有伺服器的任意客戶端直推訊息
<?php
//對繫結的uid精準推送,@onOpen中間鍵繫結
Cluster::transport(string $message, $uid = null)
Cluster::transportToUid(string $message, ...$uid)
<?php
//對所有在役服務端的客戶端廣播訊息
Cluster::transportToAll(string $message)
內建事件
訊息接收Jcsp\WsCluster\Event::RECV_MESSAGE
使用者註冊Jcsp\WsCluster\Event::REGISTER
使用者登出Jcsp\WsCluster\Event::LOGOUT
server服務心跳Jcsp\WsCluster\Event::DISCOVER
server服務離線Jcsp\WsCluster\Event::SHUTDOWN
本作品採用《CC 協議》,轉載必須註明作者和本文連結