推荐 最新
一只臭美的Doggg

gateway-worker向uid发送消息前,如何判断uid是否已离线?

一、问题描述 我有一个场景,像是车场道闸那种收费系统 1.gateway-worker作为服务端,然后道闸系统是客户端,与服务端建立tcp长连接。(客户端会向服务端发送心跳,5s/次) 2.用户请求服务端,获取道闸上的金额,进行支付 3.支付完,道闸抬杆车辆驶离 "车场道闸连接模型 (1).jpg" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241118/1c8cc9027027da6f716bb0c9bac42578.png) 假设道闸客户端连接到gateway-worker的client_id是001,车场的客户端编号是A,那在客户端连接上服务端的时候,会进行client_id 001和编号A的绑定"Gateway::bindUid(001, 'A')"。那后续有用户发起http请求获取金额的时候,请求中也会传递车场编号A,那服务端会向客户端A发送tcp请求获取金额,代码示例"Gateway::sendToUid('A', json_encode($message));" 二、问题出现的环境背景及自己尝试过哪些方法 现在有一种情况,就是道闸系统有时候网络不好,老是断网,断网情况下,道闸客户端就没办法及时向服务端及时发送心跳包,服务端也不知道这个客户端A离线了,这时候如果有http请求进来,服务端会继续向客户端A发送请求获取金额,这时候就会导致进程阻塞,导致http请求一直在请求中,直接影响到后续的http请求也进不来 2.1 尝试的方案 1、在向客户端A发送请求前,检测客户端A是否离线 // client_id http请求client_id // uid http请求uid Gateway::bindUid($client_id, $uid); // A为车场客户端编号 $client_ids = Gateway::getClientIdByUid('A'); $status = Gateway::isUidOnline('A'); if (!$status || !$client_ids) { Gateway::sendToUid(http请求client_id, json_encode(['code' => 0, 'message' => '车场客户端已离线'])); return; } // 向客户端A发送请求 Gateway::sendToUid('A', json_encode($message)); 先检测客户端A状态。但是这种方法建立在client_id触发了onClose回调,像断网这种情况,客户端是没办法触发onClose回调 2、服务端向客户端发送心跳包检测客户端状态 我看官方文档可以通过服务端向客户端发送心跳包检测客户端状态,假设我设置心跳包3s/次,但是这种也会存在心跳包刚检测客户端正常,过了1s客户端因为断网离线了,这时候有http请求进来,服务端还不知道客户端连接不上了,还是会出现上面我所说的情况 你期待的结果是什么?实际看到的错误信息又是什么? 请问大家有合适的解决方案吗?

0
1
0
浏览量29