websocket 的 问题
目前服务端使用的是 swoole 的 websocket,用redis绑定用户与资源符fd。
用户可能多端登录,于是当用户登录 socket 后,用的 redis 类型是 set 类型,即 'user:5' => [fd1,fd2..],当服务端 onClose 时把当前 fd 从[fd1,fd2..] 中删除。
但运行中发现,可能有的用户下线,没有走 onClose,具体什么原因我不清楚,可能是应用被杀死,或者断网了。 自己组里的fd没有及时清除,导致[fd1,fd2..]中有无效的fd,或者根本就是别人的fd了,如果不加判断,会造成消息发送给了其他人。
不论在哪个步骤去检查整理[fd1,fd2..],筛选出属于自己的fd,都不能准确的判断当前用户是否在线,登录了多少个端。
没有好的思路,求助。
谢谢大家的回复。swoole服务器开启心跳检测对于我这个项目不太适合,因为app应用黑屏一段时间以后,客户端js的定时器ping会停止,但不代表这个链接已经关闭了。
我在服务端加了一个定时器,检查所有fd是不是websocket链接,发现非正常close的fd,$server->isEstablished($fd) 仍然返回true。
正在参考回帖中的超时未回复踢下线,没有回复就代表客户端收不到消息也不会提醒通知了,在不在线也就没意义了,稍后再回复。
最后采用服务器定时ping客户端,如果没有回复就剔除该 fd ,断网、主动退出、redis数据被清除的情况,盯了几个小时,数据正常,再观察看看。
大家说的都对,是我理解错了,服务器端开启心跳检测即可。
'open_tcp_keepalive' => 1,//Keep-Alive 的机制可以检测死连接
'tcp_keepidle' => 10, //30s没有数据传输就进行检测
'tcp_keepinterval' => 1, //1s探测一次
'tcp_keepcount' => 5, //探测的次数,超过5次后还没回包close此连接
就解决了,客户端甚至无需ping,客户端ping的目的是万一服务器清理了redis,或者fd和用户双向绑定不一致的异常情况。
到此解决,谢谢大家!
关于 LearnKu
推荐文章: