سؤال

I am attempting to get ready to move our environment to Rails 4 and working through all the issues. Regretfully we are currently on Centos 5.5 so there were some hurdles to jump through just to get Rails up and running. This included installing python 2.6 and node.js in order to get extjs working.

And now I am stuck. With a fresh rails 4.0.2 app I have simple ActionController::Live example working fine in development with Puma. But in production with Apache + Passenger it simply doesn't send the data back to the browser (Firefox)

production.rb has

config.allow_concurrency = true

Here is the HTML/JS in index.html.

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

});
</script>

Here is the controller:

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

I can see the request go out to the server in Firebug notice the spinner on /feed :

Firebug Request notice the spinner

Apache/Passenger Config has this:

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

The Apache logs don't show anything. Like it never connects to the server. Another weird thing is that curl from the command line works:

     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"}

I figure it must be something in Apache , but I am not sure.

هل كانت مفيدة؟

المحلول

Okay I finally figured this out by a pile of googling that lead me to an indication that mod_deflate ( used for compressing responses to the browser ) will interfere with non-buffered responses like text/event-stream.

Looking at my httpd.conf I found this:

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 turns on compression for all responses making the rest of the AddOutputFilterByType directives unnecessary. This was obviously a bug in the httpd.conf . I removed this line, and verified that compression was still working for html pages.

And now everything works great! As well as the dashing dashboard tool that I was trying to get going in the first place.

نصائح أخرى

We've experienced some similar issue when we wanted to push some notifications with the Rails Action::LiveController as the feature was released with Rails 4.0 - in development with Puma everything works fine, but in production the streams we're not closed. This was resulting in a steadily increasing number of processes. Back then we came back to a different solution.

But just today I started some research (very interesting SO answer by one of the Passenger authors: https://stackoverflow.com/a/4113570) on this topic again and ended up here - right after I've read that Phusion Passenger supports Concurrency and Multithreading only with the Enterprise version (Phusion Passenger Enterprise Features).

Is it possible that a production environment with an Apache2 Web Server integration Phusion Passenger Open Source Edition isn't suitable for Rails Live Streaming?

Honestly, I have no idea - but wanted to let you know of my thoughts on this.

To prevent the Server (nginx to be honest) from deflating in specific cases, we set

response.headers['Cache-Control'] = 'no-transform, no-cache, private'

Maybe one of these is enough ;)

Rails 5

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top