小白的踩坑记录——socket.io-解决多进程

需求:

利用socket.io实现多进程长连接,实时获取kafka数据

问题重现:

启动单个进程的时候,socket.io可以正常的获取到长连接进行实时数据,但是利用多个线程的时候就会报长连接404,并且下图已经清晰的显示了socket.io握手的错误:

小白的踩坑记录——socket.io-解决多进程_第1张图片

有图可见,ws连接建立之前多出了三个http的请求,而且是每三个http请求之后就会有ws请求,这就说明,socket.io没有直接建立ws连接方式,而是先通过http请求访问服务端的相关轮训配置信息以及sid,sid唯一标识连接,可理解为socketId。

为什么会出现这种情况呢?

当我们开启一个进程的时候,就不会出现这种404的报错,但是当我们启动了多个线程的时候就会出现这种问题。当前实例是用pm2启动的多线程,利用了pm2中的某种算法,但是这种算法socket.io并不支持,因此在socket.io客户端连接建立阶段发送的多个http请求,会被pm2定位到不同的worker进程中,总而言之,客户端多次请求的服务端进程不是同一个进程才导致的ws连接无法成功建立。

那怎么解决呢?

那么如何才能解决呢?最简单的方案就是确保客户端的每次请求都可以定位到同一个服务进程即可。

官方解决方法:利用nginx反向代理+iphash
官方地址: https://socket.io/docs/using-multiple-nodes/
本实例利用官网这种方式解决的,具体如下:

第一种方法:

nginx.conf

upstream io_nodes {
  ip_hash;
  server 127.0.0.1:3131;
  server 127.0.0.1:3132;
  server 127.0.0.1:3133;
}
server {
    listen 3000;
    server_name io.yourhost.com;
    location / {
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;
      proxy_http_version 1.1;
      proxy_pass http://io_nodes;
    }
}

app.js

import socketList from './src/router/socket';
const app = new Koa();
// socket - socket.io
const server = require('http').createServer(app.callback());
server.setMaxListeners(30);
const port = 3131 + parseIn(process.env.NODE_APP_INSTANCE);
socketList.initialize(port);

app的详细配置就不展示了...

export default server;
// pm2
server.listen(port, () => console.log(`Server started on port ${port}`));

vue重要代码

import VueSocketio from 'vue-socket.io';
Vue.use(VueSocketio, url);

第二种方法:

利用sticky-session插件

app.js

import socketList from './src/router/socket';
import sticky from 'sticky-session';
const app = new Koa();
// socket - socket.io
const server = require('http').createServer(app.callback());
server.setMaxListeners(30);
socketList.initialize(server);

app的详细配置就不展示了...

export default server;
// sticky
const options = {
  workers: 3
};
if (!sticky.listen(server, port, options)) {
  // Master code
  server.once('listening', () => {
    console.log('server started on 3000 port');
  });
} else {
  console.log('sticky listen');
  // Worker code
}

我是初次接触socket.io的小白,对socket.io的理解还不到位,对于文章当中的专业说法还不到位,如果有建议,我会非常开心的接受并修改的,也希望和大家分享我自己的浅见。

你可能感兴趣的:(socket-io)