我希望别人之前遇到过这个问题:
我已将Socket.IO配置为使用redis-store模块,该模块非常适合在广播到房间/发送事件时保持节点实例同步。但是我一直在测试失败点,似乎当redis实例重新启动时,节点服务器停止接收来自其他节点的消息。
以下是我如何设置socket.io客户端(在此代码之前创建redis连接)
// Setup the socket server for web clients
self.ioServer = socketIo.listen(9000);
self.ioServer.enable('browser client minification'); // send minified client
self.ioServer.set('log level', 3);
self.ioServer.set( 'store', new socketIo.RedisStore ({
redisPub: self.redisPub,
redisSub: self.redisSub,
redisClient: self.redisStore
})
);
实质上,每当redis崩溃/重启时,socket.io redis-store都无法继续通过redis将事件发送到其他节点服务器。
重新连接到redis服务器需要采取哪些特殊步骤吗?我花了很多时间来寻找解决这个问题的方法,但没有任何运气。
此致
-Ryan
答案 0 :(得分:3)
任何人都感兴趣的是我为上述问题实施的修复:
由于系统正在为socket.io节点使用集群,我正在捕获redis连接上的任何“end”事件(reidsPub,redisSub等)并终止分叉进程。在主进程中,我捕获子进程的退出并重新分叉。
另外,我还发现了redis和socket.io的redis-store的另一个恼人问题:如果没有与redis交换数据,redis连接最终会超时。为了解决这个问题,我必须实现一个简单的keep alive函数,该函数每15秒运行一次,与redis交换数据用于所有上述redis连接。
通常情况下,我可以使用默认的redis客户端重新连接逻辑,但由于我无法知道redis服务器是否实际重启,或者它只是暂停。
答案 1 :(得分:1)
我没有详细介绍redis-store的实现。我不相信默认情况下将带有redis的pub-sub备份到磁盘,如果服务器重新启动,则消息将丢失。除非redis-store已经为您做了同样的事情,否则除了使用pub-sub之外,您还可以使用列表或排序集来存储消息。
如果默认情况下不是由redis-store提供的,则需要确保列表/排序集不会增大太多,从而对性能产生负面影响。您可以考虑使用MULTI / EXEC(并查看ACK消息)事务进行ACID保护,并确保除非订阅者处理/使用消息,否则不会删除消息。
您可以随时查看其他消息服务器,例如ActiveMQ等,它们提供持久的(磁盘备份)消息队列/主题。
希望它有所帮助。