简单 Rails 4 ActionController::Live 示例不适用于 Apache + Passenger

Posted

技术标签:

【中文标题】简单 Rails 4 ActionController::Live 示例不适用于 Apache + Passenger【英文标题】:Simple Rails 4 ActionController::Live example not working with Apache + Passenger 【发布时间】:2014-04-22 04:31:13 【问题描述】:

我正在尝试准备将我们的环境迁移到 Rails 4 并解决所有问题。遗憾的是,我们目前使用的是 Centos 5.5,所以为了让 Rails 启动和运行,需要克服一些障碍。这包括安装 python 2.6 和 node.js 以使 extjs 正常工作。

现在我被困住了。使用新的 rails 4.0.2 应用程序,我有一个简单的 ActionController::Live 示例,在 Puma 开发中运行良好。但是在使用 Apache + Passenger 的生产环境中,它根本不会将数据发送回浏览器 (Firefox)

production.rb 有

config.allow_concurrency = true

这是 index.html 中的 HTML/JS。

<script>
jQuery(document).ready(function()
   var source = new EventSource("/feed");
   source.addEventListener('update', function(e)
     console.log(e.data);
   );

);
</script>

这里是控制器:

class LiveController < ApplicationController
  include ActionController::Live
  respond_to :html
  def feed
    response.headers['Content-Type']      = 'text/event-stream'
    response.headers['X-Accel-Buffering'] = 'no'

    while true do 
      response.stream.write "id: 0\n"
      response.stream.write "event: update\n"
      data = time: Time.now.to_s.to_json
      response.stream.write "data: #data\n\n"
      sleep 2
    end
  end
end

我可以看到请求在 Firebug 中发送到服务器,请注意 /feed 上的微调器:

Apache/Passenger Config 有这个:

LoadModule passenger_module /usr/local/ordernow/lib/ruby/gems/2.0.0/gems/passenger-4.0.27/buildout/apache2/mod_passenger.so
PassengerRoot /usr/local/ordernow/lib/ruby/gems/2.0.0/gems/passenger-4.0.27
PassengerDefaultRuby /usr/local/ordernow/bin/ruby
RailsAppSpawnerIdleTime 0
PassengerMinInstances 1

Apache 日志不显示任何内容。就像它永远不会连接到服务器一样。另一个奇怪的事情是命令行中的 curl 有效:

     curl -k -i -H "Accept: text/event-stream" https://10.47.47.44:8446/feed
HTTP/1.1 200 OK
Date: Thu, 27 Mar 2014 16:52:52 GMT
Server: Apache/2.2.20 (Unix) mod_ssl/2.2.20 OpenSSL/1.0.0e Phusion_Passenger/4.0.27
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
X-Accel-Buffering: no
Cache-Control: no-cache
X-Request-Id: 46fca6bb-4c6a-49f4-b0d6-2cbc5f0a63a5
X-Runtime: 0.002065
X-Powered-By: Phusion Passenger 4.0.27
Set-Cookie: request_method=GET; path=/
Status: 200 OK
Vary: Accept-Encoding
Transfer-Encoding: chunked
Content-Type: text/event-stream

id: 0
event: update
data: "time":"2014-03-27 10:52:52 -0600"

id: 0
event: update
data: "time":"2014-03-27 10:52:54 -0600"

我认为它一定是 Apache 中的东西,但我不确定。

【问题讨论】:

你检查过 apache 日志文件了吗? 有趣。访问日志中没有任何内容。所以它甚至没有到达Apache?奇怪的是它适用于 curl 也许,它可以在 curl 命令行中运行。那么什么防火墙设置会触发它呢? 如果我关闭响应流然后我得到数据。但只是在最后。所以它似乎不是防火墙。它似乎正在缓冲。 感谢@blueberryfields 让我知道我并不孤单。我终于弄明白了。 mod_deflate 对所有干扰非缓冲响应的请求启用。 【参考方案1】:

好吧,我终于通过一堆谷歌搜索弄明白了这一点,这让我发现 mod_deflate(用于压缩对浏览器的响应)会干扰非缓冲响应,如文本/事件流。

查看我的 httpd.conf 我发现了这个:

SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpg|png|ico|zip|gz)$ no-gzip

# Restrict compression to these MIME types
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/css

# Level of compression (Highest 9 - Lowest 1)
DeflateCompressionLevel 9

SetOutputFilter DEFLATE 为所有响应打开压缩,从而使其余的 AddOutputFilterByType 指令变得不必要。这显然是 httpd.conf 中的一个错误。我删除了这一行,并验证压缩仍然适用于 html 页面。

现在一切正常!以及我一开始就尝试使用的仪表板工具。

【讨论】:

【参考方案2】:

当我们想要使用 Rails Action::LiveController 推送一些通知时,我们遇到了一些类似的问题,因为该功能是在 Rails 4.0 中发布的 - 在 Puma 的开发中一切正常,但在生产中我们不是关闭。这导致进程数量稳步增加。 那时我们又回到了不同的解决方案。

但就在今天,我再次开始对这个主题进行一些研究(一位乘客作者非常有趣的 SO 回答:https://***.com/a/4113570)并最终来到这里——就在我读到 Phusion Passenger 仅支持并发和多线程之后企业版 (Phusion Passenger Enterprise Features)。

具有 Apache2 Web 服务器集成 Phusion Passenger 开源版的生产环境是否可能不适合 Rails 直播?

老实说,我不知道 - 但想让你知道我对此的想法。

【讨论】:

我让它与乘客的开源版本一起工作。问题是 mod_deflate,我在下面添加了一个答案。感谢您的参与。

以上是关于简单 Rails 4 ActionController::Live 示例不适用于 Apache + Passenger的主要内容,如果未能解决你的问题,请参考以下文章

简单 Rails 4 ActionController::Live 示例不适用于 Apache + Passenger

ruby 一个简单的脚本来解码Rails 4会话cookie

ruby 一个简单的脚本来解码Rails 4会话cookie

无法验证 CSRF 令牌真实性 Rails 4.1

将 Rails 4 降级到 3.2

数据类型 JS 的 Rails 4 远程请求回调问题