FastCGI and MapServer
| Release: | 4.4.2 |
|---|---|
| Last Updated: | 2008/05/20 |
| Author: | Frank Warmerdam and Howard Butler |
| Contact: | hobu@iastate.edu |
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
- There are three pieces to the MapServer FastCGI puzzle. First, you need the actual FastCGI library. This can be downloaded from http://www.fastcgi.com/. 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.
- Assuming you are running Apache, the next piece you need is 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).
- 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
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-4.4.2]# ./mapserv -v MapServer version 4.4.2 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
Configuration
Modify http.conf to load the FastCGI module.
LoadModule fastcgi_module /usr/lib/apache/1.3/mod_fastcgi.so
Add an Apache handler for FastCGI applications.
AddHandler fastcgi-script fcgi
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
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. However MS4W does not contain the required Apache module mod_fastcgi, because the module must be compiled to work with the Apache 2.2.x series (MS4W 2.2.7 contains Apache 2.2.8). If you compile this please contribute it back to the MS4W mailing list. Update: the mod_fastcgi module for Apache 2.2 is available for download at the Apache Lounge.
Building fcgi-2.4.0
I used libfcgi-2.4.0 for use with Apache2 from http://www.fastcgi.com.
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
- 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.
- 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.
This How-to applies to: MapServer 4.4, MapServer 4.6, MapServer 4.8, MapServer 4.10
Win2003
Pakman reports that you may need to install the MS PlatformSDK to get fastcgi working properly on Windows 2003. This fixes a problem with "overlapped io".