GatewayWorker使用两个websocket连接session丢失

黑老怪

项目开了两个websocket地址用相同的注册地址
192.168.100.96:5858
192.168.100.201:5858
我在websocket的onConnect时候设置了认证定时器 (我用的是GlobalTimer)// 连接到来后,定时10秒关闭这个链接,需要10秒内发认证并删除定时器阻止关闭连接的执行

$auth_timer_id  = GlobalTimer::add(2, function () use ($client_id) {
    //错误提示.
    //发送离线提示
    Send::sendToClientClose($client_id, 'server', 'Sign', 'auth', 400);
}, null, false);
$_SESSION = $auth_timer_id;
$_SESSION     = $client_id;

在message里的接收第一条信息里会在成功后删除定时器,但是$_SESSION会有时候为空,而且只在多个websocket同时连接时会发生,单独一个不会发生(我是同时连接两个websocket,一直刷新页面就会出现这个问题)
因为业务逻辑以后还会更多个,甚至5-10个websocket服务器,求大佬求救啊!

3501 3 0
3个回答

walkor 打赏

如果你的session是在onMessage里设置的,那很可能为空,因为会出现只发起连接但是还没来得及发送数据连接就断开的情况。也就是onMessage根本没触发的情况。
 
请自行记录下日志就排查,在设置SESSION的地方记录日志,包括client_id。获取的地方也记录client_id日志。
 

  • 黑老怪 2019-05-14

    我是在websocket连接的时候设置Session,然后websocket连接成功后,客户端会立即发送登录信息给后台,然后删除定时的时候session就为空
    在onMessage里打印session为空,但是在onConnect里不为空

  • walkor 2019-05-14

    把整体代码发出来吧。

黑老怪

连接触发

public static function onConnect($client_id)
{
    try {
        // 连接到来后,定时10秒关闭这个链接,需要10秒内发认证并删除定时器阻止关闭连接的执行
        $auth_timer_id = GlobalTimer::add(2, function () use ($client_id) {
            //错误提示.
            //发送离线提示
            Send::sendToClientClose($client_id, 'server', 'Sign', 'auth', 400);
        }, null, false);
        $_SESSION = $auth_timer_id;
        $_SESSION     = $client_id;
    } catch (Throwable $e) {
        //错误日志记录
        Other::ErrorLog('Events', 'onConnect', $e);
        //workerman记录错误
        \GatewayWorker\Gateway::log($e);
    }
}

连接后客户端发送第一条消息就会出现空,如果我在客户端连接后延迟100毫秒就不会出现,或者只使用一个websocket连接也不会出现

public static function onMessage($client_id, $message)
{
    if ($_SESSION === null) {
        $_SESSION = $client_id;
    }
    Route::index($client_id, $message);
}```
**环境:**
两个websocket服务器
2个BusinessWorker进程 第一个为定时器第二个为业务逻辑
客户端为node.js 业务逻辑为
打开窗口会在nodejs后台生成ws连接
```js
const express = require('express');
const router = express.Router();
const request = require('request');
const webSocket = require("ws");
/* GET home page. */
router.get('/', function (req, res, next) {
    request({
        url: "http://poker3.freepks.com/robotGameData",
        method: "POST",
        json: true,
        headers: {
            "content-type": "application/json",
        },
        body: {id: '100000035'}
    }, function (error, response, body) {
        res.end(JSON.stringify(body));
        if (body.code === 200) {
            webSocketF(body.address, 1)
        }
    });

});
function webSocketF(address, roomId) {
    let ws = [];
    let msgId = 1;
    for (let a = 0; a < address.length; a++) {
        const websocketUrl = "ws://" + address.url;
        const token = address.token;
        ws = new webSocket(websocketUrl);
        ws.on("open", function () {
            // console.log(a);
            ws.send('{"type":"client","class":"Sign","method":"in","site":"web","msgId":"1","data":{"token":"' + token + '"}}')
        });
        ws.on("error", function (err) {
            console.log("error: ", err);
        });
        ws.on("close", function () {
            console.log(a);
            // console.log(ws.length);
        });
        ws.on("message", function (data) {
            msgId++;
            data = JSON.parse(data);
            route(ws, data, msgId, roomId);
        });
    }
}
function route(ws, data, msgId, roomId) {
    if (msgId === 2) {
        console.log(ws.length);
        //发送给游戏加入房间
        for (let a = 0; a < ws.length; a++) {
            ws.send('{"type":"client","class":"Room","method":"join","site":"hall","msgId":"2","data":{"roomId":' + roomId + '}}')
        }
    }
}
module.exports = router;

这是为了写游戏机器人 所以会模拟用户触发行为

  • 暂无评论
walkor 打赏

估计你的GatewayWorker版本低了,升级试下

  • 黑老怪 2019-05-14

    3.5.18的...

  • walkor 2019-05-14

    发个能重现问题的最精简的demo吧。代码片段看不出什么

年代过于久远,无法发表回答
×
🔝