如今在 ruby 上制作异步 Web 应用程序有哪些好方法?
我正在寻找一个带有 WebSocket 组件的 web 应用程序,以及基于磨坊机架的前端。我最初的计划是使用 Camping 作为前端,在瘦网络上运行服务器,机架 config.ru
如下所示:
require 'rack'
require './parts/web-frontend'
require './parts/websocket'
AppStationary = Rack::File.new("./stationary")
run Rack::Cascade.new(AppWebSockets, AppWebPages, AppStationary)
AppWebSockets
由 websocket-rack 提供,效果很好。在没有 Upgrade: WebSocket
请求的情况下,它只是 404,并且该请求会级联到露营应用程序 AppWebPages
。
越来越明显的是,这个露营 Web 应用程序不可避免地需要访问 IO,以便使用常规 http 请求与 CouchDB 数据库进行通信。有很多方法可以执行 http 请求,包括一些与 eventmachine 兼容的异步库。如果我订阅回调,rack 返回,并且在我准备创建响应时页面已经响应。我希望能够使用 em-synchrony 通过 Ruby 1.9 的 Fibers 获得一些并发性 - 我刚刚了解了它 - 但找不到任何有关如何在 Thin 中使用 em-synchrony 的文档。
我遇到过一个名为 Goliath 的网络服务器,它声称与 Thin 类似,内置了 em 同步支持,但它缺少启动和测试服务器的命令行实用程序,并且似乎需要我将不同类型的文件写入到架起来,这是相当令人厌恶的。目前还不清楚它是否会支持 websocket-rack,目前仅指定支持 Thin。
有哪些好方法可以避免阻塞 IO,同时仍然使用熟悉的基于机架的工具(例如露营)以及访问 WebSockets?
I'm looking to build a webapp with a WebSocket component, and a run of the mill rack based frontend. My initial plan was to use Camping for the frontend, running the server on thin, with a rack config.ru
looking like this:
require 'rack'
require './parts/web-frontend'
require './parts/websocket'
AppStationary = Rack::File.new("./stationary")
run Rack::Cascade.new(AppWebSockets, AppWebPages, AppStationary)
AppWebSockets
is being provided by websocket-rack and works great. In the absence of an Upgrade: WebSocket
request it simply 404's and the request runs down the cascade to the camping app, AppWebPages
.
It's becoming clear that this camping webapp inevitably requires access to IO, to talk with the CouchDB database using regular http requests. There are plenty of ways to do http requests, including some async libraries compatible with eventmachine. If I subscribe to a callback, rack returns and the page has already responded by the time I'm ready to create a response. I'd like to be able to use em-synchrony to get some concurrency via Ruby 1.9's Fibers - which I've only just gotten my head around - but cannot find any documentation on how to make use of em-synchrony with Thin.
I've encountered a webserver called Goliath which claims to be similar to thin, with em-synchrony support baked in, but it lacks a command line utility to launch and test the server and seems to require I write a different sort of file to a rackup, which is quite distasteful. It also is unclear if it would even support websocket-rack, which only specifies support for Thin currently.
What are some good ways to avoid blocking IO while still making use of familiar rack based tools like camping, and having access to WebSockets?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
至于 Goliath,Goliath 是基于 Thin 的(我从 Thin 代码开始,以及从那里开始)。许多代码已经更改(例如使用 http_parser.rb 而不是 mongrel 解析器),但最初的基础是 Thin。
启动服务器只需执行 .rb 文件即可。该系统与 Sinatra 使用的系统相同(我借用了 Sinatra 的代码来使其工作)。如果需要,您还可以编写自己的服务器,如果您需要额外的控制,存储库中有示例。对于我们来说,我们希望启动尽可能简单,并且需要创建尽可能少的文件。因此,启动 .rb 文件并使用 God 启动/重新启动服务器效果很好。
使用 RSpec/Test::Unit 编写的测试并像平常一样运行测试文件。 Goliath 的测试将启动反应器并从单元测试向 API 发送真实请求(注意,这不会分叉,它使用 EM 在与测试相同的进程中运行反应器)。所有这些东西都包含在 goliath 提供的 test_helper 中。
Goliath 没有rackup 文件。您直接运行 .rb 文件。 Goliath 应用程序将中间件使用命令直接烘焙到 .rb 文件中。对于我们 PostRank 来说,这是定义服务器最简单、最清晰的方法。当您处理文件时,您可以看到所有 use 语句(以及它们使用的任何额外位),而不是拥有多个文件。对我们来说,这是一场胜利,您的里程可能会有所不同。
我不知道 websocket-rack 是否可以工作,但是,仓库中有一个分支可以直接将 websocket 支持烘焙到 Goliath 中。我已经有一段时间没有看过它了(有一些上游错误需要修复),但是启动并运行它应该不会太难,并且在上游修复后,将其合并到 master 中。
对于有关 em-synchrony 和 Thin 的问题,您应该能够在代码中包含 EM.synchrony {} 块。同步方法只是调用 EM.run 并将您的块包装在新的纤程中。如果反应堆已经在运行,EM 将立即执行传递的块。只要 Thin 已经启动了反应堆,就应该可以正常工作。
更新: websockets 分支已合并到 Goliath 主线中,因此如果您从 HEAD 运行,则 WebSocket 支持会直接融入到 Goliath 中。
In regards to Goliath, Goliath is based on Thin (I started with the thin code and when from there). A lot of the code has changed (e.g. using http_parser.rb instead of mongrel parser) but the original basis was Thin.
Launching the server is just a matter of executing your .rb file. The system is the same as Sinatra uses (I borrowed the code from Sinatra to make it work). You can also write you own server if you want, there are examples in the repo if you need the extra control. For us, we wanted the launching to be as simple as possible and require as few files created as possible. So, launching .rb file and using God to bringup/restart servers worked well.
Tests you write with RSpec/Test::Unit and run the test file as you normally would. The tests for Goliath will fire up the reactor and send real requests to the API from your unit tests (note, this doesn't fork, it uses EM to run the reactor in the same process as the tests). All this stuff is wrapped in a test_helper that goliath provides.
There is no rackup file with Goliath. You run the .rb file directly. The Goliath application has the middleware use commands baked straight into the .rb file. For us at PostRank, this was the easiest and clearest way to define the server. You had all of your use statements (with any extra bits they use) visible as you work on the file instead of having multiple files. For us, this was a win, your mileage may vary.
I have no idea if websocket-rack would work but, there is a branch in the repo for baking websocket support straight into Goliath. I haven't looked at it in a while (there were some upstream bugs that got fixed that were required) but it shouldn't be too hard to get it up and running and, with the upstream fixed, merged into master.
To your question about em-synchrony and thin, you should just be able to wrap an EM.synchrony {} block around your code. The synchrony method just calls down to EM.run and wraps your block in a new fiber. If the reactor is already running EM will just execute the passed block immediately. As long as Thin has already started the reactor this should work fine.
Update: The websockets branch as been merged into Goliath mainline, so there is WebSocket support baked straight into Goliath if you're running from HEAD.
以下是如何向 Camping 添加异步支持的示例:https://gist.github.com/1192720 (有关您必须在应用程序中使用的代码,请参阅 65)。也许我们应该把它包裹在宝石之类的东西里……
Here's an example of how to add async support to Camping: https://gist.github.com/1192720 (see 65 for the code you'll have to use in your app). Maybe we should wrap it up in a gem or something…
您看过 Cramp - http://cramp.in 吗? Cramp 是完全异步的,并且具有内置的 websockets 支持。
Have you looked at Cramp - http://cramp.in ? Cramp is fully async and has an in-built websockets support.