这个问题反复看了好几次论坛里的回答还是无法解决。
大致逻辑如下:
1.前端用户连接A服务器workerman的Websocket服务。
2.A服务器在Event中即充担客户端也担任服务端,A服务器连接B服务的WebScoket服务。
3.B服务连接后会一直吐一段数据给A服务器,A服务器负责转发给前端。
4.期间当多个前端用户同时使用A服务WebScoket服务时,其中某个A服务器与B服务器的链接会被中断,且不触发onClose,本地调试和日志排查后无报错。且是一个概率事件。
5.想和大佬们讨论下这个问题应该如何精准定位和排查以及处理
private static $ws_connection;
public static function onWorkerStart($worker)
{
self::$ws_connection = new AsyncTcpConnection("ws://***.***.***.**:80");
}
public static function onConnect($client_id)
{
}
public static function onWebSocketConnect($client_id, $data)
{
}
public static function onMessage($client_id, $message)
{
/**
* $msg = [ ];
*
*/
$msg = json_decode($message,TRUE);
try {
/* <<连接远端socket>> Start */
// 以websocket协议连接远程websocket服务器
// 连上后发送数据
$sendData = [];
self::$ws_connection->onConnect = function(AsyncTcpConnection $connection)use ($sendData,$client_id){
$_SESSION['time_id'] = Timer::add(10,function () use($connection){
$connection->send('{"type":"ping"}');
});
static $is_first_connect = true;
if (!$is_first_connect) return;
$is_first_connect = false;
$connection->send(json_encode($sendData,JSON_UNESCAPED_UNICODE));
Log::info($client_id . '连接成功');
};
// 远程websocket服务器发来消息时
self::$ws_connection->onMessage = function(AsyncTcpConnection $connection, $dataMsg) use ($client_id,$data,$res){
Log::info($client_id . $dataMsg);
$dataMsg = json_decode($dataMsg,true);
if(isset($dataMsg['type']) && $dataMsg['type'] == 'msg'){
Gateway::sendToClient($client_id,json_encode($choices,JSON_UNESCAPED_UNICODE));
};
// 连接上发生错误时,一般是连接远程websocket服务器失败错误
self::$ws_connection->onError = function($connection, $code, $msg){
Log::error("error: $msg\n");
};
self::$ws_connection->onClose = function($connection) use ($client_id){
Log::info($client_id . '我下线了,重连\n');
};
// 设置好以上各种回调后,执行连接操作
self::$ws_connection->connect();
/* <<连接远端socket>> End */
}catch (\Exception $e){
$res['code'] = $e->getCode();
$res['msg'] = $e->getMessage();
Gateway::sendToClient($client_id,json_encode($res,JSON_UNESCAPED_UNICODE));
return;
}
}
public static function onClose($client_id)
{
// Log::info($client_id . 'Close');
}
先梳理一下代码整体的逻辑吧
代码有bug吧。
1、你代码里用的self::$ws_connection,就是所有前端用户共用一个 self::$ws_connection,但是你代码里又是在onMessage里不断重置 self::$ws_connection。应该是在onWorkerStart里设置self::$ws_connection才对。
2、没有人保证连接永远不断开,所以要在onClose里加一个reconnect()逻辑,断开自动重连。前端代码也是一样。
其他都就是连接数超过1024要装event扩展,优化linux内核
好的 感谢 我梳理一下看看
静态属性都换成new之后掉线情况更严重了,突然某一秒就断了,服务端知道断线,客户端不知道也不触发close。
可能你哪里代码还有bug吧。既然没触发onclose,那么你怎么知道断了?
我在服务端打印了 Gateway::isOnline($client_id) 文档中写这个值是1的时候在线 0的时候就掉线了
你不是说 ”其中某个A服务器与B服务器的链接会被中断“ 么?怎么会用$client_id判断在线,$client_id是浏览器到gatewayWorker的链接id,不是A服务器与B服务器的链接。
A服务器到B服务器是通过AsyncTcpContent通过websocket链接的 所以是可以在B服务器看到A服务器与B服务器的链接是否在线的
onWorkerStart干的事情
启动公共连接:
设置异步连接:
断线重连逻辑:
定时器周期的调用checkStatus方法,检查连接是否正常(最后收到客户端消息的时间,超时主动断开)
感谢 逻辑都没有问题 最后发现是Phar打包的问题导致的
哈哈哈
你看看这个https://www.workerman.net/q/11278