socket.io与cluster
在线上系统中,需要使用node的多进程模型,我们可以自己实现简易的基于cluster模式的socket分发模型,也可以使用比较稳定的pm2这样进程管理工具。在常规的http服务中,这套模式一切正常,可是一旦server中集成了socket.io服务就会导致ws通道建立失败,即使通过backup的polling方式仍会出现时断时连的现象,因此我们需要解决这种问题,让socket.io充分利用多核。
在这里之所以提到socket.io而未说websocket服务,是因为socket.io在封装websocket基础上又保证了可用性。在客户端未提供websocket功能的基础上使用xhr polling、jsonp或forever iframe的方式进行兼容,同时在建立ws连接前往往通过几次http轮训确保ws服务可用,因此socket.io并不等于websocket。再往底层深入研究,socket.io其实并没有做真正的websocket兼容,而是提供了上层的接口以及namespace服务,真正的逻辑则是在“engine.io”模块。该模块实现握手的http代理、连接升级、心跳、传输方式等,因此研究engine.io模块才能清楚的了解socket.io实现机制。
场景重现
服务端采用express+socket.io的组合方案,搭配pm2的cluster模式,实现一个简易的b/s通信demo:
app.js
var path = require('path');
var app = require('express')(),
server = require('http').createServer(app),
io = require('socket.io')(server);io
.on('connection', function(socket) {
socket.on('disconnect', function() {
console.log('/: disconnect-------->')
});
socket.on('b:message', function() {
socket.emit('s:message', '/: '+port);
console.log('/: '+port)
});
});
io.of('/ws')
.on('connection', function(socket) {
socket.on('disconnect', function() {
console.log('/ws: disconnect-------->')
});
socket.on('b:message', function() {
socket.emit('/ws: message', port);
});
});
app.get('/page',function(req,res){
res.sendFile(path.join(process.cwd(),'./index.html'));
});
server.listen(8080);
index.html
<script>
var btn = document.getElementById('btn1');
btn.addEventListener('click',function(){
var socket = io.connect('http://127.0.0.1:8080/ws',{
reconnection: false
});
socket.on('connect',function(){
// 发起“脚手架安装”请求
socket.emit('b:message',{}); socket.on('s:message',function(d){
console.log(d);
});
});
socket.on('error',function(err){
console.log(err);
})
});
</script>
pm2.json
{
"apps": [
{
"name": "ws",









