【问题标题】:Persistent/Keep-Alive HTTP Connection Using POST In Rails在 Rails 中使用 POST 的持久/保持活动 HTTP 连接
【发布时间】:2014-01-04 10:23:13
【问题描述】:

有没有办法维护/使用 Rails 中的 POST 命令的持久连接?

我想创建一个 API,我的应用程序可以在其中接受相当于来自外部服务的数据流(我正在编写这个外部服务,因此我可以在此处灵活地进行设计)。速度至关重要。我需要以每秒 1000+ 点的速度从外部来源获取信息。在与一些计算机科学家同行交谈时,有人提出了使用持久连接的想法,以便只需执行一次昂贵的 TCP 握手。使用外部服务中的库,然后我将创建多个推送到我的 rails 应用程序中的 POST 项目,然后逐个处理这些 POST 项目。

我对 rails 范例的理解是每个请求(POST、GET、PUT 等)都需要一个 TCP 连接。有没有一种方法可以利用一个 TCP 连接来获取多个 POST?

我目前正在使用以下内容:

  • Rails 3.2
  • Ruby 1.9.3(必要时可以切换到 2.0)

编辑

为了帮助澄清我的目标是什么:

我有一个每秒收集 1,000 个数据点的外部系统(3 个浮点数、一个时间戳和 2 个整数)。我想将该数据推送到我的 Ruby on Rails 服务器。我希望通过正确配置的系统,我可以实时使用 HTTP 堆栈(收集数据点时,我将其推送到我的 rails 服务器)。我还可以减慢这种传输速度,并将数据点组合在一起发送。我已经研究过使用消息队列,但我想看看是否可以在使用专门的队列 API 之前编写一个更“标准”的 HTTP API。

【问题讨论】:

  • 如果知道您通过POST 传输的具体内容会很有趣。如果可以将其放入多部分 MIME 消息中,则您可以流式传输请求,从而进一步减少开销。
  • @DaSourcerer 我更新了我的问题,希望这能让您了解我想要完成的工作。我从未听说过“流式传输”请求。我可以通过谷歌了解什么?
  • 谢谢。我必须说,这是一个最有趣的问题。我有一些想法可能会对你有所帮助。我会在时间允许的情况下更新我的答案。
  • 我已将我的流媒体创意添加到我的答案中。抱歉花了这么长时间:很可能我不是第一个有这个想法的人,但我找不到任何资源。我非常有信心这个解决方案符合所有相关的 RFC。

标签: ruby-on-rails http post stream keep-alive


【解决方案1】:

认为Net::HTTP::Persistent 库正是您要找的。还有this 库通过在持久连接上实现连接池更进一步。但由于听起来您只有一个 API 点,所以这可能有点过头了。

一些额外的想法:如果您真的研究原始速度,可能值得发送单个多部分 POST 请求以进一步减少开销。这将归结为实现reverse server push

为此,您的 Rails 应用需要接受 chunk-encoded 请求。这很重要,因为我们不断地将数据流式传输到服务器,而不知道生成的消息体最终会持续多长时间。 HTTP/1.1 要求所有消息(即响应 请求)要么进行块编码,要么具有由 Content-Length 标头指定的正文大小(参见 RFC 2616, section 4.4)。然而,大多数客户端更喜欢后一种选择,这会导致一些网络服务器不能很好地处理块编码的请求(例如,nginx 在v1.3.9 之前没有实现这个)。

作为一种序列化格式,我可以放心地推荐JSON,它的生成速度非常快并且被广泛接受。 RoR 的实现可以在here 找到。您可能想看看this 的实现以及它本身与流一起工作,因此可能更适合。如果您发现 JSON 不适合您的需求,请尝试MessagePack

如果您达到网络饱和状态,可能值得研究 request compression 的可能性。

将所有内容放在一起,您的请求可能如下所示(为了便于阅读,压缩和块编码被剥离):

POST /api/endpoint HTTP/1.1
Host: example.com
Content-Type: multipart/mixed; boundary="---boundary-"
Transfer-Encoding: chunked
Content-Encoding: deflate

---boundary-
Content-Type: application/json

{...}
---boundary-
Content-Type: application/json

{...}
---boundary---

mime 类型是multipart/mixed,因为我觉得它是最合适的类型。它实际上意味着消息部分具有不同的内容类型。但据我所知,这在任何地方都没有强制执行,所以multipart/mixed 在这里可以安全使用。 deflate 被选为 gzip 作为压缩方法,因为它不需要生成 CRC32 校验和。这可以提高速度(并节省几个字节)。

【讨论】:

  • 感谢您非常详细的回复。我对 HTTP 堆栈不是很熟悉。是客户端请求持久(分块)连接还是我需要在服务器上进行一些配置?
  • 这是客户端请求它,它是服务器需要支持它。很抱歉简短的回答,我在农村地区,没有稳定的连接。
  • 你知道配置是只在网络服务器中(我使用 nginx)还是我需要在 Rails 中检查一些设置?感谢到目前为止的所有帮助,顺便说一句。它非常有用。
  • 必须在服务器中配置请求压缩(如果它支持的话。我不确定 nginx 是否这样做,tbh)。分块编码需要足够新的 nginx 版本(见上文)。如果 nginx 不支持请求压缩,您可以尝试压缩单个消息部分并让 RoR 处理解压缩。 nginx 和所有相关的 RFC 都应该没问题。
【解决方案2】:

我知道你想要一个 HTTP 解决方案,但老实说,如果速度很关键,我会把 HTTP 排除在外。 Web 套接字似乎更好地适应了这个问题。

查看 Heroku 的示例应用:https://devcenter.heroku.com/articles/ruby-websockets

一般来说,请参阅 Twitter 流 API 以获取灵感:https://dev.twitter.com/docs/streaming-apis

最重要的是,您可以传输二进制数据而不是文本,进一步加快传输速度,然后让工作人员摄取和保存数据。

只要我的 2cents

【讨论】:

  • 我想我正在寻找类似 Twitter 的流 API 之类的东西,但这不是通过 HTTP 处理的吗?
  • 其实可以,但是长连接得由谁来配置。因此,如果您希望其他人打开连接以将数据注入您的服务器,他们必须建立一个持久连接。使用套接字,您只需要担心处理数据。
  • 我想我已经接近理解您的建议了。如果我错了,请纠正我:我将创建一个人们可以连接到的启用 WebSocket 的服务。然后他们会将信息推送到这个 WebSocket 服务,这个 WebSocket 服务会将信息推送到我的后端?
  • 是的,完全正确。后端应该异步处理。
猜你喜欢
  • 1970-01-01
  • 2010-11-01
  • 2011-04-28
  • 2011-02-03
  • 1970-01-01
  • 2012-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多