Phusion white papers Phusion overview

Technology Preview: Introducing Flying Passenger

By Hongli Lai on July 3rd, 2013

Phusion Passenger is software that deploys Ruby and Python web apps, by integrating into Apache and Nginx and turning them into a fully-featured application server. It is very fast, stable and robust and thus used by the likes of New York Times, AirBnB, Symantec, Pixar, etc. It comes with many features that make your life easier and your application perform better.

“Flying Passenger” is a technology which allows one to decouple Phusion Passenger’s life time from the web server’s life time, so that the web server can be independently restarted from Phusion Passenger, and from any of the application processes served by Phusion Passenger.

Normally, Phusion Passenger starts together with the web server, and shuts down together with the web server. The advantages of this default behavior is that it makes Phusion Passenger easy to administer: one only has to deal with the web server process and can expect all relevant processes to be cleaned up after a web server shut down. However this also brings about a disadvantage: every time one restarts the web server (e.g. to make a minor configuration change), Phusion Passenger and all its application processes also get restarted.

This problem is solved by “Flying Passenger”, which is an advanced mode of operation in Phusion Passenger that allows the web server to be indepedently restarted from Phusion Passenger. When this mode is enabled:

  • One must start Phusion Passenger separately from the web server, namely by starting the Flying Passenger daemon. This daemon must — to an extent — be separately configured and managed from the web server.
  • The web server must be configured to forward requests to the Flying Passenger daemon.
  • You should beware of the caveats and limitations, which will be described in this article.

Flying Passenger is fully documented in the Phusion Passenger manual. This article serves as an introduction.

Differences with existing reverse proxy setups

You may be wondering how this differs from existing reverse proxy setups with other application servers, e.g. Nginx+(G)Unicorn, Nginx+Puma, or Nginx+uWSGI. Most other application servers can serve only one application per instance. Flying Passenger works just like Phusion Passenger for Nginx: it can serve multiple applications. Almost all Phusion Passenger for Nginx features are preserved in the Flying Passenger mode: dynamic process scaling, process supervision, user switching, real-time response buffering, etc all work as one is used to in Phusion Passenger for Nginx. However, Flying Passenger is only partially configured through the Nginx configuration file; some configuration is set through command line options.

Python users may see parallels between Flying Passenger’s mode of operation and uWSGI Emperor’s.

Availability

Flying Passenger will become available in the Enterprise variant of the next Phusion Passenger release, namely version 4.0.6.

At this time, this feature is only available in Phusion Passenger for Nginx. You must have Phusion Passenger for Nginx properly installed. Flying Passenger is not available in Phusion Passenger for Apache, and also not in Phusion Passenger Standalone.

Basic usage

Start the Flying Passenger daemon by invoking the flying-passenger command. The only required option is --socket-file. Depending on whether you wish to enable User Switching, you have to start flying-passenger with root privileges or not.

