【问题标题】:How scalable are server-sent events in Rails?Rails 中服务器发送事件的可扩展性如何?
【发布时间】:2015-05-07 21:16:16
【问题描述】:

我正计划编写一个 Rails 应用程序,其中多个用户将使用带有 ActionController::Live 和 Puma 的服务器发送事件将更新信息推送给他们。我已经编写了一个测试应用程序,它似乎工作得很好。对于我正在做的事情,SSE 比 WebSockets 更有意义,因为大多数用户只是在“听”,而且 SSE 比设置 websockets-rails 更简单,这也取决于 Faye(在这种情况下,我会自己写Faye 之上的代码)。

我想知道 Rails 中服务器发送事件的可扩展性如何?这是在我将使用 Puma 的前提下,它为每个连接到 EventSource 的用户创建一个新线程。潜在地,这个应用程序旨在同时连接数十万用户,但 Puma 的默认线程限制是 16。我有什么理由不能将线程限制更改为 200,000?

【问题讨论】:

  • MS IE 中是否还缺少 SSE?
  • 我认为 Rails/Puma 堆栈遇到的挑战与任何堆栈相同。线程/用户听起来像是矫枉过正,但我​​对您的用例了解不足,无法发表评论。增加 puma 使用的线程显然会增加 cpu 利用率,并且受到 CPU 数量的限制。 16 是一个很好的默认值。 200,000 个线程太多了。
  • @adi-pradhan 完全同意你的看法。 Python + gevent 很好地处理了这个问题,很好奇 Ruby 最好的方法。
  • Gene - 有一个适用于 IE 的 SSE 的 polyfill。 Adi - 如果这是真的,那么 Rails 中 SSE 的当前示例和教程不切实际吗?他们都建议使用带螺纹的 Puma;超过最大线程限制,除非释放线程,否则新用户无法连接。在这种情况下,16 似乎是一个微不足道的数字,因为这意味着只有 16 个用户可以连接到事件源或同时发出其他请求。这是并发的高昂代价。

标签: ruby-on-rails ruby multithreading server-sent-events puma


【解决方案1】:

如果 Puma 为每个连接创建一个新线程,请不要使用它。您不仅要同时为数十万用户计划,而且如果它是一个 Web 应用程序,用户可以在多个浏览器选项卡中打开多个实例。甚至the SSE specification warns against the "multiple tabs" problem,因为浏览器可能对同时连接到一个主机的数量有自己的限制:

支持 HTTP 的每服务器连接限制的客户端可能会运行 如果每个页面都有 一个事件源到同一个域。作者可以使用 每个人使用唯一域名的相对复杂的机制 连接,或通过允许用户启用或禁用 基于每页的 EventSource 功能,或通过共享单个 使用共享工作者的 EventSource 对象。

使用连接不会阻塞的事件服务器。上面提到的 gevent,基于 Node JS 构建的东西或 Ruby 中的其他东西(我不知道,因此不能推荐任何东西)。

对于登陆此页面并可能会感到困惑的其他读者,Rich Peck 的回答是错误的。服务器发送事件不依赖于长轮询,也不每隔几秒发送一次请求。它们是长期存在的 HTTP 连接,无需在每次事件后重新打开连接。没有“对服务器的持续请求”。

【讨论】:

    【解决方案2】:

    关于每个客户端使用一个线程的 Puma 方法,假设每个服务器有 16 个线程的限制,也许您可​​以考虑水平扩展您的服务器?例如,如果您部署到亚马逊并设置 Elastic Load Balancing + Auto Scaler,您的基础设施应该能够根据需要接受尽可能多的客户端。还是我错了? 而且我猜想可以通过禁止每个客户端进行多个连接来解决多标签问题,如果用户打开一个新标签,则会显示适当的错误消息。

    【讨论】:

      【解决方案3】:

      我不确定线程​​问题,但根据经验,我可以给你一些关于 SSE 的想法


      上交所

      要考虑的最重要的事情是 SSE 依赖于 Javascript long polling,这意味着它会每隔几秒钟继续向您的服务器发送请求,以尝试“侦听”更新

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

      这里有一个很好的讨论:What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?

      --

      至少对我而言,这里的问题是,如果您不断向服务器发送请求,它不仅效率低下,而且在功能方面也非常受限

      pub/sub pattern 一样,如果您想向您的用户提供“实时”更新,您首先需要进行某种身份验证(我相信 SSE 不提供),并确保您有特定的“渠道”让这些用户为他们接收更新

      话虽如此,关于creating a chat application with SSE's here 的帖子很棒:

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


      推动者

      我们尽可能使用websockets

      不过,诀窍是您可以使用第三方 websock 提供程序,例如 Pusher。我与 Pusher 没有任何关系。我们已经将它们用于许多项目 - EPIC 服务

      使用 Pusher,您无需设置自己的 websocket 服务器即可接受并向您网站上的用户发送特定消息。您只需使用相同的 JS 设置(事件侦听器)连接到 Pusher 的服务,它只会连接到 Pusher 服务一次:

      然后,您只需“推送”到 Pusher API 即可将更新发送给您的用户。我们已经通过一个正在构建here 的分析应用程序进行了初步设置


      为了回答您的问题,我不知道 SSE 的可扩展性如何

      我倾向于从“大”互联网公司那里带头(作为如何“正确”做的示范),我还没有看到他们中的任何一个更喜欢 SSE 而不是 websockets。我可能错了,但他们都更喜欢 websockets

      【讨论】:

      • 感谢您提供的信息。安全对我来说不是什么大问题,因为所有用户都应该查看正在流式传输的信息。我选择 SSE 而不是 WebSocket 是因为简单,而且在这种情况下额外连接 (AJAX) 的数量很少。所以在现实中,唯一会发生的请求是来自客户端的初始事件源连接和不时发出的少量 AJAX 请求。
      猜你喜欢
      • 2015-08-08
      • 1970-01-01
      • 2020-05-13
      • 1970-01-01
      • 2017-06-17
      • 2019-04-07
      • 1970-01-01
      • 1970-01-01
      • 2015-10-24
      相关资源
      最近更新 更多