在Heroku + Sinatra + Twitter Streaming API上运行EventMachine Worker?

时间:2011-05-20 05:32:37

标签: heroku sinatra eventmachine

我正试图了解使用Sinatra在Heroku上运行eventmachine所涉及的异步模式。简而言之,我想要实现的目标是:使用 em-http 创建一个http请求到twitter流API, stream 回调,解析和推送使用websockets向客户发送推文。到现在为止还挺好。当同一个应用程序也需要提供网页时,就会出现问题。在我的config.ru中,我有其他Bundler的东西,

require 'app'
run TwitterApp

然后在我的app文件中,EM块:

EM.run{
 class TwitterApp < Sinatra::Base {
       get '/' do
        haml :index
       end
 }
 http = EventMachine::HttpRequest.new(url, options).get :head=>{'Authorization' => [USERNAME, PASSWORD]}
 http.stream do |chunk|
    #parse tweet, push using websockets
  end
}

现在,似乎正在发生的事情是运行TwitterApp 永远不会到达,因为EventMachine使用Reactor模式并且永远不会返回。

或者,如果我尝试做

App.run!
在EM.run块中,一切运行正常并使用 ruby​​ app.rb 运行,但是使用 rackup 它似乎运行服务器两次(一次使用瘦而另一个用WEBrick)和Heroku上它崩溃了

Error R11 (Bad bind) -> Process bound to port other than $PORT
Stopping process with SIGKILL

我在这里错过了一些非常微不足道的事情吗?

非常感谢!

4 个答案:

答案 0 :(得分:3)

为此,您可以运行async_sinatra - https://github.com/raggi/async_sinatra - 并使用其异步处理程序而不是自己编写。

答案 1 :(得分:2)

我在自己的线程中运行reactor,这样它就不会阻塞主进程:

  if not EM.reactor_running?
    Thread.new {
      EM.run {
        logger.info "Starting EventMachine Reactor"
        EM.error_handler{ |e|
          logger.error "Error raised during event loop: #{e.message}"
          logger.error e.backtrace unless e.backtrace.nil?
        }
      }
    }
  else
    logger.info "Reactor already started"
  end

然后我通过

运行
 EM.next_tick { do_background_stuff }

我还在等待你发现需要一个Worker Dyno才能使用这种模式。

答案 2 :(得分:1)

我对Eventmachine并不熟悉,但据我所知,Heroku尚不支持Websockets。像travis-ci这样的项目通过使用像Pusher这样的服务来为他们的Websockets提供服务。

Heroku上的R11(错误绑定)错误意味着,您必须确保您的Web工作者绑定到从Heroku(ENV["PORT"])获取的端口。这样可以确保支持HTTP路由。

我希望这在某种程度上有所帮助。

答案 3 :(得分:0)

您可以将应用分成多个服务器实例。 App 1提供网页,App 2运行事件机器服务器(两者都连接到同一个数据库)。您可以使用Pusher将它们与网络套接字粘合在一起。

你能粘贴一整套Sinatra应用程序吗?