Configuring the FastCGI Extension for IIS 6.0

Applies To: Windows Server 2003

Since version 1.0, the Microsoft® Internet Information Services (IIS) Web server has supported the Common Gateway Interface (CGI) protocol specification. CGI, in its basic form, is a standards-based protocol that allows information servers, such as IIS, to interface with external applications. FastCGI was introduced to the market to address scalability shortcomings of CGI.

This article describes the shortcomings of earlier versions of CGI and defines the need for the FastCGI extension for Internet Information Services 6.0. In addition, this article describes configurations settings of the FastCGI extension.

CGI, ISAPI, and FastCGI on IIS 6.0

CGI

As stated in the introduction, CGI is a protocol that allows information servers to interface with external applications. Because HTTP is stateless, it makes sense that any requests made over HTTP create a new instance of the external application in a new operating system process.

Within the new process, the stdin handle is remapped so that it receives request data from the client, the stdout handle is remapped so that it writes response data to the client, and the command-line and operating system environment variables are set to provide other server and request information to the CGI process.

The disadvantage with CGI on IIS is the relatively expensive process creation on Windows® operating systems. Every HTTP request creates a new process, performs the work inside the CGI application, and shuts down the process. On operating systems with very lightweight process creation, the performance is bound by the work done inside the CGI application. On operating systems such as Windows where process creation is expensive, the performance of the CGI application is bound by spinning up the new process. That is why CGI has performed well in UNIX-based systems but has not been recommended for IIS.

ISAPI

Despite the disadvantage of CGI on Windows, IIS can keep up with, and often surpass, the performance of other Web servers. Use of Internet Server Application Programming Interface (ISAPI) enables this performance. Unlike CGI, ISAPI is internal to the Web server process. When a new request is made for an ISAPI application, a new process is not created. Instead, the Web server calls an entry point in a dynamic-link library (DLL) that is loaded into the Web server process. If the ISAPI application is written with an understanding of how the operating system threading model works, the performance is very fast.

For many years, PHP has run on IIS, both through ISAPI and CGI implementations. However, both implementations have disadvantages when they run on IIS. As with all CGI applications, the CGI implementation of PHP has a disadvantage due to the performance characteristics of process creation on Windows. The ISAPI implementation has a disadvantage caused by threading issues.

When PHP runs as an ISAPI, it runs inside the Web server process in a highly multithreaded environment. While the PHP implementation is thread-safe, many popular extensions to PHP are not thread-safe. If you use a non-thread-safe extension to PHP with ISAPI, the server could become unstable. Hence, many applications cannot run in the ISAPI PHP implementations whereas others run very well in this environment.

FastCGI

FastCGI offers a compromise solution that delivers both performance and stability. FastCGI allows the host CGI process to remain alive after one request finishes so that the process may be reused for another request. Since the process can be reused many times over, the cost of process creation on Windows drops out of the equation.

The technical difference between ordinary CGI and FastCGI is that FastCGI has a layer in the process that maps the FastCGI protocol into the stdin, stdout, and the other standard streams that CGI uses. Many third-party libraries can be linked into existing CGI source code with very minor modifications that will enable them to work with FastCGI.

FastCGI on IIS runs on top of ISAPI. It is comprised of applications, the Application Manager, and FastCGI protocol support code.

Because Web servers handle multiple, concurrent requests, they must have a pool of processes available that are ready to handle incoming requests. In the FastCGI handler, this pool of processes is called an application (to avoid confusion with IIS applications, this article uses the term process pool). There are several properties of a process pool that you may want to manage. For example, you probably want to specify the number of processes in the pool, or the number of requests that a process can accept before it is shut down and recycled.

The FastCGI handler supports multiple process pools. This capability lets you run more than one kind of FastCGI on one server—for example, both PHP and Ruby. You may also have multiple sites on your server, and you may not want requests for those sites to share the same processes, especially if you want the site processes to run as different users. The application manager is the part of FastCGI that handles multiple process pools.

Configuring FastCGI

Script Maps

