大家好,我是烤鸭:
怎么监控长链接服务器的稳定,除了探活服务之外,怎么保证长链接的收发正常,这篇文章考虑下这个。
问题来源
运营反馈部分直播间无法收到弹幕、点赞消息,第一时间进行复现,发现切换网络可以,但是不是所有人都可以。
怀疑是长连接服务器出问题了,重启后问题消失。
怎么监控呢,消息是否丢失?用户是否收到?
长链接实现
先谈谈实现方式,我们是基于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()) {
@Override
public void onOpen(ServerHandshake handshakedata) {
log.info("[websocket] 连接成功");
}
@Override
public void onMessage(String message) {
log.info("[websocket:" + url + "] 收到消息={}", message);
// 放到 ConcurrentHashMap 一会和发送后的进行对比
websocketPool.put(PREFIX_RECV_MSG + url, message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
log.info("[websocket] 退出连接");
}
@Override
public void onError(Exception ex) {
log.info("[websocket] 连接错误={}", ex.getMessage());
String msg = "[" + url + "][sub error]" + ex.getMessage();
// 发送报警消息
}
};
webSocketClient.connect();
// 记录 WebSocketClient 对象,发送后进行 close
websocketPool.put(url, webSocketClient);
return webSocketClient;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
验证方法
public void init() {
String uri = "localhost:8080";
// 随机生成群组id
String cStr = UUID.randomUUID().toString();
String protocol = "ws://";
if ("prod".equalsIgnoreCase(envValue)) {
protocol = "wss://";
}
// 1. 初始化 websocketclient
String 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和监控机制。