【workbunny】分布式websocket服務(wù)(即時(shí)通訊服務(wù))

Webman-push-server
說明
- 3.0:全新架構(gòu)
- 2.0:舊版架構(gòu),長(zhǎng)期技術(shù)支持版本(LTS),點(diǎn)擊跳轉(zhuǎn)2.0文檔
- 1.0:舊版架構(gòu),不再維護(hù),請(qǐng)使用2.0 / fork自行維護(hù),點(diǎn)擊跳轉(zhuǎn)1.0文檔
文檔
https://github.com/workbunny/webman-push-server/blob/main/README.md
簡(jiǎn)介
- 全新重構(gòu)的分布式推送服務(wù),更簡(jiǎn)單的使用,更簡(jiǎn)單的部署,更簡(jiǎn)單的代碼!
- 完整且高效的即時(shí)通訊服務(wù),支持聊天、在線推送、數(shù)字大屏等雙向通訊長(zhǎng)連接業(yè)務(wù)場(chǎng)景;
- 高保真復(fù)刻的Pusher-Channel,可以利用現(xiàn)有的Pusher-Channel客戶端,其他語言(Java Swift .NET Objective-C Unity Flutter Android IOS AngularJS等)客戶端地址下載地址:
https://pusher.com/docs/channels/channels_libraries/libraries/ - 本項(xiàng)目1.0/2.0版本承接實(shí)現(xiàn)了諸多商業(yè)項(xiàng)目的即時(shí)通訊服務(wù),日最大連接300K+,日活連接200K+,最久的商業(yè)化項(xiàng)目已穩(wěn)定運(yùn)行3年,性能與穩(wěn)定性兼顧;
- 如遇問題,歡迎 issue & PR;
架構(gòu)
- 摒棄了api-service服務(wù)需要掛載在Push-server的設(shè)計(jì),獨(dú)立化api-server,性能更好
- 使用redis Publish/Subscribe 代替workerman/channel作為分布式廣播
- 使用redis Publish/Subscribe 代替HookServer隊(duì)列作為事件監(jiān)聽中間件
- 簡(jiǎn)化Push-server的代碼內(nèi)容
- 簡(jiǎn)化了Api邏輯
┌─────────────┐ 2 | 3
┌───> | Push-server | ─── ─ · ─
| └─────────────┘ 1 | 4 ··· n
| Hash | ↑
| | PUB | SUB
┌────────────────────┐ ──┘ ┌──────────────┐ <────┘
| webman-push-server | ──────> | Redis-server |
└────────────────────┘ ──┐ └──────────────┘ <────┐
| | PUB | SUB
| Hash | ↓
| ┌────────────┐ 2 | 3
└────> | API-server | ─── ─ · ─
└────────────┘ 1 | 4 ··· n
約定
配置說明
配置信息及對(duì)應(yīng)功能在代碼注釋中均有解釋,詳見對(duì)應(yīng)代碼注釋;
|-- config
|-- plugin
|-- webman-push-server
|-- app.php # 主配置信息
|-- bootstrap.php # 自動(dòng)加載
|-- command.php # 支持命令
|-- log.php # 日志配置
|-- middleware.php # 基礎(chǔ)中間件
|-- process.php # 啟動(dòng)進(jìn)程
|-- redis.php # redis配置
|-- route.php # APIs路由信息
頻道說明
push-server支持以下三種頻道類型:
- 公共頻道(public):客戶端僅可監(jiān)聽公共頻道,不可向公共頻道推送消息;
- 私有頻道(private):客戶端可向私有頻道推送/監(jiān)聽,一般用于端對(duì)端的通訊,服務(wù)端僅做轉(zhuǎn)發(fā);該頻道可以用于私聊場(chǎng)景;
- 狀態(tài)頻道(presence):與私有頻道保持一致,區(qū)別在于狀態(tài)頻道還保存有客戶端的信息,任何用戶的上下線都會(huì)收到該頻道的廣播通知,如user_id、user_info;
狀態(tài)頻道最多支持100個(gè)客戶端(客戶端限制,實(shí)際上可以放開);
事件說明
1. 默認(rèn) event 遵守以下的約定規(guī)范:
- client- 前綴的事件:擁有 client- 前綴的事件是客戶端發(fā)起的事件,客戶端在推送消息時(shí)一定會(huì)帶有該前綴;
- pusher: 前綴的事件:擁有 pusher: 前綴的事件一般用于服務(wù)端消息、公共消息,比如在公共頻道由服務(wù)端推送的消息、客戶端發(fā)起的訂閱公共消息;
- pusher_internal: 前綴的事件:擁有 pusher_internal: 前綴的事件是服務(wù)端的回執(zhí)通知,一般是由客戶端發(fā)起訂閱、取消訂閱等操作時(shí),由服務(wù)端回執(zhí)的事件信息帶有該前綴的事件;
2. event支持自定義注冊(cè)
使用
服務(wù)端
1. 環(huán)境依賴
- php >=8.0
- webman >= 1.0
- redis >= 5.0
2. 安裝使用
- 使用composer安裝
composer require workbunny/webman-push-server
- webman框架自動(dòng)加載配置
- 在config/plugin/workbunny/webman-push-server/中配置對(duì)應(yīng)文件
- webman啟動(dòng)
3. 服務(wù)說明
push-server服務(wù)
- push-server服務(wù)用于監(jiān)聽websocket消息,是實(shí)現(xiàn)即時(shí)通訊功能的主要服務(wù)
- push-server服務(wù)支持多進(jìn)程,通訊方式及基礎(chǔ)數(shù)據(jù)儲(chǔ)存方式為redis
- config/plugin/workbunny/webman-push-server/process.php中可調(diào)節(jié)啟動(dòng)進(jìn)程數(shù),默認(rèn)為cpu count
- config/plugin/workbunny/webman-push-server/app.php中可配置心跳等參數(shù)
- config/plugin/workbunny/webman-push-server/redis.php中可配置redis連接信息
- config/plugin/workbunny/webman-push-server/middleware.php中可配置push-server消息中間件,可用于消息的攔截、過濾、路由等
api-server服務(wù)
- api-server服務(wù)用于監(jiān)聽http/https消息,對(duì)外提供REST風(fēng)格的open-apis,API服務(wù)提供REST風(fēng)格的http-APIs,接口內(nèi)容與 pusher-channel-api 基本保持一致
- config/plugin/workbunny/webman-push-server/process.php中可調(diào)節(jié)啟動(dòng)進(jìn)程數(shù),默認(rèn)為cpu count
- config/plugin/workbunny/webman-push-server/app.php中可配置流量統(tǒng)計(jì)間隔等參數(shù)
- config/plugin/workbunny/webman-push-server/route.php中為基礎(chǔ)open-apis的實(shí)現(xiàn)
- config/plugin/workbunny/webman-push-server/middleware.php中可配置api-server消息中間件,可用于消息的攔截、過濾、路由等
open-apis列表:
method | url | 描述 |
---|---|---|
POST | /apps/[app_id]/events | 對(duì)應(yīng)的pusher文檔地址 |
POST | /apps/[app_id]/batch_events | 對(duì)應(yīng)的pusher文檔地址 |
GET | /apps/[app_id]/channels | 對(duì)應(yīng)的pusher文檔地址 |
GET | /apps/[app_id]/channels/[channel_name] | 對(duì)應(yīng)的pusher文檔地址 |
POST | /apps/[app_id]/users/[user_id]/terminate_connections | 對(duì)應(yīng)的pusher文檔地址 |
GET | /apps/[app_id]/channels/[channel_name]/users | 對(duì)應(yīng)的pusher文檔地址 |
客戶端
javascript客戶端
1. 安裝
- 引入
<script src="/plugin/workbunny/webman-push-server/push.js"> </script>
- 創(chuàng)建連接
TIps:每 new 一個(gè) Push 會(huì)創(chuàng)建一個(gè)連接。
// 建立連接
var connection = new Push({
url: 'ws://127.0.0.1:8001', // websocket地址
app_key: '<app_key>', // 在config/plugin/workbunny/webman-push-server/app.php里配置
});
2.客戶端訂閱公共頻道
TIps:頻道和事件可以是任意符合約定前綴的字符串,不需要服務(wù)端預(yù)先配置。
// 建立連接
var connection = new Push({
url: 'ws://127.0.0.1:8001', // websocket地址
app_key: '<app_key>', // 在config/plugin/workbunny/webman-push-server/app.php里配置
});
// 監(jiān)聽 public-test 公共頻道
var user_channel = connection.subscribe('public-test');
// 當(dāng) public-test 頻道有message事件的消息回調(diào)
user_channel.on('message', function(data) {
// data里是消息內(nèi)容
console.log(data);
});
// 取消監(jiān)聽 public-test 頻道
connection.unsubscribe('public-test')
// 取消所有頻道的監(jiān)聽
connection.unsubscribeAll()
3.客戶端訂閱私有/狀態(tài)頻道
Tips:您需要先實(shí)現(xiàn)用于鑒權(quán)的接口服務(wù)
- 私有頻道
Tips:樣例鑒權(quán)接口詳見 config/plugin/workbunny/webman-push-server/route.php
// 訂閱發(fā)生前,瀏覽器會(huì)發(fā)起一個(gè)ajax鑒權(quán)請(qǐng)求(ajax地址為new Push時(shí)auth參數(shù)配置的地址),開發(fā)者可以在這里判斷,當(dāng)前用戶是否有權(quán)限監(jiān)聽這個(gè)頻道。這樣就保證了訂閱的安全性。
var connection = new Push({
url: 'ws://127.0.0.1:8001', // websocket地址
app_key: '<app_key>',
auth: 'http://127.0.0.1:8002/subscribe/auth' // 該接口是樣例接口,請(qǐng)根據(jù)源碼自行實(shí)現(xiàn)業(yè)務(wù)
});
// 監(jiān)聽 private-test 私有頻道
var user_channel = connection.subscribe('private-test');
// 當(dāng) private-test 頻道有message事件的消息回調(diào)
user_channel.on('message', function(data) {
// data里是消息內(nèi)容
console.log(data);
});
// 取消監(jiān)聽 private-test 頻道
connection.unsubscribe('private-test')
// 取消所有頻道的監(jiān)聽
connection.unsubscribeAll()
- 狀態(tài)頻道
Tips:樣例鑒權(quán)接口詳見 config/plugin/workbunny/webman-push-server/route.php
- 方法一
// 方法一
// 訂閱發(fā)生前,瀏覽器會(huì)發(fā)起一個(gè)ajax鑒權(quán)請(qǐng)求(ajax地址為new Push時(shí)auth參數(shù)配置的地址),開發(fā)者可以在這里判斷,當(dāng)前用戶是否有權(quán)限監(jiān)聽這個(gè)頻道。這樣就保證了訂閱的安全性。
var connection = new Push({
url: 'ws://127.0.0.1:8001', // websocket地址
app_key: '<app_key>',
auth: 'http://127.0.0.1:8002/subscribe/auth' // 該接口是樣例接口,請(qǐng)根據(jù)源碼自行實(shí)現(xiàn)業(yè)務(wù)
});
- 方法二
// 方法二
// 先通過接口查詢獲得用戶信息,組裝成如下
var channel_data = {
user_id: '100',
user_info: "{\'name\':\'John\',\'sex\':\'man\'}"
}
// 訂閱發(fā)生前,瀏覽器會(huì)發(fā)起一個(gè)ajax鑒權(quán)請(qǐng)求(ajax地址為new Push時(shí)auth參數(shù)配置的地址),開發(fā)者可以在這里判斷,當(dāng)前用戶是否有權(quán)限監(jiān)聽這個(gè)頻道。這樣就保證了訂閱的安全性。
var connection = new Push({
url: 'ws://127.0.0.1:8001', // websocket地址
app_key: '<app_key>',
auth: 'http://127.0.0.1:8002/subscribe/auth', // 該接口是樣例接口,請(qǐng)根據(jù)源碼自行實(shí)現(xiàn)業(yè)務(wù)
channel_data: channel_data
});
// 監(jiān)聽 presence-test 狀態(tài)頻道
var user_channel = connection.subscribe('presence-test');
// 當(dāng) presence-test 頻道有message事件的消息回調(diào)
user_channel.on('message', function(data) {
// data里是消息內(nèi)容
console.log(data);
});
// 取消監(jiān)聽 presence-test 頻道
connection.unsubscribe('presence-test')
// 取消所有頻道的監(jiān)聽
connection.unsubscribeAll()
4.客戶端推送
Tips:
- 客戶端間推送僅支持私有頻道(private-)/狀態(tài)頻道(presence-),并且客戶端只能觸發(fā)以 client- 開頭的事件。
客戶端觸發(fā)事件推送的例子 - 以下代碼給所有訂閱了 private-user-1 的客戶端推送 client-message 事件的數(shù)據(jù),而當(dāng)前客戶端不會(huì)收到自己的推送消息
// 以上省略
// 私有頻道
var user_channel = connection.subscribe('private-user-1');
user_channel.on('client-message', function (data) {
//
});
user_channel.trigger('client-message', {form_uid:2, content:"hello"});
// 狀態(tài)頻道
var user_channel = connection.subscribe('presence-user-1');
user_channel.on('client-message', function (data) {
//
});
user_channel.trigger('client-message', {form_uid:2, content:"hello"});
5. wss代理(SSL)
- https下無法使用ws連接,需要使用wss連接。這種情況可以使用nginx代理wss,配置類似如下:
server {
# .... 這里省略了其它配置 ...
location /app
{
proxy_pass http://127.0.0.1:3131;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}
}
- 重啟nginx后,使用以下方式連接服務(wù)端
var connection = new Push({
url: 'wss://example.com',
app_key: '<app_key>'
});
Tips:
wss開頭,不寫端口,必須使用ssl證書對(duì)應(yīng)的域名連接
websocket-php客戶端
1. 創(chuàng)建連接
use Workbunny\WebmanPushServer\WsClient;
use Workerman\Connection\AsyncTcpConnection;
use Workbunny\WebmanPushServer\EVENT_SUBSCRIBE;
use Workbunny\WebmanPushServer\EVENT_SUBSCRIPTION_SUCCEEDED;
// 創(chuàng)建連接
$client = WsClient::instance('127.0.0.1:8001', [
'app_key' => 'workbunny',
'heartbeat' => 60,
'auth' => 'http://127.0.0.1:8002/subscribe/auth',
'channel_data' => [] // channel_data
'query' => [], // query
'context_option' => []
])
// 建立連接
$client->connect();
// 關(guān)閉連接
$client->disconnect();
2. 訂閱/退訂
use Workbunny\WebmanPushServer\WsClient;
use Workerman\Connection\AsyncTcpConnection;
// 創(chuàng)建連接
$client = WsClient::instance('127.0.0.1:8001', [
'app_key' => 'workbunny',
'heartbeat' => 60,
'auth' => 'http://127.0.0.1:8002/subscribe/auth',
'channel_data' => [] // channel_data
'query' => [], // query
'context_option' => []
])
// 訂閱一個(gè)私有通道,訂閱成功后會(huì)執(zhí)行回調(diào)函數(shù)
$client->subscribe('private-test', function (AsyncTcpConnection $connection, array $data) {
// 訂閱成功后打印
dump($data);
});
// 訂閱一個(gè)私有通道,不注冊(cè)訂閱成功后的回調(diào)
$client->subscribe('private-test');
// 取消訂閱一個(gè)私有通道
$client->unsubscribe('private-test', function (AsyncTcpConnection $connection, array $data) {
// 取消訂閱成功后打印
dump($data);
});
// 取消訂閱一個(gè)私有通道,不注冊(cè)訂閱成功后的回調(diào)
$client->unsubscribe('private-test');
// 取消全部訂閱
$client->unsubscribeAll();
3. 觸發(fā)消息
// 向 private-test 通道發(fā)送 client-test 事件消息
$client->trigger('private-test', 'client-test', [
'message' => 'hello workbunny!'
]);
// 向 presence-test 通道發(fā)送 client-test 事件消息
$client->trigger('presence-test', 'client-test', [
'message' => 'hello workbunny!'
]);
// 事件不帶 client- 前綴會(huì)拋出RuntimeException
try {
$client->trigger('presence-test', 'test', [
'message' => 'hello workbunny!'
]);
} catch (RuntimeException $exception){
dump($exception);
}
4. 事件注冊(cè)回調(diào)
use Workerman\Connection\AsyncTcpConnection;
// 注冊(cè)關(guān)注private-test通道的client-test事件
$client->eventOn('private-test', 'client-test', function(AsyncTcpConnection $connection, array $data) {
// 打印事件數(shù)據(jù)
dump($data);
});
// 取消關(guān)注private-test通道的client-test事件
$client->eventOff('private-test', 'client-test');
// 獲取所有注冊(cè)事件回調(diào)
$client->getEvents();
5. 其他
// 獲取客戶端id,當(dāng)連接創(chuàng)建前該方法返回null
$client->getSocketId();
// 獲取已訂閱通道,訂閱觸發(fā)前該方法返回空數(shù)組
$client->getChannels();
// 發(fā)布消息
$client->publish();
// 更多詳見 WsClient.php
open-apis-php客戶端
1. 安裝
-
或者使用\Workbunny\WebmanPushServer\ApiClient 【建議使用】
composer require workbunny/webman-push-server
-
使用pusher提供的api客戶端 【不建議使用,客戶端請(qǐng)求沒有使用keep-alive】
composer require pusher/pusher-php-server
2. 推送
use Workbunny\WebmanPushServer\ApiClient;
try {
$pusher = new ApiClient(
'APP_KEY',
'APP_SECRET',
'APP_ID',
[
'host' =>"http://127.0.0.1:8001",
'timeout' => 60,
'keep-alive' => true
]
);
$pusher->trigger(
// 頻道(channel)支持多個(gè)通道
["private-d"],
// 事件
"client-a",
// 消息體
[
'message' => 'hello workbunny!'
],
// query
[]
);
} catch (GuzzleException|ApiErrorException|PusherException $e) {
dump($e);
}
3. 其他功能詳見open-apis列表
其他客戶端
- 兼容pusher,其他語言(Java Swift .NET Objective-C Unity Flutter Android IOS AngularJS等)客戶端地址下載地址:
https://pusher.com/docs/channels/channels_libraries/libraries/
進(jìn)階用法
1. push-server中間件服務(wù)
在一些服務(wù)器監(jiān)控場(chǎng)景下,我們需要獲取全量的往來信息,包括客戶端的消息和服務(wù)端的回執(zhí)等
- 創(chuàng)建一個(gè)中間件服務(wù)類,use引入ChannelMethods
<?php declare(strict_types=1);
namespace YourNamespace;
use Workbunny\WebmanPushServer\Traits\ChannelMethods;
class PushServerMiddleware
{
use ChannelMethods;
/** @inheritDoc */
public static function _subscribeResponse(string $type, array $data): void
{
// TODO
}
}
-
客戶端與服務(wù)端的任何通訊消息會(huì)觸達(dá)_subscribeResponse方法,請(qǐng)?jiān)赺subscribeResponse方法中實(shí)現(xiàn)對(duì)應(yīng)業(yè)務(wù)邏輯,入日志等;
-
在項(xiàng)目config/process.php或config/plugin/workbunny/webman-push-server/process.php中添加配置
// push-server-middleware
'push-server-middleware' => [
'handler' => YourNamespace\PushServerMiddleware::class,
'count' => 1,
],
- 啟動(dòng)webman即可
Tips:
- 中間件切記保持單進(jìn)程運(yùn)行,本質(zhì)上是與push-server進(jìn)程組監(jiān)聽同一個(gè)內(nèi)部通訊通道
- _subscribeResponse方法中請(qǐng)勿執(zhí)行耗時(shí)操作,否則將影響性能,建議異步執(zhí)行,如投送到隊(duì)列進(jìn)行消費(fèi)
- _subscribeResponse中type為client時(shí)為客戶端消息,type為server時(shí)為服務(wù)端回執(zhí)消息,其他則詳見AbstractPublishType.php
- 該中間件更適合作為監(jiān)控服務(wù)或者日志服務(wù),如果作為攔截器等服務(wù),可能存在調(diào)用鏈路較長(zhǎng)的問題
- 樣例查看,PushServerMiddleware.php
2. push-server onMessage中間件
我們?cè)谑褂眠^程中可能需要為push-server的onMessage做一些安全性考慮或者數(shù)據(jù)過濾和攔截的功能,那么消息中間件非常適合該場(chǎng)景
- 以攔截非websocket協(xié)議消息距離
- 在config/plugin/workbunny/webman-push-server/middleware.php中添加中間件回調(diào)函數(shù)
// push server root middlewares
'push-server' => [
// 以攔截非websocket消息舉例
function (Closure $next, TcpConnection $connection, $data): void
{
// 攔截非websocket服務(wù)消息
if (!$connection->protocol instanceof \Workerman\Protocols\Websocket) {
$connection->close('Not Websocket');
return;
}
$next($connection, $data);
}
],
- 啟動(dòng)webman即可
Tips:
- push-server onMessage中間件由于傳遞了connection對(duì)象,所以我們可以使用PushServer類中針對(duì)connection操作的所有方法,無需使用open-apis等進(jìn)行回執(zhí)
- onMessage中間件可以使用例子中的Closure匿名函數(shù)方式,也可以使用任意callable函數(shù),也可以使用類方法,只需要滿足實(shí)例的入?yún)⒑统鰠⒓纯?/li>
3. 自定義事件響應(yīng)
我們?cè)谑褂眠^程中,可能需要自定義事件響應(yīng)客戶端的消息,那么我們可以創(chuàng)建一個(gè)自定義響應(yīng)類
- 創(chuàng)建自定義響應(yīng)類
<?php declare(strict_types=1);
namespace Tests\Examples;
use Workbunny\WebmanPushServer\Events\AbstractEvent;
use Workerman\Connection\TcpConnection;
class OtherEvent extends AbstractEvent
{
/**
* @inheritDoc
*/
public function response(TcpConnection $connection, array $request): void
{
// todo
}
}
- 在服務(wù)啟動(dòng)前注冊(cè)該相應(yīng)類,注冊(cè)方法可以放在webman的bootstrap中
\Workbunny\WebmanPushServer\Events\AbstractEvent::register('other', \Tests\Examples\OtherEvent::class);
- 啟動(dòng)webman即可
- 當(dāng)合法客戶端發(fā)送event=other時(shí),將會(huì)觸發(fā)該事件響應(yīng)
Tips:
- response傳遞了connection對(duì)象及request對(duì)象,所以我們可以使用PushServer類中針對(duì)connection操作的所有方法,無需使用open-apis等進(jìn)行回執(zhí)
- 樣例查看,OtherEvent.php
4. 自定義內(nèi)部廣播事件
內(nèi)部廣播默認(rèn)存在client事件和server事件,push-server默認(rèn)只會(huì)響應(yīng)該兩種事件,如果我們需要對(duì)其他額外的內(nèi)部事件進(jìn)行處理時(shí)可使用該方案
- 創(chuàng)建自定義內(nèi)部廣播事件
<?php declare(strict_types=1);
namespace Tests\Examples;
use Workbunny\WebmanPushServer\PublishTypes\AbstractPublishType;
class OtherType extends AbstractPublishType
{
/** @inheritDoc */
public static function response(array $data): void
{
static::verify($data, [
['appKey', 'is_string', true],
['channel', 'is_string', true],
['event', 'is_string', true],
['socketId', 'is_string', false]
]);
// todo
}
}
- 在服務(wù)啟動(dòng)前注冊(cè)該相應(yīng)類,注冊(cè)方法可以放在webman的bootstrap中
\Workbunny\WebmanPushServer\PublishTypes\AbstractPublishType::register('other', \Tests\Examples\OtherType::class);
- 啟動(dòng)webman即可
- 當(dāng)使用內(nèi)部廣播發(fā)送type=other時(shí),將會(huì)觸發(fā)該事件響應(yīng)
\Workbunny\WebmanPushServer\PushServer::publish('other', [
'a' => 'a'
])
Tips:
- 樣例查看,OtherType.php
5. 高階部署
分布式部署
- 在不同的服務(wù)項(xiàng)目中引入該插件
- 配置redis指向同一個(gè)redis服務(wù)
- 啟動(dòng)所有服務(wù)項(xiàng)目即可
push-server api-server分離部署
- 在A服務(wù)項(xiàng)目中配置config/plugin/workbunny/webman-push-server/process.php中注釋api-server進(jìn)程配置
- 在B服務(wù)項(xiàng)目中配置config/plugin/workbunny/webman-push-server/process.php中注釋push-server進(jìn)程配置
- 分別啟動(dòng)A、B服務(wù)即可
Tips:
- 分布式部署與分離式部署可以相互結(jié)合,達(dá)到最小顆粒度的部署
- redis配置中可以獨(dú)立配置storage與channel,以達(dá)到最高性能
6. 二次開發(fā)
在一些場(chǎng)景下,我們可能需要對(duì)push-server進(jìn)行二次開發(fā),那么我們可以使用組合式拓展開發(fā),以實(shí)現(xiàn)對(duì)push-server的拓展
- 創(chuàng)建自定義push-server類
- 以PushServer為樣例,引入Traits并實(shí)現(xiàn)其方法;或者繼承PushServer類進(jìn)行方法重寫
- 修改process啟動(dòng)配置,將push-server替換為自定義push-server類
- 啟動(dòng)webman即可