Apache Server Survival Guide asgxc.htm
|
Request | Client, Server, and Application Processing Time |
Static File | 21ms + 0.19ms/KB |
FastCGI | 22ms + 0.28ms/KB |
CGI | 59ms + 0.37ms/KB |
Add to this the cumulative time that it takes for an application to establish a TCP/IP connection to, say, a database. Under CGI, a process will have to initialize each time it is run. FastCGI can yield a performance increase of four times the speed of the same program used as CGI. In load terms, this could mean that your server could potentially handle four times your current CGI load. However, the level of enhancement will depend on the source of the bottleneck. If your database server is the current source of the problem, FastCGI cannot do much about that except reduce the number of connections that the database server will need to perform, perhaps giving it more time to process data instead.
The FastCGI API has a handful of calls:
Data is read and written through the standard input, output, and error streams. FastCGI also provides macros that map files and streams to native calls supported by your operating system.
Like CGI, you can create FastCGI applications in almost any language. However, you are currently limited to the ports of the library. Currently available are Perl, C/C++, Tcl, Java, and very soon Python, which should be available by the time you read this. Also in the works is a multithreaded C/C++ library that has not been released, but should be available as part of the 1.6 release. The multithreaded library allows a single application process to handle concurrent requests, which will allow you to implement things like HTTP-based chat applications.
Even though FastCGI is not universal, most developers should find themselves at home in one of the programming languages previously mentioned. As soon as FastCGI gains more acceptance, there will be additional libraries implemented. Developers are encouraged to port the FastCGI libraries to their programming language of choice, ensuring that the openness of the extension is more widely supported. The success of FastCGI will depend on getting many vendors and programmers to support it. Given its current feature set, it should have no trouble reaching this goal.
The design of FastCGI also wins big on the learning curve because unlike server APIs, you are still programming a CGI, so you can leverage what you already know. The only issues that you will need to address have to do with reorganizing your application so that the initialization code, which is done once, is kept separate from the application body. FastCGI applications are long-lived; they are kept alive between transactions. This also means that memory needs to be managed because unlike CGIs, which have a short life span, FastCGI processes may execute for undetermined amounts of time.
Data sent to a FastCGI application by the server is accessed through special streams that provide complete binary compatibility with the CGI standard. This also allows a FastCGI program to run as a regular CGI program. A FastCGI program can determine, at runtime, if it is being run as CGI or as FastCGI and behave accordingly.
This translates into an environment that allows you to migrate FastCGI programs down, should you ever need to. This provides server independence because the same binary can be run on two serverssay Apache and Netscapeunder the same operating system without even needing to be rebuilt or require programming modifications, even if the server couldn't support FastCGI. This feature alone is very interesting from a legacy and recycling standpoint. Also, all servers support FastCGI. The FastCGI Developer's Kit comes with a program called cgi-fcgi that allows you to run FastCGI responder applications. The cgi-fcgi program allows any Web server that supports CGI to run FastCGI.
FastCGI applications communicate with Apache using a single full-duplex connection. Through this connection, the server transmits the environment variables and stdin to the FastCGI application; stdout and stderr streams from the application are sent back to the server.
A modified version of my HelloWorld.c looks like this:
#include "fcgi_stdio.h" #include <stdio.h> int main (void) { int timesVisited = 0; while(FCGI_Accept() >=0) { printf ("Content-type: text/html\r\n\r\n"); printf("<HTML>"); printf("<HEAD><TITLE>Hello World!</TITLE></HEAD>"); printf("<BODY><H1>Hello, this is a FastCGI program!</H1>"); printf("<BIG><P>I can tell that you are visiting from %s.</P>"); printf("<p>This page has been accessed: %d times</P></BIG></BODY>", getenv("REMOTE_HOST"), ++timesVisited); printf("</HTML>"); } } |
This version makes use of the fact that the application is persistent and will maintain a count of the times the program is run (until the program dies).
As you can see from this example, FastCGI applications follow this sequence:
This process is repeated until the FastCGI application is killed by the System administrator or the Web server. If the process were to die, the FastCGI module or cgi-fcgi program in the Web server is responsible for making a FastCGI process available to handle the request. This means that if it dies, the server will fork another process to replace the original.
|
AddType application/x-httpd-fcgi .fcgi Alias /fcgi-bin/ /usr/local/etc/httpd/fcgi-bin # AppClass |
Create the fcgi-bin directory, while in /usr/local/etc/httpd:
% mkdir fcgi-bin As you may be able to guess by now, FastCGI applications should be run from a directory other than the cgi-bin directory.
After Apache builds, issue the following commands:
|
% cd /usr/local/etc/httpd % mv httpd httpd.prev % mv src/httpd . % strip httpd % kill -HUP 'cat /usr/local/etc/httpd/logs/httpd.pid` |
cc -o Hello.fcgi -lfcgi HelloWorld.c Put the resulting Hello.fcgi on your fcgi-bin directory. Before you can access it, you'll need to add an AppClass entry into your srm.conf:
AppClass /usr/local/etc/httpd/fcgi-bin/Hello.fcgi and restart the server with
% kill -HUP `cat /usr/local/etc/httpd/logs/httpd.pid` |
The AppClass directive takes care of starting and maintaining the FastCGI application. At this point you should be able to access it by pointing your browser to http://localhost/fcgi-bin/Hello.fcgi.
You should get a similar result to those displayed in Figure C.2.
Figure C.2. The FastCGI version of Hello World!. Notice that it keeps state. My version is fancier than the HelloWorld listing.
|
#!/usr/local/bin/perl use strict; use FCGI; my($timesVisited) = 0; while(FCGI::accept() >=0){ print "Content-type: text/plain\n\n"; print <<STOP; <HTML> <HEAD> <TITLE>Hello World!</TITLE> </HEAD> <BODY> <H1>Hello, this is a FastCGI program!</H1> <P>I can tell that you are visiting from $ENV{REMOTE_HOST}</P> <P>This page has been accessed: ++$timesVisited</P> </BODY> </HTML> STOP } |
AppClass /usr/local/etc/httpd/fcgi-bin/HelloWorld.fcgi -processes 2 |
For a Perl program, to circumvent the environment problem, you would have to do this:
|
AppClass /usr/local/etc/httpd/fcgi-bin/HelloWorld.fcgi -processes 2 -initial- env: DB_PATH_NAME=/proj/accts/db2 |
|