前言
最近在做一个类chatroom的模块,前端用的vue+vue-socket.io,chat服务器用nodejs+socketio搭的,通信的时候发现个问题。
当前端连接之后,node会生成一个id然后通过emit给前端并讲id加入一个Set里面,然而如果我前端页面刷新之后我的列表里面原来的id还在。这里我需要一个机制能够帮我检测节点是否存活,如果死掉了就把它从列表里面删了。
分析
我隐约记得以前软件设计与体系结构里面提到过类似的东西,我只记得两个方法的名词,一个是ping-echo,我估计大概是程序在某个特定的时间点向列表里面的所有节点发出ping,然后在规定的时间内等待节点echo,没收到的设置为死节点。另一个就是heartbeat了,每一个节点周期的向服务器发送心跳(heartbeat),如果服务器在一定时间内没有听到每个节点的心跳就认为它已经死了。
实战
现在我开始简单的实现一下心跳检测
node服务器
var io = require('socket.io')(2333);
var uuid = require('node-uuid');
var static = require('node-static');
var os = require('os');
// keeping track of connections
var sockets = {};
var heartbeat = new Set();
io.on('connection', function(socket) {
socket.on('getId', function() {
var id;
// determine an identifier that is unique for us.
do {
id = uuid.v4();
} while (sockets[id]);
// we have a unique identifier that can be sent to the client
console.log("dispatch id:" + id)
sockets[id] = socket;
socket.emit('yourId', id);
heartbeat.add(id);
console.log("now listeners number is: "+Object.getOwnPropertyNames(sockets).length)
})
// heart beats
socket.on('heartbeat', function(id){
heartbeat.add(id);
console.log('hear beat from: ' + id);
})
})
// sweep the dead socket
setInterval(function(){
for(var key in sockets) {
if(!heartbeat.has(key)) {
delete sockets[key];
}
}
heartbeat.clear();
console.log("after sweep listeners number is: "+Object.getOwnPropertyNames(sockets).length)
},10000)
vue代码(sockets是vue-socket.io组件里面的东西,基本等同于监听对应消息)
sockets: {
connect() {
console.log('connect')
this.$socket.emit('getId');
},
disconnect() {
console.log('disconnect')
},
yourId(id) {
let self = this;
this.myId = id;
console.log('id = ' + id);
setInterval(function() {
self.$socket.emit('heartbeat', self.myId)
},2000)
},
},
不足
其实这个不完全是心跳,因为清扫节点是周期的而不是每个节点都是10秒1次,也许对于不太实时或者单一客户端的系统这样写还勉强可以,但写完之后我在想这个实时性比较高而且多客户端的模块是不是用ping-echo来做这块会更好
网友评论