之所以说”不完全解决”,是因为解决方式不能称之为”解决方案”,只是避免了这个问题的发生(尴尬)~
bug 现象描述
故障现象需要使用到多个客户端连接,才能看到效果。表现形式语言很难描述(跟前一个 修复 Socket.IO Multiple Sockets open after reconnect #430 那个一样很难描述,难道我的语文老师是体育老师兼职的??)。
业务很简单:每次有新的连接生成的 Socket 都会加入同一个 room 中去。然后:
Socket.id 为 A1 的客户端连接成功后,此时 room 中的 Socket 是
|
|
Socket.id 为 A2 的客户端连接成功后,此时 room 中的 Socket 是
|
|
刷新 A2,此时 room 中的 Socket 是
|
|
刷新 A2 again,此时 room 中的 Socket 是
|
|
刷新 A2 triple,此时 room 中的 Socket 是
|
|
如此不断重复刷新 A2 就会看到 room 中一会儿有 A1,一会没有。。。难以描述。。。
bug 成因分析
一开始是完全没有头绪,你要么都在 room 中,要么都不在,特么一下在一下不在的,真是无语。。。
没办法,只能去看 issues 了。翻来翻去忽然看到这么一句话 Rooms is not same in all process #2330,心中忽然一亮:莫不是多实例造成的?
回想起先前的 pm2 配置参数如下
|
|
启动 Node 实例时使用了 cluster mode,这时 pm2 会根据当前服务器的状态,尽可能的利用 CPU 多核的优势提高实例的工作能力。
这是 pm2 文档中的 原文:
The -i or instances option can be:
- 0 to spread the app across all CPUs
- -1 to spread the app across all CPUs - 1
- number to spread the app across number CPUs
当时这台服务器是双核的 CPU,因此按照这个配置策略启动的实例,在 pm2 里面其实是两个进程(Process)。问题一定出现在这里。
这就解释了为啥 A1 一会在一会不在,应该是 pm2 为了均衡多核 CPU 的工作负载,将客户端以轮询的方式命中两个进程导致的。
解决方案
找到问题,就好办了:调整 pm2 配置参数,强制使用一个进程运行实例
|
|
再次如前方法测试,room 里面乖乖的躺着全部连接上来的客户端了~
done~