Here is part 3.
From its first version, IIS has supported CGI (“Common Gateway Interface”). 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 FastCGI extension for Internet Information Services 6.0. In addition, this article describes configurations settings of FastCGI extension.
CGI, ISAPI and FastCGI in IIS 6.0 and IIS 5.1
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 light weight process creation, the performance is bound by the work done inside the CGI application. On operating systems, such as Windows where process creating is expensive, the performance of the CGI application is bound by spinning up the new process. This is why CGI has performed very well on a Unix-based platform, but has not been recommended for IIS.
Despite the disadvantage of CGI on Windows, IIS is capable of keeping up with, and often surpassing, the performance of other web servers. The reason for this is ISAPI (“Internet Server Application Programming Interface”). Unlike CGI, ISAPI is completely 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 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 extremely fast.
For many years, PHP has run on IIS, both through ISAPI and CGI implementations. However, both implementations have disadvantages when running 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 due to threading issues.
When PHP runs as an ISAPI, it runs inside the web server process in a highly multi-threaded 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 while others run very well in this environment.
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 normal CGI and FastCGI is that FastCGI has a layer in the process that maps the FastCGI protocol into the stdin, stdout and other resources that CGI uses. Many third-party libraries can be linked into existing CGI source code with very minor modifications to make them work with FastCGI.
FastCGI on IIS runs on top of ISAPI and breaks into the following parts: Applications, the Application Manager and FastCGI protocol support code.
Because web servers handle multiple, concurrent requests, it is necessary to have a pool of processes available and 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 a number of 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 a process is allowed to accept before it is shut down and recycled.
The FastCGI handler supports multiple process pools. This is so because you may want to run more than one kind of FastCGI on one server. For example, you wish to configure your server to support both PHP and Ruby. You also have multiple sites on your server, and you do not want requests for those sites to share the same processes. This is particularly true if you want the site processes to run as different users or are concerned that one site might cause a process to become unstable. The part of the server that handles multiple process pools is called the application manager.
To route requests to the FastCGI handler, you must associate the FastCGI handler with IIS. In IIS 6.0 and IIS 5.1, this is done with an IIS configuration setting called a “script map.” Script maps associate file 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, there are times when you want 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” 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 wild card in the script map. In this situation, all requests are routed to a single ISAPI extension. If you create a wild card script map for fcgiext.dll, all requests go to FastCGI, regardless of the file extension requested.
To create a script map for FastCGI handler on IIS 6.0 and IIS 5.1 follow these steps:
2.Double click the machine icon for the local computer.
3.Right click on “Web Sites” and pick “Properties.”
4.Click the tab labeled “Home Directory.”
5.Click the “Configuration…” button.
6.Click the “Add…” button.
7.Browse to %WINDIR%system32inetsrv to select fcgiext.dll as the Executable.
Note: If you are setting this up on 64bit platform in WOW mode, then you must use fcgiext.dll located in %WINDIR%SysWOW64inetsrv
8.Enter .php (or another extension specific to your FastCGI application) as the Extension
9.Enter Verbs as GET,HEAD,POST
10.Ensure that “Script Engine” and “Verify that file exists” are checked.
The configuration for FastCGI is a collection of one or more applications. A FastCGI application consists of a pool of processes that each handle HTTP requests. Each process in the pool will handle one request at a time. After each request, the process will be returned to the pool to await another request. Each application is required to have its own section in the configuration file to specify its behavior.
The main section of the fcgiext.ini file is the [types] section. This section associates file extensions from the URL with FastCGI applications.
The general syntax is a follows:
The above example consists of 7 mappings mapped as follows:
•The file extension “abc” is associated with the FastCGI application named “Application 1”.
•The file extension “def” is associated with the FastCGI application named “Application 2”, but only for requests made to the application /app1 under site with the numeric identifier “1701187997”. Note that application specific mappings override site, extension specific mappings.
•Requests to the application /app1 under web site with the identifier “1701187997” with a file extension other than “def” are associated with the FastCGI application named “Application 3”.
•The file extension “def” is associated with the FastCGI application named “Application 4”, but only for requests made to the applications other than /app1 under web site with the numeric identifier “1701187997”. Note that site specific mappings override non-site specific mappings.
•Requests to the applications other than /app1 under web site with the identifier “1701187997” with a file extensions other than “def” are associated with the FastCGI application named “Application 5”.
•The file extension “def” is associated with the FastCGI application named “Application 6” for requests which are not for site with numeric identifier “1701187997”.
•Requests with a file extension that does not have a specific mapping are associated with the FastCGI application named “Application 7”.
Note that application names are ASCII and should generally contain only alphanumeric characters, and spaces are allowed. Application names are case-insensitive.
Note also that it is allowed for multiple mappings to be associated with the same FastCGI application.
FastCGI Application Settings
FastCGI extension has a set of configuration settings that controls the behavior of FastCGI processes associated with the FastCGI process pool. This section lists all the settings supported by FastCGI and their format:
•ExePath – The physical path to the process executable to use in the pool
•Arguments – Arguments to pass to each process in the pool at start time. This setting is optional.
•EnvironmentVars – Environment variables that are set for the process executable associated with this pool. This setting uses the following format:
EnvironmentVars=VARIABLE1:10000,VARIABLE2:20000If the environment variable value contains a space character, then enclose the value in quotes. If the environment variable value contains a comma character, then this character is escaped with “/”. Similarly, if environment variable value contains “/” then it should be escaped as well.
EnvironmentVars=VARIABLE1:”C://PHP”,VARIABLE2=”1/,2/,3″•Protocol – This setting specifies the protocol to 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 this application’s process pool that are queued before the FastCGI handler starts returning errors to clients, indicating 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. 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. The default is 0, which means that number of process instances will be adjusted automatically based on available memory and current CPU usage .
•InstanceMaxRequests – This is the number of requests that we send 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 being returned to the client as responses. This property specifies the amount of response data, in bytes, that is buffered for requests to this application. This buffer is flushed to the client once it is full, or when the response is complete, whichever occurs first. If not specified, the default value is 4194304 (4MB).
•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 happens, the web server waits for a read that is not coming, causing a deadlock on that member of the process pool. This most often happens in the case where the FastCGI process abnormally exits. For instance, the process may have an internal notion of the max number of requests it can handle that is lower than InstanceMaxRequests setting. Setting FlushNamedPipe to 1 causes FastCGI to flush data that might lead to this condition. The default is 0.
•UnhealthyOnQueueFull – If 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 does a ping to the worker process. If that worker process has been flagged as unhealthy, it (along with everything it is hosting) will be recycled. If not specified, the default value is 0.
•MonitorChangesTo – This property specifies path to a file, changes to which will trigger a recycle of FastCGI executables running for this FastCGI process pool. If value of this property is blank, file change monitoring is disabled. Path to file can be absolute or relative to folder in which FastCGI process (as specified by ExePath) is present. If not specified, default value is blank.
•StderrMode – Specifies how content received on stderr is handled. The allowed values are:
•’ReturnStderrIn500′ – FastCGI Extension will set response status code to 500 and send whatever was received on stderr stream as a response. This is the same behavior as in FastCGI Extension v1.0.
• ‘ReturnGeneric500’ – The Extension will set the response status code to 500, but will return a generic 500 response.
• ‘IgnoreAndReturn200′ – Data on stderr is completely ignored and FastCGI Extension will send what was received on stdout as a response with status code 200.
•’TerminateProcess’ – The Extension will terminate FastCGI process as soon as it returns anything on stderr. A generic response with 500 status code will be send to HTTP client.
If setting not specified, the default value is ‘ReturnStderrIn500’.
•MaxInstances – This setting dictates maximum number of FastCGI processes which can be launched for each application pool which is also equal to maximum number of requests which can be processed simultaneously as one process handle only one request at a time. This setting existed before in FastCGI Extension v1.0. However, with FastCGI Extension 1.5 it can be set to 0, which will turn on automatic adjustment of the maximum number of instances. When it is set to 0, FastCGI Extension will constantly analyze current CPU load and memory availability and based on that will increase or decrease the number of FastCGI process instances running at the same time.
•SignalBeforeTerminateSeconds – Specifies the number of seconds to elapse after setting shutdown event and before calling TerminateProcess thereby forcibly terminating the process. Default value is 0 which means event is not set and FastCGI processes can be terminated abruptly at any time. If this value is greater than 0, FastCGI process will create an event which is inherited by the child process. Handle value of this event is set as environment variable _FCGI_SHUTDOWN_EVENT_. The name of the named pipe, used to communicate with the process is stored in environment variables _FCGI_X_PIPE_.
•ActivityTimeout – This is the number of seconds that the FastCGI handler waits for I/O activity from a process before it is terminated. This setting existed before in FastCGI Extension 1.0 but in v1.5 its default value has been increased from 30 seconds to 70 seconds.
Using UTF-8 encoding for server variables
By default, FastCGI extension uses ASCII encoding when setting server variables that are used by PHP. When requested URL contains non-ASCII characters, then server variables that derive their values from the requested URL string may be set incorrectly. PHP applications that rely on those server variables may not work because of that.
To prevent this the FastCGI extension can be configured to use UTF-8 encoding when setting server variables. To configure FastCGI to use UTF-8 encoding for a particular set of server variables, use the REG_MULTI_SZ registry key FastCGIUtf8ServerVariables and set its value to a list of server variable names, for example:
reg add HKEY_LOCAL_MACHINESystemCurrentControlSetServicesw3svcParameters /v FastCGIUtf8ServerVariables /t REG_MULTI_SZ /d REQUEST_URIPATH_INFO
The above example will configure FastCGI extension to use UTF-8 encoding when setting REQUEST_URI and PATH_INFO server variables.
After setting the registry key restart the IIS by using the iisreset command.
Warning: using UTF-8 encoding for server variables may affect how PHP core and PHP applications work. Make sure to verify that applications work as expected after the registry key has been changed.
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%system32inetsrv. This script adds and removes script maps and to modifies application pool settings in 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:. This parameter specifies the name of the section that will be added to the fcgiext.ini file in [Types] block.
•-extension:. This parameter specifies what file extensions are associated with this section.
•-path:. Absolute file path to the CGI executable that processes requests for files with extension specified in –extension parameter.
•-site:. Optional parameter that specifies to which site the section should be added. If not specified, then the section is added to all sites on your web server.
•-norecycle. By default, configuration script recycles all applications pools on IIS 6.0 in order for configuration changes to take effect. This optional parameter prevents this recycling.
>cscript fcgiconfig.js -add -section:”PHP” -extension:php -path:”C:PHPphp-cgi.exe”The above example adds script map for .php extension and updates the fcgiext.ini file.
As an option, you can specify to which site the script map is applied:
>cscript fcgiconfig.js -add -section:”PHP” -extension:php -path:”C:PHPphp-cgi.exe” –site:1This example adds script map to “Default Web Site” only.
Also, you can specify to which application the script map is applied:
>cscript fcgiconfig.js -add -section:”PHP” -extension:php -path:”C:PHPphp-cgi.exe” -application:”/w3svc/1/root/app1″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:.. 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 in order for configuration changes to 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 to all the 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:. This parameter specifies the section to which the configuration change is applied.
•-:. The name of the parameter to change and its new value. The complete list of possible parameters is found in the section “Application Pool Settings”
•-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 “PHP” section:
>cscript fcgiconfig.js -set -section:”PHP” –InstanceMaxRequests:10000