分布式websocket,如何让命中不同服务器的人相互通信?

最近接触到websocket,需求很简单,利用websocket让用户参与一个1v1的小游戏。
环境是分布式部署,且每台服务器是多进程,web服务器使用nodejs,websocket框架选用了socket.io。

遇到的问题:
首先,在单服务器调研,在利用nodejs多进程(cluster)时,建立websocket时会出现400报错,后来发现了是多进程的问题,用户访问服务器时不能保证每次访问到相同的进程中,所以后台会报错"Session ID unknown",可能是socket.io为了保证偶尔有可能会变成long polling,必须保证前后台要传递一个session id,但是每次页面刷新时,重新发起websocket应该和上次的刷新前的websocket没关系了才对,也有可能是socket.io为了保证与服务器重连节省资源才引入了session id,不知道我的理解对不对。
在网上查找了大量的资料,也看了socket.io官网的推荐方案(http://socket.io/docs/using-multiple-nodes/),有两种:

nginx
利用配置ip_hash让用户每次都连接到固定的进程,没玩过nginx不太懂。

redis
看了网上最多的既成的推荐方案也是redis,之前没有接触过redis,不知道其运行原理,大概了解之后,发现他是一个key-value的持久化存储,与MemCache、mongoDB类似,官网给出的代码示例:

var io = require('socket.io')(3000);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));

示例很简单,把请求弄一个适配器转向到连接redis服务,但是原理是什么样的呢,共享内存的方案吗,不太懂所以也没下手。

最后我选用了一个比较傻的方案,在不同的子进程中启动websocket服务时选用了不同的端口,比如一台服务器8核,会有8个端口3001-3008,这样用户连接某个固定端口时就不会再出现400error了,但是用户命中到不同的端口后,相互之间如何通信仍然是个问题,这只是单台服务器实验,如果是集群,相互通信也是一个问题,而且关键是否需要每次用户都连接到同一个端口和同一台服务器呢?说到底,还是对websocket了解太少了,希望能在这里得到一点指导和帮助。

阅读 16.5k
5 个回答
新手上路,请多包涵

如果是用 Redis, 我猜测是使用 Redis 的订阅/发布功能实现,这样就能很好的解决不同服务器上用户相互通信的问题。

楼主你好最近我也在做websocket 分布式,但我做的是web站点的,用的框架是workerman ,也是多台服务器集群,
以下是我的理解:
如果我没没理解错误的话你的疑问应该就是不同服务器如何相互通信
我认为解决不同服务器通信在于共享数据,让每台websocket 接受到同样的数据,redis 的话就是内存共享。
抽象出来看的话每个进程如果需要通信,就是让他们接受的数据是一模一样的也就实现数据共享了websocket 只是负责传输数据而已。

具体的实现我也是推荐redis 。

题主这个问题解决的怎么样了?分享一下方案呗。

我大致看了一下楼主的问题。我的理解是楼主遇到了分布式的问题,想让用户在连WEBSocket的时候刷新等各种都不影响。我对socket.io仅仅是初步理解,我用的是PHP的一个解决方案(swoole)。

我大概说一下我的解决方案。因为目前仅仅是预留分布式构架,还没真正部署分布式,因此方案可能不完善,仅供参考。

我是借助普通的HTTP session来处理分布式的。

首先,我会让用户在普通的HTTP请求里登录,然后把登录的session存到redis里,让登录信息天然分布式。因为每次连接WEBSocket时都会先发一个普通的http请求,然后upgrade到websocket的,这个时候,登录的cookie是存在登录的key的,因为在websocket的open阶段是能读到这个cookie信息的,把这个区redis比对下,就知道登录否了。

  1. 放弃长轮训握手, 使用websocket握手, 这样只会有一条请求到特定的服务器, 同样某些不兼容的浏览器无法使用.
  2. 使用nginx做前端分发路由器ip_hash, 某个ip的请求统一发到某个端口处理

上面说的都要用socket.io-adapter来做适配,目的是为了不同端口(进程)的socket.io能互相通信

最后问问你是怎么让一个项目跑在多个端口的? 一个一个开起来 还是有什么更优雅的方法?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