大家好,我是烤鸭:
怎么监控长链接服务器的稳定,除了探活服务之外,怎么保证长链接的收发正常,这篇文章考虑下这个。
问题来源
运营反馈部分直播间无法收到弹幕、点赞消息,第一时间进行复现,发现切换网络可以,但是不是所有人都可以。
怀疑是长连接服务器出问题了,重启后问题消失。
怎么监控呢,消息是否丢失?用户是否收到?
长链接实现
先谈谈实现方式,我们是基于nchan做的,之前也写过一篇文章。
https://blog.csdn.net/Angry_Mills/article/details/120068037
每次pub一条消息都会发布到redis,通过redis的发布订阅模式,不同的节点订阅后进行消息分发。
监控怎么加
客户端没收到消息的话,是建联的时候出错,还是建联成功一直没收到消息。
画一个简单的流程图,和监控可能加在哪里。
客户端加:
sub时候报错,进行错误上报,收到错误日志后进行报警。
服务端加:
发送到nchan服务器失败,进行报警。
发送到nchan服务器成功,redis中未有对应的消息,报警。
还有一种情况就是个人用户没收到消息,这种怎么监控。
建联了100个用户,只有1个用户没收到,网络原因?sub通道关闭了?nchan本身处理问题?
没什么好的方案,只能想办法记录当前建联了多少ip,以及发送了多少ip,进行比对,这种情况本身发生的几率不高。
服务端监控方案
pom中添加包
<dependency><groupId>org.java-websocket</groupId><artifactId>Java-WebSocket</artifactId><version>1.3.5</version>
</dependency>
定时任务进行建联+消息发送和接收校验,看看是否有丢消息的情况,同时还可以探活长连接服务器
public WebSocketClient webSocketClient(String url, String vid) {try {WebSocketClient webSocketClient = new WebSocketClient(new URI(url), new Draft_6455()) {@Overridepublic void onOpen(ServerHandshake handshakedata) {log.info("[websocket] 连接成功");}@Overridepublic void onMessage(String message) {log.info("[websocket:" + url + "] 收到消息={}", message);// 放到 ConcurrentHashMap 一会和发送后的进行对比websocketPool.put(PREFIX_RECV_MSG + url, message);}@Overridepublic void onClose(int code, String reason, boolean remote) {log.info("[websocket] 退出连接");}@Overridepublic void onError(Exception ex) {log.info("[websocket] 连接错误={}", ex.getMessage());String msg = "[" + url + "][sub error]" + ex.getMessage();// 发送报警消息}};webSocketClient.connect();// 记录 WebSocketClient 对象,发送后进行 closewebsocketPool.put(url, webSocketClient);return webSocketClient;} catch (Exception e) {e.printStackTrace();}return null;
}
验证方法
public void init() {String uri = "localhost:8080";// 随机生成群组idString cStr = UUID.randomUUID().toString();String protocol = "ws://";if ("prod".equalsIgnoreCase(envValue)) {protocol = "wss://";}// 1. 初始化 websocketclientString subUrl = protocol + uri + "/subscribe?integer=" + cStr;webSocketClient(subUrl, cStr);// 2. pub 消息String pubUrl = "http://" + uri + "/pubsub?integer=" + cStr;String message = UUID.randomUUID().toString();// 2.1 pub一次验证一次,pub就是https发送nchan负载//pub(pubUrl, message);try {// 5秒后验证sub端是否和pub端结果一致Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}// 2.2 验证结果String subUrlMsg = PREFIX_RECV_MSG + protocol + uri + "/subscribe?integer=" + cStr;String recvMsg = (String) websocketPool.get(subUrlMsg);if (!message.equalsIgnoreCase(recvMsg)) {String msg = "[" + subUrl + "][sub error][message receive fail][send msg]=" + message+"[recv msg]=" + recvMsg;// 不一致的话,报警}// 4. 销毁WebSocketClient webSocketClient = (WebSocketClient) websocketPool.get(subUrl);webSocketClient.close();}
报警截图:
可以看到确实有丢消息的情况,不过概率不高。
总结
nchan虽然是基于nginx的,性能和效率好,不过确实有些黑盒,不太好监控和二次开发。
以后还得考虑换一套框架,进行更完善的api和监控机制。