在 Heroku 上运行 EventMachine Worker +西纳特拉 + Twitter 流媒体 API?
我正在尝试了解使用 Sinatra 在 Heroku 上运行 eventmachine 所涉及的异步模式。简而言之,我想要实现的是:使用 em-http 创建一个到 twitter 流 api 的 http 请求,在 stream 回调上,解析并推送使用 websocket 向客户端发送推文。到目前为止,一切都很好。当同一个应用程序还需要提供网页服务时,就会出现问题。在我的 config.ru 中,除了其他 Bundler 内容之外,
require 'app'
run TwitterApp
还有我的应用程序文件中的 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
}
现在,似乎发生的情况是 run TwitterApp 永远不会到达,因为 EventMachine 使用 Reactor 模式并且永远不会回来。
或者,如果我尝试
App.run!
在 EM.run 块中执行操作,则一切都在本地运行良好并使用 ruby app.rb 运行,但使用 rackup 似乎运行服务器两次(一次使用 Thin,另一次使用 WEBrick),在 Heroku 上它崩溃了,
Error R11 (Bad bind) -> Process bound to port other than $PORT
Stopping process with SIGKILL
我在这里错过了一些非常微不足道的东西吗?
非常感谢!
I'm trying to get my head around the asynchronous pattern involved in running eventmachine on Heroku with Sinatra. In a nutshell, what I'm trying to achieve is this: using em-http create a http request to the twitter streaming api, on the stream callback, parse and push the tweet to clients using websockets. So far, so good. The problem arises when the same application also needs to serve webpages. In my config.ru I have, among other Bundler stuff,
require 'app'
run TwitterApp
Then in my app file, the EM block:
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
}
Now, what seems to be happening is that run TwitterApp never gets reached because EventMachine uses the Reactor pattern and never returns.
Alternately, if I try to do a
App.run!
within the EM.run block, everything runs fine locally and running using ruby app.rb, but using rackup it seems to run the server twice (once with thin and the other with WEBrick) and on Heroku it crashes with
Error R11 (Bad bind) -> Process bound to port other than $PORT
Stopping process with SIGKILL
Am I missing something very trivial here?
Thanks very much!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
为此,您可以运行 async_sinatra -- https://github.com/raggi/async_sinatra --并使用它的异步处理程序而不是自己滚动。
For this, you could just run async_sinatra -- https://github.com/raggi/async_sinatra -- and use its asynchronous handlers rather than rolling your own.
我在它自己的线程中运行反应器,这样它就不会阻塞主进程:
然后我通过
我仍在等待发现你需要有一个 Worker Dyno 来使用这种模式。
I run the reactor in it's own thread so that it doesn't block the main process:
I then run things via
I am still waiting to find out you need to have a Worker Dyno to use this pattern.
我对Eventmachine不太熟悉,但据我了解,Heroku尚不支持Websockets。像 travis-ci 这样的项目通过使用像 Pusher 这样的服务来为其 Websocket 提供服务来解决这个问题。
Heroku 上的 R11(错误绑定)错误意味着您必须确保您的 Web Worker 绑定到从 Heroku 获取的端口 (
ENV["PORT"]
)。我猜这可以确保 HTTP 路由受到支持。我希望这在某种程度上有所帮助。
I am not so familiar with Eventmachine, but as far as I understand it, Websockets are not yet supported on Heroku. Projects like travis-ci get around that by using a service like Pusher to serve their Websockets.
The R11 (bad bind) error on Heroku means, that you have to make sure that your web worker binds to the port that it gets from Heroku (
ENV["PORT"]
). This makes sure the HTTP routing is supported I guess.I hope this is helpful in some way.
您可以将您的应用程序分成多个服务器实例。应用程序 1 提供网页服务,应用程序 2 运行事件机服务器(两者都连接到同一个数据库)。您可以使用 Pusher 将其与 Web 套接字粘合在一起。
您能否粘贴完整的 Sinatra 应用程序的要点?
You could separate your app into multiple server instances. App 1 serves web pages and App 2 runs the event-machine server (both are connected to the same db). You can use Pusher to glue it all together with web sockets.
Could you paste a gist of the full Sinatra app?