Description
choerodon-starters 中的 choerodon-websocket-helper 对于 websocket 的长连接心跳并不能检测出链接的失效.
由于我们有很多集群需要管理,有些是通过公网连接.时不时会有集群认为是健康的,但是无法发送命令的集群发生.我查看了代码,直到最新的 devops tag 中仍然用的是 choerodon-websocket-helper 项目,其从0.7.1(我们用的)至当前的 0.11.1在这块代码几乎是一样的.
@Scheduled(initialDelay = 10*1000,fixedRate = 10*1000)
public void sendPing(){
List<Session> sessions = sessionRepository.allSessions();
for (Session session : sessions){
try {
session.getWebSocketSession().sendMessage(new PingMessage());
} catch (Exception e) {
sessionRepository.removeById(session.getUuid());
logger.error("remove disconnected ");
}
}
}
这里的心跳检测依赖发送是否成功,但是这里是有问题的.
用户空间的写入只是表示成功将数据从用户空间 copy 至内核空间而已,之后由 tcp 的协议处理器去发送.
所以这里我认为正常的做法,发送了 PingMessage得必须在限定时间内得到 PongMessage 响应才表示链接是健康的.
agent 直到最新的版本都是直接丢弃 PingMessage 没有做任何处理.
我认为正确的做法是应该 agent-devops 都需要发送 PingMessage 并等待对方的 PongMessage,达到阀值后(超时+次数)即认为链接不健康断开等待 agent 发起重连.
第二个问题,由于心跳就算正常处理了,但是仍然会有心跳确认中这个时间窗口链接已经失效了,但是在发送消息的时候虽然用的是 spring 的 websocket 实现,却没有实现
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception}
这个方法,这里建议应该最次要将链接断开等待发起重连.
如果可以,我可能会发起一个 PR,不过 master 中已经放弃了 choerodon-websocket-helper 改为了 choerodon-starts-websocket 并重新实现了,不过问题好像仍然存在.
由于我们仍然使用了 0.11.1 的 choerodon,所以我只能 fork 自己修改一下旧有的版本.