Deploying Nagare applications in a production environment¶
Serving a Nagare application in a development setup is easy. You just have to launch the following command:
nagare-admin serve [options] <app_name>
It starts a standalone threaded server which stores the sessions data in memory.
This standalone server is very convenient when developing Nagare applications, especially when
using the --reload
and --debug
options that respectively restart the server when source
files are changed and show the exceptions stacktraces as Web pages instead of in the console
shell.
However, this standalone mode is not suitable in a production environment, because it is not efficient nor fail-safe:
- Since it’s a threaded program, it does not fully utilize the CPU cores due to the GIL (see this discussion). To solve this problem, we need to use multiprocessing.
- Static files are served by the standalone server and are not cached. They would be better served by a faster dedicated Web server such as Apache, Nginx, Lighttpd …
- The server processes are not monitored, and they don’t cope with failures very well. For example, in a production setup, it’s important to detect zombie processes and restart them to prevent attacks or to limit the impact of unnoticed programmation errors in the application. Of course, you should also use logging to trace the origin of the problems in order to solve them.
So, in a production environment, the recommended way to serve Nagare applications is through FastCGI associated to a frontend Web server such as Apache, Nginx or Lighttpd. We are now going to describe how to do that.
Serving an application through FastCGI¶
In a FastCGI setup, a Web server such as Apache, Nginx or Lighttpd is needed. It will serve the static contents of the application, such as images, CSS and javascript files, and pass the other requests (i.e. those with a “dynamic” nature) to the Nagare application through the FastCGI protocol.
FastCGI is a variation of the CGI protocol, which defines an interface layer between a Web server and external applications (such as shell or python scripts). The main difference between FastCGI and CGI is that FastCGI doesn’t create a new worker process at the start of each request but use a pool of processes that are created when the FastCGI service starts, and uses sockets for exchanging informations (i.e. request and response data) between the Web server and the external applications.
This setup is particularly efficient when serving Nagare applications because the pool of processes fully utilize the CPU cores. Furthermore, Web servers are far more efficient than the standalone threaded server when serving the static contents of the application since they cache the data and they are mostly written in C.
The publisher configuration¶
In order to serve a Nagare application through FastCGI, we must first tell the nagare-admin serve
utility
that we don’t want to use the standalone server but FastCGI instead. This is done by creating a publisher
configuration file (see The publisher configuration file) and passing it to the nagare-admin serve
command
with the -c
option.
Here is a typical publisher configuration file to serve an application through FastCGI:
[publisher]
type = fastcgi
host = 127.0.0.1
port = 9000
[sessions]
type = memcache
host = 127.0.0.1
port = 11211
We use the fastcgi
backend for the publisher (with the default settings) and the memcache
backend for
the sessions management.
Then, the FastCGI server can be launched by running this command:
nagare-admin serve -c publisher.conf <app_name>
By default, the FastCGI server forks 5 worker processes at startup to handle the incoming requests received on port 9000. However, the number of worker processes can grow or shrink depending on the workload.
Warning
When an application is served through FastCGI, you must use a memcache
backend for storing the sessions data. The default standalone
session
backend will not work with FastCGI because the session data is stored
in memory, and since the processes spawned by the FastCGI server don’t
share memory (by definition), the sessions data stored in one process would
not be available in another process.
That’s why a kind of distributed “shared memory” session backend should be
used with the FastCGI publisher. So don’t forget to launch your memcached
server.
As the sessions are shared through the memcached server, the same FastCGI application can be launched on several machines thus easily creating a scalable applicative cluster.
Configuring the Web server¶
The next step is to configure the Web server so that it serves the static files and pass the other requests to the FastCGI processes we just launched. Of course, the procedure depend on the Web server used, so we are going to show you how to achieve that with Apache, Nginx and Lighttpd. However, it should be easy to use another Web server supporting FastCGI if you want to.
Apache¶
On Apache, the FastCGI support is provided by the mod_fastcgi
module which is not installed by default.
You should download and install it by yourself, as described here.
Then, the mod_fastcgi
module should be activated by including it in the main apache configuration file as shown
below:
LoadModule fastcgi_module /path/to/mod_fastcgi.so
The rewrite rules serving the static files of your application can be generated with this command:
nagare-admin create-rules --apache <application> > rewrite_rules.apache
You should obtain something like this:
RewriteEngine On
RewriteRule ^/static/nagare/(.*)$ /path/to/python/site-packages/nagare-0.5.0-py2.7.egg/static/$1 [L]
RewriteRule ^/static/myapp/(.*)$ /path/to/python/site-packages/myapp-0.0.1-py2.7.egg/static/$1 [L]
Then, you must create a VirtualHost
for your application and include the rewrite rules file
into the configuration, as shown below:
# virtualhost configuration for http://www.myapp.com
<VirtualHost *:80>
ServerName www.myapp.com
FastCGIExternalServer /path/to/python/site-packages/fcgi -host 127.0.0.1:9000
Include /path/to/rewrite_rules.apache
RewriteRule ^/(.*)$ /fcgi/$1 [QSA,L]
</VirtualHost>
The FastCGIExternalServer
directive instructs Apache to forward the requests directed to
/path/to/python/site-packages/fcgi
to the FastCGI server listening at 127.0.0.1
on port
9000
which has been launched externally, and the last RewriteRule
directive redirects
the requests not handled by the other rewrite rules to /path/to/python/site-packages/fcgi
,
thus forwarding those requests to the FastCGI processes.
Finally, you should include
the VirtualHost
configuration file into the main
apache configuration file, or put it in the conf.d
directory of your apache installation,
and restart Apache.
Nginx¶
Nginx has builtin support for FastCGI thanks to the Nginx’s HttpFastcgiModule, so no manual installation is necessary.
The rewrite rules serving the static files can be generated with this command:
nagare-admin create-rules --nginx <application> > rewrite_rules.nginx
You should obtain something like this:
location /static/nagare/ {
alias /path/to/python/site-packages/nagare-0.5.0-py2.7.egg/static/;
}
location /static/myapp/ {
alias /path/to/python/site-packages/myapp-0.0.1-py2.7.egg/static/;
}
Then, you must create a server configuration, as shown below:
server {
listen 80;
server_name www.myapp.com;
access_log /var/log/nginx/myapp.access.log;
error_log /var/log/nginx/myapp.error.log;
# serve the static files
include /path/to/rewrite_rules.nginx;
# serve the application
location / {
include /etc/nginx/fastcgi_params;
# Nagare applications need a properly set PATH_INFO variable
# either pass the request URI or use fastcgi_split_path_info to split the URI
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
}
}
Note that, in addition to the default FastCGI parameters specified in /etc/nginx/fastcgi_params
,
we must also set the PATH_INFO
parameter which is required by Nagare.
Finally, you must copy the configuration file in /etc/nginx/conf.d/
, or create a symbolic link
there pointing to your configuration file, and restart Nginx.
Lighttpd¶
Lighttpd has also builtin support for FastCGI thanks to the Lighttpd’s mod_fastcgi module.
The rewrite rules serving the static files can be generated with this command:
nagare-admin create-rules --lighttpd <application> > rewrite_rules.lighttpd
However, it’s easier the generate the rewrite rules in an include_shell
directive.
An example of Lighttpd server configuration is show below:
server.modules = ( "mod_rewrite", "mod_fastcgi" )
server.errorlog = "/tmp/lighttpd.log"
server.indexfiles = ( "index.html" )
#debug.log-request-handling = "enable"
server.port = 8080
server.bind = "0.0.0.0"
#server.event-handler = "linux-sysepoll"
fastcgi.server = (
"/fcgi" =>
(
(
"host" => "127.0.0.1",
"port" => 9000,
"check-local" => "disable",
)
)
)
# Here, change the path to the ``nagare-admin`` command
include_shell "path/to/nagare-admin create-rules --lighttpd"
url.rewrite += (
"^(.*)" => "/fcgi/$1"
)
# ---------------------------------------------------------------------------------
mimetype.assign = (
".pdf" => "application/pdf",
".sig" => "application/pgp-signature",
".spl" => "application/futuresplash",
".class" => "application/octet-stream",
".ps" => "application/postscript",
".torrent" => "application/x-bittorrent",
".dvi" => "application/x-dvi",
".gz" => "application/x-gzip",
".pac" => "application/x-ns-proxy-autoconfig",
".swf" => "application/x-shockwave-flash",
".tar.gz" => "application/x-tgz",
".tgz" => "application/x-tgz",
".tar" => "application/x-tar",
".zip" => "application/zip",
".mp3" => "audio/mpeg",
".m3u" => "audio/x-mpegurl",
".wma" => "audio/x-ms-wma",
".wax" => "audio/x-ms-wax",
".ogg" => "application/ogg",
".wav" => "audio/x-wav",
".gif" => "image/gif",
".jpg" => "image/jpeg",
".jpeg" => "image/jpeg",
".png" => "image/png",
".xbm" => "image/x-xbitmap",
".xpm" => "image/x-xpixmap",
".xwd" => "image/x-xwindowdump",
".css" => "text/css",
".html" => "text/html",
".htm" => "text/html",
".js" => "text/javascript",
".asc" => "text/plain",
".c" => "text/plain",
".conf" => "text/plain",
".text" => "text/plain",
".txt" => "text/plain",
".dtd" => "text/xml",
".xml" => "text/xml",
".mpeg" => "video/mpeg",
".mpg" => "video/mpeg",
".mov" => "video/quicktime",
".qt" => "video/quicktime",
".avi" => "video/x-msvideo",
".asf" => "video/x-ms-asf",
".asx" => "video/x-ms-asf",
".wmv" => "video/x-ms-wmv",
".bz2" => "application/x-bzip",
".tbz" => "application/x-bzip-compressed-tar",
".tar.bz2" => "application/x-bzip-compressed-tar"
)
Then, place this config file in /etc/lighttpd/lighttpd.conf
and restart Lighttpd.
Handling the FastCGI processes¶
Since the FastCGI processes are launched externally from the Web server, you can use any monitoring tool to handle the processes, such as Supervisor. Here is a typical configuration file that starts a Nagare application as a daemon with Supervisor:
[unix_http_server]
file=/path/to/supervisord/supervisor.sock
[supervisord]
logfile=/path/to/supervisord/supervisord.log
pidfile=/path/to/supervisord/supervisord.pid
directory=/path/to/supervisord
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///path/to/supervisord/supervisor.sock
[program:myapp]
command=/path/to/nagare-admin serve /path/to/application/conf/myapp.conf -c /path/to/application/conf/fastcgi.conf
process_name=myapp
autostart=true
autorestart=true
stdout_logfile=/path/to/application/logs/myapp.log
redirect_stderr=true
Then, you can start the application by running this command:
/path/to/supervisord -c /path/to/supervisord.conf
The supervisord
process daemonizes itself and starts the FastCGI processes through
the nagare-admin serve
command. Furthermore, they are restarted automatically when something goes
wrong thanks to the autorestart
option.