To route requests to the FastCGI handler, you must associate the FastCGI handler with IIS. In IIS 6.0, you do this by using an IIS configuration setting called a script map. Script maps associate file name extensions with the ISAPI handler that executes when that file type is requested. In addition, the script map has an optional setting that verifies that the physical file associated with the request exists before allowing the request to be processed. For security reasons, this is the default setting.

However, sometimes you need to allow a request to be processed that is not associated with a physical file. The ISAPI extension that contains the FastCGI handler is called fcgiext.dll. To configure the FastCGI handler to accept PHP requests, create a new script map that associates the ".php" file name extension with fcgiext.dll. For Ruby, map the ".rb" extension to fcgiext.dll and so on. In IIS 6.0 it is also possible to use a wildcard in the script map. In this situation, all requests are routed to a single ISAPI extension. If you create a wildcard script map for fcgiext.dll, all requests will use FastCGI, regardless of the file name extension requested.

To create a script map for FastCGI handler on IIS 6.0

  1. Start inetmgr.exe.

  2. Double-click the icon for the local computer.

  3. Right-click Web Sites and select Properties.

  4. Click Home Directory tab.

  5. Click Configuration.

  6. Click Add.

  7. Browse to %windir%\system32\inetsrv\ to select fcgiext.dll as the Executable.

  8. Enter .php in the Extension field.

  9. Select Limit to and enter GET,HEAD,POST.

  10. Select Script Engine and Verify that file exists.

  11. Click OK.

FCGIEXT.ini

Once you have created a script map, you must configure the FastCGI extension settings. Use the Fcgiext.ini file found in %windir%\system32\inetsrv\. This file contains various configuration sections and settings that change the behavior of the FastCGI handler.

Regardless of the FastCGI application type that you want to run, you must include a Types section in your configuration file. The purpose of the Types section is to associate a file name extension with a specific process pool and process. If you configure IIS script maps to point both .php and .rb files to the FastCGI handler, you must configure the Types section to tell FastCGI how these extensions differ from each other. Following is a sample configuration file that maps:

[Types]

php=c:\php\php-cgi.exe

php:123154536=PHP Site 1

php:123154537=PHP Site 2

*=Wildcard Mapping

The first line of this file shows that PHP file name extensions are associated with c:\php\php-cgi.exe, which is the PHP CGI application handler. The second and third lines of this sample use site instance identifiers to limit which sites have access to the PHP handler.

You can create configuration on a process-name basis, a file name extension (which is optionally site-specific), and a section name. The section name supports declaring arguments for the process. Since different pools running in the same process may require different arguments, you cannot depend on the process name alone to define all the settings for a given process pool. However, to maintain compatibility with previous technical preview releases of the FastCGI handler, the path of the executable is used to create the starting configuration, as in the following sample:

[c:\php\php-cgi.exe]

QueueLength=999

MaxInstances=20

InstanceMaxRequests=500

Since this section does not contain an ExePath setting, the FastCGI handler uses the section name for the path of the executable. The section below is for PHP Site 1, which only applies to the site that uses 123154536 as its ID:

[PHP Site 1]

ExePath=c:\php\php-cgi.exe

Arguments=site1

QueueLength=1001

MaxInstances=20

IdleTimeout=200

ActivityTimeout=20

RequestTimeout=60

InstanceMaxRequests=1000

In this section, .php requests are associated on that site with c:\php\php-cgi.exe. Additionally, when a process starts, "site1" is passed as an argument. This differs from the procedures followed on PHP Site 2, which looks like the following:

[PHP Site 2]

ExePath=c:\php\php-cgi.exe

Arguments=site2

QueueLength=1001

MaxInstances=20

IdleTimeout=400

ActivityTimeout=40

RequestTimeout=120

InstanceMaxRequests=1000

In this case, you pass "site2" as the argument when you start c:\php\php-cgi.exe.

Note: The Arguments setting is optional, and you can pass multiple arguments using a space delimiter.

If you need a space within a single argument, use quotation marks around the complete argument, just as you would do when using the command line.

Note: Every time that you change the FastCGI extension configuration in the Fcgiext.ini file, you must restart the application pools associated with Web sites that use FastCGI extension before the configuration changes will take effect.

