一、在tp6項目下安裝? GatewayWorker?
composer require topthink/think-worker
composer require workerman/gatewayclient
安裝成功后在配置文件目錄下會出現(xiàn)gateway_worker.php
開始配置gateway_worker? 下邊我貼出了我的配置文件供大家參考
return [
// 擴展自身需要的配置
'protocol' => 'websocket', // 協(xié)議 支持 tcp udp unix http websocket text
'host' => '127.0.0.1', // 監(jiān)聽地址
'port' => 9099, // 監(jiān)聽端口
'socket' => '', // 完整監(jiān)聽地址
'context' => [], // socket 上下文選項
'register_deploy' => true, // 是否需要部署register
'businessWorker_deploy' => true, // 是否需要部署businessWorker
'gateway_deploy' => true, // 是否需要部署gateway
// Register配置
'registerAddress' => '127.0.0.1:1236',
// Gateway配置
'name' => 'thinkphp',
'count' => 1,
'lanIp' => '127.0.0.1',
'startPort' => 2000,
'daemonize' => false,
'pingInterval' => 30,
'pingNotResponseLimit' => 1,
'pingData' => '{"type":"ping"}',
// BusinsessWorker配置
'businessWorker' => [
'name' => 'BusinessWorker',
'count' => 1,
'eventHandler' => 'app\common\service\WsEventService',
],
];
?下面對gateway 配置部分的屬性解釋
name :?可以設置Gateway進程的名稱,方便status命令中查看統(tǒng)計
count :可以設置Gateway進程的數(shù)量,以便充分利用多cpu資源
lanIp :lanIp是Gateway所在服務器的內網(wǎng)IP,如果不做多服務器分布式部署的話默認填寫127.0.0.1即可
startPort :官方文檔是這樣說的??Gateway進程啟動后會監(jiān)聽一個本機端口,用來給BusinessWorker提供鏈接服務,然后Gateway與BusinessWorker之間就通過這個連接通訊。這里設置的是Gateway監(jiān)聽本機端口的起始端口。比如啟動了4個Gateway進程,startPort為2000,則每個Gateway進程分別啟動的本地端口一般為2000、2001、2002、2003。
官方的話比較繞,其實就可以理解為一下配置了? N個端口? 起始端口是 你配置的端口號 至于會啟動多少個完全取決你配置的工作進程數(shù) "count"
?registerAddress : 注冊服務地址
daemonize : 是否以守護進程模式啟動(linux下有效?)
pingInterval :心跳間隔時間
pingNotResponseLimit :?服務端是否允許客戶端不發(fā)送心跳 如果配置為0則服務端允許客戶端不發(fā)心跳 ,如果配置為1 客戶端必須要在心跳間隔時間(pingInterval)內發(fā)送心跳到服務器否則服務器會判定客戶端斷開而終端連接觸發(fā)onclose事件。
pingData : 如果pingData 不是空字符串則服務器會在心跳間隔時間(pingInterval)向客戶端發(fā)送心跳數(shù)據(jù)
PS:GatewayWorker 通過pingInterval、pingNotResponseLimit、pingData? 這三個配置實現(xiàn)了心跳檢測機制 ,詳情請參見官方文檔心跳檢測部分?心跳檢測-gateway-worker手冊
下面對??businessWorker 的配置進行講解
name :businessWorker啟動的進程名
count :businessWorker啟動的工作進程數(shù)
eventHandler :?businessWorker 的事件類(這里要寫完整的命名空間)
以下是eventHandler 的示例代碼
namespace app\common\service;
use GatewayWorker\Lib\Gateway;
class WsEventService{
public static function onConnect($client_id)
{
Gateway::sendToCurrentClient("Your client_id is $client_id");
}
public static function onMessage($client_id , $data){
Gateway::sendtoCurrentClient("client_id: $client_id -> "."data => $data");
}
}
當然這里還可以配置更多的事件 詳情請參照官方文檔的Events類的回調屬性-gateway-worker手冊
至此我們就可以啟動 gateway了
php think worker:gateway
如果你是在windows下會報錯??
這里不支持windows環(huán)境并不是說gateway worker不支持windows,而是tp的命令行運行方式不支持windows,原因是(在官方文檔中有說明)
?
?官方文檔說要分別創(chuàng)建三個php文件分別啟動?gateway、register、businessworker服務
我們這里可以通過一個TP自定義命令行搞定 繼續(xù)上代碼!
<?php
declare(strict_types=1);
namespace app\command;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use think\console\Command;
use think\console\Input;
use think\console\input\Argument;
use think\console\input\Option;
use think\console\Output;
use think\facade\Config;
use Workerman\Worker;
class WebSocket extends Command
{
protected function configure()
{
// 指令配置
$this->setName('wserver')
->addArgument('service', Argument::OPTIONAL, 'workerman service: gateway|register|businessworker', null)
->addOption('host', 'H', Option::VALUE_OPTIONAL, 'the host of workerman server', null)
->addOption('port', 'P', Option::VALUE_OPTIONAL, 'the port of workerman server', null)
->addOption('daemon', 'd', Option::VALUE_OPTIONAL, 'Run the workerman server in daemon mode.')
->setDescription('workerman Server for ThinkPHP');
}
protected function execute(Input $input, Output $output)
{
$service = $input->getArgument('service');
$option = Config::get('gateway_worker');
if ($input->hasOption('host')) {
$host = $input->getOption('host');
} else {
$host = !empty($option['host']) ? $option['host'] : '0.0.0.0';
}
if ($input->hasOption('port')) {
$port = $input->getOption('port');
} else {
$port = !empty($option['port']) ? $option['port'] : '2347';
}
$registerAddress = !empty($option['registerAddress']) ? $option['registerAddress'] : '127.0.0.1:1236';
switch ($service) {
case 'register':
$this->register($registerAddress);
break;
case 'businessworker':
$this->businessWorker($registerAddress, isset($option['businessWorker']) ? $option['businessWorker'] : []);
break;
case 'gateway':
$this->gateway($registerAddress, $host, $port, $option);
break;
default:
$output->writeln("<error>Invalid argument action:{$service}, Expected gateway|register|businessworker .</error>");
exit(1);
break;
}
Worker::runAll();
}
/**
* 啟動register
* @access public
* @param string $registerAddress
* @return void
*/
public function register($registerAddress)
{
// 初始化register
new Register('text://' . $registerAddress);
}
/**
* 啟動businessWorker
* @access public
* @param string $registerAddress registerAddress
* @param array $option 參數(shù)
* @return void
*/
public function businessWorker($registerAddress, $option = [])
{
// 初始化 bussinessWorker 進程
$worker = new BusinessWorker();
$this->option($worker, $option);
$worker->registerAddress = $registerAddress;
}
/**
* 啟動gateway
* @access public
* @param string $registerAddress registerAddress
* @param string $host 服務地址
* @param integer $port 監(jiān)聽端口
* @param array $option 參數(shù)
* @return void
*/
public function gateway($registerAddress, $host, $port, $option = [])
{
// 初始化 gateway 進程
if (!empty($option['socket'])) {
$socket = $option['socket'];
unset($option['socket']);
} else {
$protocol = !empty($option['protocol']) ? $option['protocol'] : 'websocket';
$socket = $protocol . '://' . $host . ':' . $port;
unset($option['host'], $option['port'], $option['protocol']);
}
$gateway = new Gateway($socket, isset($option['context']) ? $option['context'] : []);
// 以下設置參數(shù)都可以在配置文件中重新定義覆蓋
$gateway->name = 'Gateway';
$gateway->count = 4;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2000;
$gateway->pingInterval = 10;
$gateway->pingNotResponseLimit = 1;
$gateway->pingData = '{"type":"ping"}';
$gateway->registerAddress = $registerAddress;
// 全局靜態(tài)屬性設置
foreach ($option as $name => $val) {
if (in_array($name, ['stdoutFile', 'daemonize', 'pidFile', 'logFile'])) {
Worker::${$name} = $val;
unset($option[$name]);
}
}
$this->option($gateway, $option);
}
/**
* 設置參數(shù)
* @access protected
* @param Worker $worker Worker對象
* @param array $option 參數(shù)
* @return void
*/
protected function option($worker, array $option = [])
{
// 設置參數(shù)
if (!empty($option)) {
foreach ($option as $key => $val) {
$worker->$key = $val;
}
}
}
}
下邊我們就可以通過運行這個tp自定義命令來分別啟動三個服務
php think wserver register //啟動 register服務
php think wserver businessworker //啟動 businessworker服務
php think wserver gateway //啟動 gateway服務
這樣我們需要在windows上打開三個cmd窗體分別執(zhí)行這三條命令 如果嫌麻煩的話可以編輯個bat腳本一次啟動這三個服務, 將下邊代碼保存成 xxx.bat 就可以了
start php think wserver register
start php think wserver businessworker
start php think wserver gateway
最后執(zhí)行這個bat腳本就可以了(通過命令行執(zhí)行或者雙擊執(zhí)行都可以)
?到這里我們就可以在tp6項目中任何一個地方通過調用 GatewayWorker\Lib\Gateway 類的方法向客戶端推送消息了 詳情請參見官方文檔??Lib/Gateway類提供的接口-gateway-worker手冊文章來源:http://www.zghlxwxcb.cn/news/detail-722700.html
Gateway::sendToClient($client_id,$message);
windows 啟動服務部分參照了? 八戒王的博客《GatewayWorker Not Support On Windows.》 特此鳴謝!GatewayWorker Not Support On Windows._windows不支持 geteway_八戒王的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-722700.html
到了這里,關于TP6 + GatewayWorker 輕松實現(xiàn)web項目 websocket 功能的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!