说明
针对目前项目中需要实时通讯的场景,我们调研了一些第三方的库,目前比较成熟稳定的为基于workman的gatewaywork比较适合。本文主要针对如何集成gatewaywork进行说明。
安装
首先通过 composer 安装
composer require topthink/think-worker
Nginx配置
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=$1 last; break;
}
}
# websockets
location =/websocket{
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_pass https://localhost:21123;
proxy_connect_timeout 86400s;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
SSL配置
gateway_worker.php
<?php
return[
'protocol' => 'websocket', // 协议 支持 tcp udp unix http websocket text
'host' => '0.0.0.0', // 监听地址
'port' => 21123, // 监听端口
'socket' => '', // 完整监听地址
'ssl' => true,
'transport' =>'ssl',
'context' => [
'ssl' => [
'local_cert' => 'fullchain.pem', //证书文件的存放路径(请改成自己的路径)
'local_pk' => 'privkey.pem', //证书私钥的存放路径(请改成自己的路径)
'verify_peer' => false,
]
], // socket 上下文选项
'register_deploy' => true, // 是否需要部署register
'businessWorker_deploy' => true, // 是否需要部署businessWorker
'gateway_deploy' => true, // 是否需要部署gateway
// Register配置
'registerAddress' => '127.0.0.1:21124',
// Gateway配置
'name' => 'runnerPaotui',
'count' => 4,
'lanIp' => '127.0.0.1',
'startPort' => 21125,
'daemonize' => true,
'pingInterval' => 30,//心跳检测,默认30秒,监测不到断开链接
'pingNotResponseLimit' => 1,//0服务端主动发送心跳(不推荐,默认) 1客户端定时发送心跳(推荐,设为1后客户端需做主动定时向服务端发包处理)
'pingData' => '{"type":"ping"}',//服务端定时向客户端发送的数据
// BusinsessWorker配置
'businessWorker' => [
'name' => 'BusinessWorker',
'count' => 1,
// 'eventHandler' => '\think\worker\Events',
'eventHandler' => '\api\wxapp\controller\Events',
],
];
worker.php
<?php
return [
// 扩展自身需要的配置
'host' => '0.0.0.0', // 监听地址
'port' => 21128, // 监听端口
'root' => '', // WEB 根目录 默认会定位public目录
'app_path' => '', // 应用目录 守护进程模式必须设置(绝对路径)
'file_monitor' => false, // 是否开启PHP文件更改监控(调试模式下自动开启)
'file_monitor_interval' => 2, // 文件监控检测时间间隔(秒)
'file_monitor_path' => [], // 文件监控目录 默认监控application和config目录
// 支持workerman的所有配置参数
'name' => 'thinkphp',
'count' => 4,
'daemonize' => false,
'pidFile' => '',
];
worker_server.php
<?php
return [
'protocol' => 'websocket',
// 'pidFile' => Env::get('runtime_path') . 'worker.pid',
'worker_class' => 'api\wxapp\controller\WorkerController', // 自定义Workerman服务类名 支持数组定义多个服务
];
启动
使用 php think worker:gateway 启动 扩展中的 GatewayWorker 即可
php think worker:gateway start #启动
php think worker:gateway stop #停止
php think worker:gateway reload #重新加载
测试脚本
<!DOCTYPE html>
<html>
<head>
<title>HTML5</title>
<meta charset="utf-8" />
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
$(function() {
var socket;
var readyState = ["connecting", "connected", "closing", "closed"];
/* 打开连接事件 */
$("button:eq(0)").click(function() {
try {
/* 连接 */
// socket = new WebSocket("ws://*");
socket = new WebSocket("wss://demo.com/websocket");
/* 绑定事件 */
socket.onopen = function() {
$("#msg").html("连接成功...");
};
socket.onmessage = function(e) {
$("#msg").html($("#msg").html() + "<br />" + e.data);
};
socket.onclose = function() {
$("#msg").html($("#msg").html() + "<br />关闭连接...");
};
} catch(exception) {
$("#msg").html($("#msg").html() + "<br />有错误发生");
}
});
/* 发送数据事件 */
$("button:eq(1)").click(function() {
/* 检查文本框是否为空 */
if($("#data").val() == "") {
alert("请输入数据!");
return;
}
try {
socket.send($("#data").val());
$("#msg").html($("#msg").html() + "<br />发送数据:" + $("#data").val());
} catch (exception) {
$("#msg").html($("#msg").html() + "<br />发送数据出错");
}
/* 清空文本框 */
$("#data").val("");
});
/* 断开连接 */
$("button:eq(2)").click(function() {
socket.close();
});
});
</script>
</head>
<body>
<h1>WebSocket示例</h1>
<input type="text" id="data" />
<button>打开连接</button>
<button>发送数据</button>
<button>关闭连接</button>
<p id="msg"></p>
</body>
</html>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。