FastCGI

Author

Frank Warmerdam

Contact

warmerdam at pobox.com

Author

Howard Butler

Contact

hobu.inc at gmail.com

Last Updated

2008-07-15

Introduction

FastCGI is a protocol for keeping cgi-bin style web applications running as a daemon to take advantage of preserving memory caches, and amortizing other high startup costs (like heavy database connections) over many requests.

Obtaining the necessary software

  1. There are three pieces to the MapServer FastCGI puzzle. First, you need the actual FastCGI library. This can be downloaded from https://fastcgi-archives.github.io//. This library does the usual configure, make, make install dance. One added complication is that it installs by default in /usr/local, and you might give the configure command a –prefix=/usr to put it in a location that is already visible to ldconfig.

  2. Assuming you are running Apache, the next piece you need is the fastcgi module. There are two fastcgi implementations for apache:

    • mod_fcgid: mod_fcgid is the newer and recommended way to run fastcgi programs under recent apache versions. It can be downloaded from the Apache fcgid homepage

    • deprecated mod_fcgi: Mod_fcgi depends on the version of Apache you are running, so make sure to download the correct fork (Apache 1.3 vs. Apache 2).

  3. The third and final piece is to compile MapServer with FastCGI support. This is pretty straightforward, and all you need to do is tell configure where the FastCGI library is installed. If you changed the prefix variable as described above, this would be:

./configure [other options] --with-fastcgi=/usr/local

With those pieces in place, the MapServer CGI (mapserv) should now be FastCGI-enabled. You can verify this by testing it on with the command line:

[hobu@kenyon mapserver-6.2.0]# ./mapserv -v
MapServer version 6.2.0 OUTPUT=GIF OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP
SUPPORTS=PROJ SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT
SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=FASTCGI INPUT=EPPL7
INPUT=SDE INPUT=ORACLESPATIAL INPUT=OGR INPUT=GDAL
INPUT=SHAPEFILE DEBUG=MSDEBUG

mod_fcgid Configuration

  1. Modify http.conf to load the FastCGI module.

LoadModule fcgid_module modules/mod_fcgid.so
  1. Add an Apache handler for FastCGI applications.

AddHandler fcgid-script fcgi
  1. Set FastCGI processing information

<IfModule mod_fcgid.c>
   FcgidMaxProcessesPerClass 30
   FcgidInitialEnv PROJ_LIB /usr/local/share/proj
   FcgidInitialEnv LD_LIBRARY_PATH "/usr/local/lib:/usr/local/pgsql/lib:/usr3/pkg3/oracle9/lib"
</IfModule>

Deprecated mod_fcgi Configuration

This section is left for reference. The recommended way to run fastcgi programs under apache is to use mod_fcgid, as detailed above.

  1. Modify http.conf to load the FastCGI module.

    LoadModule fastcgi_module /usr/lib/apache/1.3/mod_fastcgi.so
    
  2. Add an Apache handler for FastCGI applications.

    AddHandler fastcgi-script fcgi
    
  3. Set FastCGI processing information

    FastCgiConfig -initial-env PROJ_LIB=/usr/local/share/proj
    -initial-env LD_LIBRARY_PATH=/usr/local/lib:/usr/local/pgsql/lib:/usr3/pkg3/oracle9/lib
    -appConnTimeout 60 -idle-timeout 60 -init-start-delay 1
    -minProcesses 2 -maxClassProcesses 20 -startDelay 5
    

Common mod_fcgid/mod_fcgi Configuration

  1. Install a copy of the mapserv executable (originally mapserv or mapserv.exe) into the cgi-bin directory with the extension .fcgi (ie. mapserv.fcgi). Use this executable when you want to utilize fastcgi support.

    For some platforms, the MapServer link would then have to changed from:

    http://your.domain.name/cgi-bin/mapserv?MAP=/path/to/mapfile.map
    

    To:

    http://your.domain.name/cgi-bin/mapserv.fcgi?MAP=/path/to/mapfile.map
    

    For other platforms, the MapServer link would then have to changed from:

    http://your.domain.name/cgi-bin/mapserv.exe?MAP=/path/to/mapfile.map
    

    To:

    http://your.domain.name/cgi-bin/mapserv.fcgi?MAP=/path/to/mapfile.map
    
  2. In your mapfile, set a PROCESSING directive to tell FastCGI to cache the connections and layer information on all layers for which connection caching is desired - ie. all slow layers.

    PROCESSING "CLOSE_CONNECTION=DEFER"
    

Common Problems

File permissions

Fedora Core 3 doesn’t allow FastCGI to write to the process logs (when you use RedHat’s Apache 2 rather than your own). This is described here.

Also, FastCGI needs to write its socket information somewhere. This can be directed with the FastCgiIpcDir directive.

FastCGI on Win32

MS4W Users

MS4W (MapServer for Windows) >= version 2.2.2 contains MapServer compiled with FastCGI support. MS4W version >= 2.2.8 also contains the required Apache module (mod_fcgid), and users must follow the README instructions to setup FastCGI with their application.

Building fcgi-2.4.0

I used libfcgi-2.4.0 for use with Apache2 from https://fastcgi-archives.github.io/.

Binary IO Patch

It is critical that stdio be in binary mode when PNG and other binary images are written to it. To accomplish this for stdio handled through the FastCGI library, I had to do the following hack to libfcgi/fcgi_stdio.c within the fcgi-2.4.0 distribution.

In FCGI_Accept() made he following change

if(isCGI) {
  FCGI_stdin->stdio_stream = stdin;
  FCGI_stdin->fcgx_stream = NULL;
  FCGI_stdout->stdio_stream = stdout;
  FCGI_stdout->fcgx_stream = NULL;
  FCGI_stderr->stdio_stream = stderr;
  FCGI_stderr->fcgx_stream = NULL;

  /* FrankWarmerdam: added so that returning PNG and other binary data
     will still work */
#ifdef _WIN32
  _setmode( _fileno(stdout), _O_BINARY);
  _setmode( _fileno(stdin), _O_BINARY);
#endif

} else {

Also, add the following just before the FCGI_Accept() function

#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif

I’m sure there is a better way of accomplishing this. If you know how, please let me know!

Building libfcgi

The makefile.nt should be fine. Just ensure you have run VCVARS32.BAT (as is needed for building MapServer) and then issue the command:

nmake /f makefile.nt

Then the .lib and .dll will be in libfcgi/Debug?. Make sure you copy the DLL somewhere appropriate (such as your cgi-bin directory).

Other Issues

1) FastCGI’s receive a very limited environment on win32, seemingly even more restricted than normal cgi’s started by apache. Make sure that all DLLs required are either in the fastcgi directory or in windowssystem32. Any missing DLLs will result in very cryptic errors in the error_log, including stuff about Overlapping read requests failing or something like that.

2) Make sure you use a libfcgi.dll built against the same runtime library as your mapserv.exe (and possibly libmap_fcgi.dll) or you will suffer a world of pain! Different runtime libraries have different “environ” variables (as well as their own stdio and heaps). You can check that everything is using MSVCRT.DLL (or all using MSVCRTD.DLL) using the MS SDK Dependency Walker.