求助WebSocket opening handshake timed out和dtruss跟踪

1,最近在做一个实时监控项目,用到了html5的websocket。场景如下:
点击设备列表,进入某个设备详情页面,监控这个设备的运行状况,实时更新一些设备运行状态参数。

2,前端代码如下:
// 省略...
const socket = new WebSocket(server);

socket.addEventListener('open', function(e) {
socket.send(该设备id);
});

socket.addEventListener('message', function(e) {
const data = e.data;

更新设备信息(data);
});

socket.addEventListener('close', function(e) {
console.log('websockt连接已关闭');
});

socket.addEventListener('error', function(e) {
alert("websockt连接发生错误,请刷新页面重试!");
});

// 省略...


3,后端我用的php的wokerman(一个php sokcet服务框架)提供的一个websocket服务用来测试(我目前做前端开发,用这个workerman只是用来测试)。
// 心跳间隔25秒
define('HEARTBEAT_TIME', 25);

$ws_worker = new Worker("websocket://0.0.0.0:9668");

// 8 processes
$ws_worker->count = 8;

// 进程启动后设置一个每秒运行一次的定时器
$ws_worker->onWorkerStart = function($worker) {
Timer::add(1, function()use($worker){
    $time_now = time();
    foreach($worker->connections as $connection) {
        // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
        if (empty($connection->lastMessageTime)) {
            $connection->lastMessageTime = $time_now;
            continue;
        }
        // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
        if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
            $connection->close();
        }
    }
});
};

// Emitted when data received
$ws_worker->onMessage = function ($connection, $data) {

// 给connection临时设置一个lastMessageTime属性,用来记录上次收到消息的时间
$connection->lastMessageTime = time();

while (true) {
    $connection->send(根据接收到的客户端的$data发送要发送的消息);
    usleep(1000000); // 睡1秒
}
};

4,现象:
我发现如果刷新设备详情页面8次以上(这个次数正好和后端代码中设置的wokerman的进程数相等),客户端就会连接不上后端的socket服务,一直pending,直到提示:WebSocket opening handshake timed out。而wokerman的运行状态则为:


5,问题:
我想问下我的代码哪里出了问题,是前端js代码或业务逻辑有问题还是后端php代码或业务有问题。
谢谢。

ps:
前后端代码都是跑在本地上,mac os。我看了论坛上和workerman手册上提到可以用strace来跟踪进程,但mac上只有dtruss(貌似是调用的dtrace)可以用,我跟踪了一个busy的进程 sudo dtruss -p 24368发现:


但我看不太明白打印的这些都是什么,不知道问题处出在哪里。
2018-02-02 12:23 添加评论 分享
已邀请:
1

xiuwang

赞同来自: beijingde

while (true) {
$connection->send(根据接收到的客户端的$data发送要发送的消息);
usleep(1000000); // 睡1秒
}

业务代码死循环了,这样你的代码一直在死循环在while (true) {}里运行,其它代码都执行不到的,包括onMessage的代码,包括workerman框架的代码都执行不到,所以完全不工作了。C/C++/java等语言都是,死循环是大忌。

要回复问题请先登录注册

退出全屏模式 全屏模式 回复