sinatra - 使用 Sinatra Server Sent Events 流时如何提高并发性

标签 sinatra eventmachine thin server-sent-events puma

我正在构建一个 Rack 中间件,它订阅 Redis channel 并使用 Server Sent Events 将消息推送到客户端。 Sinatra provides a nice DSL for doing this.我有一个工作示例,但是,我遇到的问题是一旦达到 7 或 8 个客户端,性能就会大幅下降。在尝试在请求之间重用 Redis 连接时,我还遇到了服务器“死锁”的问题。

我正在使用 Thin 来为应用程序提供服务(它在后台使用 EventMachine)。我认为 Sinatra DSL 已经使用 EventMachine 处理并发,但也许这是我需要自己实现的东西?我不想限制自己只使用基于 EventMachine 的服务器(Thin,Rainbows!),以防有人想使用像 Puma 这样的多线程服务器。我应该如何提高代码的并发性?

require 'redis'
require 'sinatra/base'

class SSE < Sinatra::Base

  def send_message(json)
    "id: #{Time.now}\n" +
    "data: #{json}" +
    "\r\n\n"
  end

  get '/channels/:id/subscribe', provides: 'text/event-stream' do
    channel_id = params['id']
    stream(:keep_open) do |connection|
      Redis.new.subscribe("channels:#{channel_id}") do |on|
        on.message do |channel, json|
          connection << send_message(json)
        end
      end
    end
  end

end

最佳答案

想到了一些事情,所以我将不分先后地重复这些事情。

I'm using Thin to serve the app (which uses EventMachine under the hood). I thought that the Sinatra DSL already handled the concurrency with EventMachine, but maybe this is something that I need to implement myself?

你是对的,Thin 使用 EventMachine。但是,EventMachine(或任何其他 react 器)的问题是,一旦执行同步操作,您就会停止整个 react 器。因此,要真正获得您期望的并发性,您需要在整个应用程序中继续使用 EventMachine。

结帐 em-hiredis对于支持发布/订阅的 EventMachine 就绪 Redis 客户端。

I don't want to restrict myself to only EventMachine based servers (Thin, Rainbows!) in case someone wants to use a multi-threaded server like Puma

从未尝试过我要说的内容,但我认为在没有 EventMachine 的服务器中使用 EventMachine 不会有问题。请记住启动您自己的 EM。也许在 config.ru 中?

I have also run into issues with "dead-locking" the server when trying to reuse a Redis connection between requests

我相信您遇到这种情况的原因是因为每次调用“/channels/:id/subscribe”都会打开与 Redis 的新连接。您只能打开这么多。考虑将 Redis.new 重构为应用程序的共享连接。只打开一次。单个 Redis 连接应该能够处理多个发布/订阅。

一些想法,希望对您有所帮助。

关于sinatra - 使用 Sinatra Server Sent Events 流时如何提高并发性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18063609/

相关文章:

ruby - 使用 Mechanize 的异步请求

ruby - 为什么这个 EventMachine Synchrony hiredis 示例返回 DefaultDefferable,而不是请求中的值?

ssl - 为什么 Rails 在开发中默认使用 SSL?

ruby - 瘦找不到 pg_ext

rubygems - 无法激活 sinatra-1.4.7,因为 rack-2.0.1 与 rack (~> 1.5) 冲突

ruby - 403 禁止 nginx + passenger + sinatra

javascript - 无法在 Coffeescript 上的 Rickshaw Graph 上显示月份名称

ruby - 具有 em-synchrony 的 EventMachine 我需要正确地限制我的 http 请求

ruby-on-rails - Thin + Nginx + 上传模块 + 上传进度模块

ruby - 如何提高我的 AWS RDS Postgres 性能?