Application Pool Settings

FastCGI extension has a set of configuration settings that control application pool behavior. This section lists all the settings supported by FastCGI and their formats:

  • ExePath – This setting specifies the physical path of the process executable that will be used in the pool.

  • Arguments – This setting specifies the arguments to pass to each process in the pool at start time. This setting is optional.

  • EnvironmentVars – This setting specifies the environment variables that are set for the process executable associated with this pool. This setting uses the following format:

    EnvironmentVars=Name:Value,Name:Value,…,Name:Value

    Example:

    EnvironmentVars=VARIABLE1:10000,VARIABLE2:20000

If the environment variable value contains a space character, then enclose the value in quotation marks. If the environment variable value contains a comma character (“,”), then this character is escaped with "/". Similarly, if the environment variable value contains "/" then it should be escaped also.

Example:

EnvironmentVars=VARIABLE1:"C://PHP",VARIABLE2="1/,2/,3"

  • Protocol – This setting specifies the protocol that must be used to communicate with the FastCGI process. The allowed values are NamedPipe and Tcp. If not specified, the default value is NamedPipe.

  • QueueLength – This setting specifies the maximum number of requests to an application's process pool that are queued before the FastCGI handler starts returning errors to clients. This indicates that the application is too busy. If not specified, the default value is 1000.

  • MaxInstances – This is the highest number of process instances allowed in the process pool. The default is 10. Note that the FastCGI handler will not create this number of processes unless they are needed. If your application never receives more than two concurrent requests, your application only creates two processes.

  • InstanceMaxRequests – This is the number of requests sent to a process in the pool before it is shut down and recycled. The default value is 1000.

  • IdleTimeout – This is the number of seconds that a process can remain idle without working on a request before it shuts down. The default is 300 seconds.

  • ActivityTimeout – This is the number of seconds that the FastCGI handler waits for I/O activity from a process before it is terminated. The default is 30 seconds.

  • RequestTimeout – This is the maximum amount of time that a FastCGI process is allowed to handle a request before it is terminated. The default is 90 seconds.

  • ResponseBufferLimit – Data from FastCGI processes is buffered before it is returned to the client as a response. This property specifies the amount of response data, in bytes, that is buffered for requests to an application. This buffer is flushed to the client as soon as it is full or when the response is complete, whichever occurs first. If not specified, the default value is 4194304 (4 MB).

  • FlushNamedPipe – There are some cases where a FastCGI application might not read all of the data from the named pipe that communicates with the Web server. If this occurs, the Web server waits for a read that does not come. This, in turn, causes a deadlock on that member of the process pool. This most often occurs when a FastCGI process exits abnormally. For instance, the maximum number of requests a process can handle may be set internally, but that number may be lower than the InstanceMaxRequests setting. Setting FlushNamedPipe to 1 causes FastCGI to flush data that could lead to this condition. The default is 0.

  • UnhealthyOnQueueFull – If the value of this variable is 1, the worker process hosting is flagged to IIS as unhealthy any time that the application's request queue is filled. IIS checks health whenever it pings the worker process. If that worker process has been flagged as unhealthy, it and everything it is hosting will be recycled. If not specified, the default value is 0.

Wildcard Mapping

The asterisk, “*”, association is used for wildcard mapping. This applies to IIS 6.0, which allows a special kind of script map that applies to all requests. If you configure fcgiext.dll as a wildcard handler, this association catches any requests that do not have a more specific configuration associated with the request. For example, the Types section described earlier in this article does not have a ".py" extension configured. If you use the sample section earlier in this article to model a request for a file that is named "File.py,” the ”*” association is used and the request is routed to the process pool called "Wildcard Mapping."

Consider this section:

[Wildcard Mapping]

ExePath=c:\echo\echo.exe

QueueLength=1000

MaxInstances=20

InstanceMaxRequests=100

IgnoreExistingFiles=1

;IgnoreExistingDirectories=1

Most of this example resembles the other process pool sections, but it has two additional settings, IgnoreExistingFiles and IgnoreDirectories, that are only used for wildcard script maps.

