运行4核Amazon EC2实例(m3.xlarge),其中200,000个并发连接没有任何问题(每个核心为10-20%,内存为2 / 14GB)。无论如何,如果我向cpu-core上首先连接的所有用户发送消息,则在几毫秒内获得它,但最后连接的用户以1-3秒的延迟获得它,每个CPU核心在1-2秒内上升到100% 。我注意到这个问题,即使只是"只有" 50k并发用户(每核12.5k)。
如何减少延迟?
我尝试将redis-adapter更改为mongo-adapter,没有任何区别。
我使用此代码在多个cpu核心上获取粘性会话:
https://github.com/elad/node-cluster-socket.io
测试非常简单:客户端只是连接而不做任何事情。服务器只侦听消息并发送给所有人。
编辑:我在没有任何集群/适配器逻辑的情况下测试了单核,具有50k客户端和相同的结果。我在一个软件包中发布了服务器,单核服务器,基准测试和html-client:https://github.com/MickL/socket-io-benchmark-kit
答案 0 :(得分:1)
好的,让我们稍微分解一下。四个核心上有200,000个用户。如果分布完好,那么每个核心就有50,000个用户。因此,如果向给定用户发送消息需要每个CPU时间.1ms,那么将需要50,000 *。1ms = 5秒来发送它们。
如果您在此期间看到CPU利用率达到100%,那么瓶颈可能是CPU,也许您需要更多核心来解决问题。但是,也可能存在其他瓶颈,例如网络带宽,网络适配器或redis进程。因此,要立即确定的一件事是您的端到端时间是否与您拥有的集群/ CPU数量成正比?如果你降到2个核心,那么端到端的时间会加倍吗?如果你去8,它会减少一半吗?如果两者都是,这是个好消息,因为这意味着你现在可能只是遇到CPU瓶颈,而不是其他瓶颈。如果是这种情况,那么您需要弄清楚如何通过检查node-cluster-socket.io代码并找到优化您的特定情况的方法来提高跨多个集群的200,000个emits的效率。
最优化的代码可能是让每个CPU完成所有内容管理以准确收集所有需要发送给所有50,000个用户的内容,然后很快每个CPU都会发送一个紧密的循环来发送50,000个网络数据包一个接着一个接一个。我无法从redis适配器代码中判断这是否发生了。
最糟糕的情况是某些进程获取所有200,000个套接字ID然后进入循环以发送到每个套接字ID,在该循环中,它必须在redis上查找哪个服务器包含该连接然后发送消息到该服务器告诉它发送到该套接字。这比指示每个服务器只向所有它自己的连接用户发送消息要低效。
值得尝试弄清楚(通过研究代码)在这个频谱中,socket.io + redis组合是什么。
哦,如果您为每个套接字使用SSL连接,那么您也会在每次发送操作时使用一些CPU进行加密。有一些方法可以从常规CPU卸载SSL处理(使用其他硬件)。