Rails中的服务器推送事件有多可伸缩?

7
我计划创建一个Rails app,多个用户将使用ActionController::Live和Puma通过服务器发送事件接收更新的信息。我已经编写了一个测试app,并且似乎非常好用。对于我的需求来说,SSE比WebSockets更合理,因为大多数用户只是“监听”,而SSE比设置依赖于Faye的websockets-rails更简单(在这种情况下,我将只在Faye之上编写自己的代码)。
我想知道的仅仅是Rails中的Server-sent events的可扩展性如何?在这种情况下,我将使用Puma,针对每个连接到EventSource的用户创建一个新线程。潜在地,这个应用程序的目标是有成千上万的用户同时在线,但Puma默认的线程限制是16.是否有任何理由我不能将线程限制更改为200,000?

1
MS IE还没有支持SSE吗? - Gene
我认为你在Rails/Puma堆栈中遇到的挑战与任何堆栈相同。一个线程/用户听起来可能有些过度,但我不了解你的用例足够发表评论。增加Puma使用的线程显然会增加CPU利用率,并受到CPU数量的限制。16是一个很好的默认值。200,000个线程实在是太多了。 - adi-pradhan
@adi-pradhan 完全同意你的观点。Python + gevent 可以很好地解决这个问题,对 Ruby 最佳方法很感兴趣。 - Martin Konecny
Gene - 有一个适用于IE的SSE填充程序。 Adi - 如果是这样,那么Rails中关于SSE的当前示例和教程是否不切实际?它们都建议使用线程化的Puma;如果超过最大线程限制,则新用户无法连接,除非释放线程。在这种情况下,16似乎是相当微不足道的数字,因为这意味着只有16个用户可以同时连接到事件源或发出其他请求。这是并发性的一个非常高的代价。 - Ten Bitcomb
3个回答

6
如果Puma为每个连接创建新线程,请不要使用它。不仅要为成千上万的用户做规划,而且如果将其用于Web应用程序,用户可以在多个浏览器选项卡中打开多个实例。即使SSE规范警告“多个选项卡”问题,因为浏览器可能有自己对一个主机的同时连接数限制:the SSE specification warns against the "multiple tabs" problem
使用事件驱动的服务器,其中连接不会阻塞。上述gevent、Node JS或Ruby中的其他内容(我不知道,因此无法推荐任何内容)。
为了避免其他读者误解,Rich Peck的答案是错误的。服务器发送的事件不依赖于长轮询,也没有每隔几秒钟就发送请求。它们是长期持久的HTTP连接,无需在每个事件之后重新打开连接。没有“向服务器发出常量请求”。

这可能值得研究一下Falcon服务器对于Ruby来说,它是一个事件驱动的服务器。 - steve

1
关于Puma使用每个客户端一个线程的方法,考虑到每个服务器有16个线程的限制,也许你可以考虑水平扩展你的服务器?比如,如果你部署在亚马逊并设置弹性负载均衡+自动扩缩容,你的基础设施应该能够接受所需的所有客户端。或者我错了吗? 我想多个选项卡的问题可能通过禁止每个客户端的多个连接来避免,如果用户打开新的选项卡,则显示适当的错误消息。

-4

我不确定关于线程问题,但是从经验上讲,我可以给你一些有关SSE的想法。


SSE

最重要的是,SSE依赖于Javascript 长轮询,这意味着它将继续每隔几秒钟向您的服务器发送请求,以尝试“监听”更新。

在设置SSE eventlistener时,请检查它-它将每隔几秒钟向您的服务器发送请求。连接不会永久保持。

这里有一个很好的讨论:什么是长轮询、Websockets、Server-Sent Events(SSE)和Comet?

--

在我看来,这里的问题是,如果您向服务器发送不断的请求,不仅效率低下,而且功能也非常受限。

就像发布/订阅模式一样,如果您想向用户提供“实时”更新,首先需要某种身份验证(我认为SSE不提供此功能),并确保您有特定的“频道”供这些用户接收更新适用于他们

话虽如此,这里有一篇关于使用SSE创建聊天应用程序的绝佳文章

enter image description here

我只使用SSE来发送站点范围的更新,因为我更喜欢拥有一个单一的连接(websocket),可以进行身份验证并填充用户特定的数据。


推送器

我们尽可能使用WebSockets

关键是,您可以使用第三方WebSockets提供程序,例如Pusher。我与Pusher没有任何关联,但我们已将其用于多个项目 - EPIC服务。

使用Pusher,您将能够向站点上的用户接受和传递特定的消息,而无需设置自己的WebSockets服务器。您只需使用相同的JS设置(事件侦听器)连接到Pusher的服务,它将仅一次连接到Pusher服务: enter image description here

然后,您只需通过向Pusher API“推送”即可向用户发送更新。 我们正在构建一个分析应用程序,并在此处试行此功能here


回答你的问题,我不知道SSE的可扩展性如何。
我倾向于从“大型”互联网公司(作为如何正确处理的演示)中获取灵感,并且我还没有看到他们中的任何一个更喜欢SSE而不是Websockets。我可能错了,但他们都更喜欢Websockets。

感谢您提供的信息。对我来说,安全性不是太大的问题,因为正在流传的信息应该被所有用户查看。在这种情况下,我选择SSE而不是WebSockets,因为它更简单,并且额外连接(AJAX)的数量很少。因此,实际上只会发生来自客户端的初始事件源连接和偶尔的一些AJAX请求。 - Ten Bitcomb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接