$ sudo flying-passenger --socket-file=/var/run/flying-passenger.sock
I, [2013-06-14T09:10:13.095339 #77179]  INFO -- : Welcome to Flying Passenger 4.1.0
I, [2013-06-14T09:10:13.095339 #77179]  INFO -- : Starting PassengerWatchdog...
I, [2013-06-14T09:10:13.097036 #77179]  INFO -- : PassengerWatchdog started on PID 77181
...
I, [2013-06-14T09:10:13.129017 #77179]  INFO -- : PassengerWatchdog initialized properly
I, [2013-06-14T09:10:13.129127 #77179]  INFO -- : Flying Passenger up and listening on /var/run/flying-passenger.sock!

Now configure Phusion Passenger for Nginx to make use of the Flying Passenger daemon, by setting the passenger_fly_with option to the socket filename:

http {
    ...
    passenger_fly_with /var/run/flying-passenger.sock;
    ...
}

After (re)starting Nginx, Nginx + Flying Passenger is fully operational:

$ sudo /path-to/nginx

You can test it by adding a virtual host for a web app:

http {
    ...

    server {
        listen 80;
        server_name www.foo.local;
        root /webapps/foo/public;
        passenger_enabled on;
    }
}

Verify that it works by making an HTTP request to it:

$ curl http://www.foo.local/

Now let’s verify that restarting the web server does not restart the just-spawned application process. Run passenger-status to obtain the PID of the application process:

$ sudo passenger-status
Version: 4.1.0
Date   : 2013-06-14 09:21:51 -0400
----------- General information -----------
Max pool size : 6
Processes     : 1
Requests in top-level queue : 0

----------- Application groups -----------
/webapps/foo#default:
  App root: /webapps/foo
  Requests in queue: 0
  * PID: 77283   Sessions: 0       Processed: 1       Uptime: 2s
    CPU: 1%      Memory  : 8M      Last used: 2s ago

As you can see, the PID of the application process is 77283. Now let’s see what happens if we restart Nginx:

$ sudo /path-to/nginx -s stop
$ sudo /path-to/nginx
$ sudo passenger-status

The application process should remain there, unchanged:

$ sudo passenger-status
Version: 4.1.0
Date   : 2013-06-14 09:21:51 -0400
----------- General information -----------
Max pool size : 6
Processes     : 1
Requests in top-level queue : 0

----------- Application groups -----------
/webapps/foo#default:
  App root: /webapps/foo
  Requests in queue: 0
  * PID: 77283   Sessions: 0       Processed: 1       Uptime: 18s
    CPU: 1%      Memory  : 8M      Last used: 18s ago

Configuring Flying Passenger

Flying Passenger gets some configuration from the web server, but not all. In particular, most web server directives that are only valid in the http context, e.g. passenger_log_level, have no effect when using Flying Passenger. Instead, you are supposed to pass these configuration directives through command line options to the Flying Passenger daemon. Configuration directives that have no effect on Flying Passenger are documented as such. You can assume that configuration directives that are not documented as such, work fine on Flying Passenger.

For example, to achieve the same effect as setting passenger_log_level to 2, run the Flying Passenger daemon as follows:

$ sudo flying-passenger --socket-file=/var/run/flying-passenger.sock --log-level=2

Currently, not all configuration directives have a Flying Passenger equivalent. Run the following command to see an overview of available options:

$ flying-passenger --help

Managing the Flying Passenger daemon

The Flying Passenger daemon runs in the foreground by default. This is undesirable on server environments. You can make it go into the background by passing --daemonize, --log-file and --pid-file:

$ sudo flying-passenger --socket-file=/var/run/flying-passenger.sock \
    --daemonize --log-file=/var/log/flying-passenger.log \
    --pid-file=/var/run/flying-passenger.pid

You can shut down a Flying Passenger daemon by sending SIGINT or SIGTERM to it:

$ kill `cat /var/run/flying-passenger.pid`

We recommend using daemontools or runit for managing the Flying Passenger daemon. These tools will automatically start the Flying Passenger daemon at boot, and will automatically restart the daemon if it crashes. You can create and enable a daemontools/runit service as folows:

$ sudo mkdir /etc/service/flying-passenger
$ sudo tee /etc/service/flying-passenger/run <<EOF
#!/bin/sh
exec /path-to/flying-passenger \
    --socket-file=/var/run/flying-passenger.sock \
    --log-file=/var/log/flying-passenger.log \
    --pid-file=/var/run/flying-passenger.pid
EOF

Immediately after creating the run file, daemontools/runit automatically runs it to start the daemon. Note that the location (/etc/service) depends on the OS or Linux distros. Sometimes it’s /service. Also note that we start the Flying Passenger daemon without --daemonize.

To shut down a daemontools/runit-managed daemon, you need to use svc -d /etc/service/flying-passenger (daemontools) or sv stop /etc/service/flying-passenger (runit) instead of sending a signal to the process.

Caveats and limitations

Beware of the following caveats and limitations when using Flying Passenger:

  • The Nginx executable must be compiled with the same version of Phusion Passenger as the Flying Passenger daemon. Failing to meet this requirement may result in cryptic errors, or may result in certain features not working, until you’ve fixed the situation. When upgrading Phusion Passenger, you must restart both Nginx and the Flying Passenger daemon.
  • The passenger_root directive has no effect. When using Flying Passenger, you are not supposed to set passenger_root.
  • When you add a new application to the web server configuration, Flying Passenger will automatically pick up the application’s settings and spawn this new application upon the first request to it. However it is not capable of automatically starting the new app before a request has been sent to it (i.e. passenger_pre_start-like behavior is not available in this case). As a workaround, you can send an HTTP request to your application after starting the daemon, which forces it to spawn application processes.
  • When you remove an application from the web server configuration, Flying Passenger will not detect the removal and will not shut down the associated application processes. Killing the application processes will also not help, because Flying Passenger will restart them per the (now-removed, but still in the Flying Passenger daemon’s memory) passenger_min_instances settings. At the moment, there are two ways to get rid of those processes:
    • Before removing the application from the web server configuration, explicitly set its passenger_min_instances to 0. Next, send a request to it, which will cause the Flying Passenger daemon to take over the new passenger_min_instances 0 option. You can then proceed with removing the application from the web server configuration, and restarting the web server. Finally, kill the PIDs associated to those application processes and remove the application configuration.
    • Restart the Flying Passenger daemon.

Conclusion

Flying Passenger should especially be useful for those who have to modify Nginx configuration on a regular basis, without modifying application configuration. Flying Passenger is still a young feature, so we encourage users to provide feedback and bug reports.

We at Phusion are continuously developing and improving Phusion Passenger. If you would like to stay up to date with Phusion news, please fill in your name and email address below and sign up for our newsletter. We won’t spam you, we promise.