6

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.

digidigo
  • 2,534
  • 20
  • 26
  • have you checked the apache log files? – blueberryfields Mar 26 '14 at 19:05
  • interesting. Nothing in the access logs. So it isn't even reaching Apache? Strangely it works from curl – digidigo Mar 27 '14 at 16:52
  • maybe, it works from curl command line though. So what firewall setting would be triggering it? – digidigo Mar 27 '14 at 17:15
  • If I close the response stream then I get the data. But only at the end. So it doesn't appear to be firewall. It appears to be buffering. – digidigo Mar 27 '14 at 17:34
  • looks like it might be a clientside issue then. Are you using exactly the same version of the browser? could you be running into a cross site javascript request maybe? – blueberryfields Mar 27 '14 at 20:54
  • It works locally just fine, but that is using puma. I'll get apache passenger setup on my mac and see if the problem happens there. – digidigo Mar 28 '14 at 15:55
  • 1
    thanks @blueberryfields for simply letting me know I wasn't alone. I finally figured it out. mod_deflate was on for all requests which interfered with non-buffered responses. – digidigo Mar 29 '14 at 16:37

3 Answers3

5

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.

digidigo
  • 2,534
  • 20
  • 26
2

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.

Community
  • 1
  • 1
mbusch
  • 51
  • 2
  • 3
    I got it working with the open source version of passenger. Problem was mod_deflate, I added an answer below. Thanks for chiming in. – digidigo Mar 29 '14 at 16:38
0

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

Phil
  • 145
  • 8