Consider the situation where you have configured an IIS script map that does not verify that a physical file exists before executing the handler. In this scenario, it is convenient to let the FastCGI handler handle requests that are not associated with physical files, but still to let IIS handle other files in the directory. This scenario explains the reason and need for these two settings.

  • IgnoreExistingFiles – When set to 1, the FastCGI handler checks if the requested URL is associated with a physical file. If the request is associated with a physical file, the FastCGI handler defers processing the request so that it will be processed externally from the FastCGI handler. The default value is 0.

  • IgnoreExistingDirectories – When set to 1, the FastCGI handler checks whether the requested URL is associated with a physical directory. If the request is associated with a physical directory, the FastCGI handler defers processing the request so that it is processed externally from the FastCGI handler. This setting is useful for allowing default documents and directory listings to be served. The default value is 0.

Site-Specific Wildcard Mappings

It is also possible to set a site-specific wildcard mapping using the same site ID syntax that file name extensions use (that is, "*:12345678=Section Name"). Note, however, that the search order for file name extensions is significant. When a request reaches the FastCGI handler, the associations in the Types section are checked in the following order:

  1. A specific file name extension association specific to the site ID.

  2. A '*' association specific to the site ID.

  3. A specific file name extension association that has no specified site ID.

  4. A '*' association that has no specified site ID.

Using FastCGI Configuration Script

To simplify and automate the configuration steps described in previous sections, the configuration script (fcgiconfig.js) is provided with the installation of FastCGI extension. The script is found in %windir%\system32\inetsrv. This script adds and removes script maps and modifies application pool settings in the Fcgiext.ini file.

Add New FastCGI Mapping

To add new FastCGI mapping, run fcgiconfig.js with the –add switch. When using this switch, you must provide the following parameters:

  • -section:<Section name>. This parameter specifies the name of the section that will be added to the fcgiext.ini file in [Types] block.

  • -extension:<file name extension>. This parameter specifies what file name extensions are associated with this section.

  • -path:<file path of the CGI executable>. This specifies the absolute file path of the CGI executable that processes requests for files that have extension specified in –extension parameter.

  • -site:<site id>. This optional parameter specifies the site to which the section should be added. If not specified, then the section is added to all sites on your Web server.

  • -norecycle. By default, the configuration script recycles all applications pools on IIS 6.0 so that configuration changes can take effect. This optional parameter prevents this recycling.

Examples:

>cscript fcgiconfig.js -add -section:"PHP" -extension:php -path:"C:\PHP\php-cgi.exe"

The example given earlier in this section adds script map for .php extension and updates the Fcgiext.ini file.

As an option, you can specify the site to which the script map is applied:

>cscript fcgiconfig.js -add -section:"PHP" -extension:php -path:"C:\PHP\php-cgi.exe" –site:1

This example adds script map to "Default Web Site" only.

Remove Existing FastCGI Mapping

To remove existing FastCGI mapping, run fcgiconfig.js with –remove switch. When using this switch, you must provide the following parameters:

  • -section:<Section name>. This parameter specifies the name of the section that is removed to the Fcgiext.ini file in [Types] block.

  • -norecycle. By default, configuration script recycles all applications pools on IIS 6.0 so that configuration changes take effect. This optional parameter can be used to prevent this recycling.

This example removes the FastCGI mapping for PHP applications.

>cscript fcgiconfig.js -remove -section:"PHP"

Configuring Existing FastCGI Mapping

You can use the configuration script for all FastCGI configuration properties that were described earlier in this article. To set the configuration properties, use the –set switch. When using this switch, you must provide the following parameters:

  • -section:<Section name>. This parameter specifies the section to which the configuration change is applied.

  • -<Parameter Name>:<Parameter Value>. This specifies the name of the parameter to change and its new value. The complete list of possible parameters is found in the Application Pool Settings section.

  • -norecycle. Use this parameter if you do not want configuration script to recycle application pools after applying configuration change.

This example sets the FastCGI process pool configuration property InstanceMaxRequests for the PHP section:

>cscript fcgiconfig.js -set -section:"PHP" –InstanceMaxRequests:10000