Deploying Frameworks Based on ASP.NET Handlers
Using
ASP.NET handlers is the next best option to using native modules,
offering developers most of the functionality of IIS 7.0 native modules
and a significantly faster development cycle. Like IIS 7.0 modules,
ASP.NET handlers are a multithreaded environment, so they are mostly
appropriate for thread-safe application frameworks. Unlike other
application framework options, ASP.NET handlers can be configured in the
application configuration without requiring administrative privileges
on the server.
The steps to deploy an application framework that uses ASP.NET handlers are as follows:
-
Deploy the ASP.NET handler assembly to the
server (in the Global Assembly Cache). Alternatively, you can deploy it
as part of a specific application (in the application /BIN or /App_Code
directories). The latter option works well when you are deploying the
application framework to servers on which you do not have administrator
privileges.
-
Create a managed handler mapping entry that
maps the desired URL paths to the ASP.NET handler type at the server
level or for a specific site, application, or URL.
-
Optionally, install the corresponding
configuration schema and UI extensions for configuring your handler.
Then set the handler-specific configuration.
Note that the location for adding ASP.NET handler mappings is different
depending on whether the target application uses Classic or Integrated
.NET integration modes. In Integrated mode, you can add the handler
mapping directly to the IIS handler mapping list in the system.webServer/handlers configuration section or by using IIS Manager. In Classic mode, you must add the handler mapping to ASP.NET’s system.web/httpHandlers
configuration section, and you must scriptmap the corresponding
extension to the ASPNET_ISAPI.dll ISAPI extension in the IIS handler
mappings (the latter can be done with IIS Manager).
Like IIS 7.0 native modules, ASP.NET
handlers are In-Process components that the IIS worker process loads.
Unlike IIS 7.0 native modules, ASP.NET handlers are loaded and executed
inside the ASP.NET application. The ASP.NET application can additionally
isolate the content and request execution by using partial trust.
Though by default ASP.NET handlers execute
with the identity of the IIS worker process, they can also be
configured to impersonate the authenticated user or an arbitrary
identity through the ASP.NET system.webServer/identity
configuration. To ensure that your application framework can access the
desired files, allow them to be read by the IIS worker process by
granting Read access to IIS_IUSRS group.
Additionally, if you need to isolate your
applications for reliability or security reasons, you need to use the
IIS application as a unit of isolation by placing different applications
in different IIS application pools.
Deploying Frameworks Based on ISAPI Extensions
ISAPI
extensions have traditionally been the preferred way to interface
application frameworks with previous versions of IIS. As a result, a
number of application frameworks that exist today use an ISAPI extension
when hosted in the IIS environment. Like IIS 7.0 modules and ASP.NET
handlers, ISAPI extensions are a multithreaded environment, so it is
mostly appropriate for thread-safe application frameworks. Adding ISAPI
extensions requires server administrator privileges.
To deploy an application framework that uses ISAPI extensions, you need to perform the following steps:
-
Create a scriptmap-based handler mapping
entry that maps the desired URL paths to the ISAPI extension, at the
server level or for a specific site, application, or URL.
-
Add the ISAPI extension to the system.webServer/security/isapiCgiRestriction configuration. This requires administrative privileges.
Note
IIS Manager can automatically prompt you to create the ISAPI extension entry in the system.webServer/security/isapiCgiRestriction configuration section when you create the handler mapping. This requires you to be connected as a server administrator.
ISAPI extensions, like IIS 7.0 native modules,
are loaded In-Process in the IIS worker process. However, unlike IIS 7.0
native modules, they are by default made to impersonate the
authenticated user if one is available. Therefore, they typically
execute with the identity of the IIS anonymous user (IUSR by default) or
the authenticated user if it’s available and has an associated Windows
principal.
However, some application frameworks may
chose to revert this impersonation and instead execute with the IIS
worker process identity. In IIS 7.0, it is also possible to make the
anonymous user the same user as the IIS worker process identity,
achieving the same behavior for anonymous requests.
As before, if you need to isolate your
applications for reliability or security reasons, you need to use the
IIS application as a unit of isolation by placing different applications
in different IIS application pools.
Deploying Frameworks That Use FastCGI
FastCGI is a new application framework option in
IIS 7.0. Unlike ISAPI extensions, IIS 7.0 modules and ASP.NET
handlers—which are both IIS-specific extension mechanisms—FastCGI uses
the open FastCGI protocol to interface with application frameworks. This
enables a variety
of existing application frameworks that support FastCGI on other Web
server platforms to work on IIS. The FastCGI protocol enables
significant performance improvements over CGI, which has been supported
in IIS since early versions. It does this while maintaining the single
request per process requirement that many of these application
frameworks have due to lack of thread safety in the framework
implementation itself or the applications that use it.
The FastCGI support is implemented by
the FastCGI module. This module maintains a pool of one or more FastCGI
processes for each FastCGI application executable configured globally on
the server. When a request that is mapped to the FastCGI module and the
corresponding FastCGI application is received, it is forwarded to one
of the processes in the corresponding FastCGI process pool by using the
FastCGI protocol. The FastCGI application process then processes the
request and returns the response to the FastCGI module, which then
writes it to the response. Unlike CGI, the FastCGI application processes
are long-lived and are reused on subsequent requests, which eliminates
the overhead of starting and destroying application processes for each
request.
To deploy an application framework that uses FastCGI, perform the following steps:
-
Create a module-based handler mapping entry
that maps the desired URL paths to the FastCGIModule module, using the
path of the FastCGI executable and the arguments to pass to it as the
script processor. You can create this at the server level or for a
specific site, application, or URL.
-
Create a FastCGI application entry for the
FastCGI executable. When you add the handler mapping through IIS
Manager, it will automatically prompt you to do this if you are
connected as a server administrator. You must be a server administrator
to create this entry.
After the FastCGI application entry
for the specific FastCGI executable is created on the server (this
requires administrative privileges), it can be used to create handler
mappings at any configuration level. This means that after the server
administrator allows a particular application framework’s FastCGI
executable, any application on the server can use it.
Unlike CGI, which starts a new process to
handle each request and executes this process with the identity of the
IIS authenticated user by default, FastCGI worker processes are
long-lived and always execute under the same identity as the parent
application pool. This means that FastCGI application framework
executables and their scripts will be executed with the identity of the
application pool to which the IIS application that contains the scripts
belongs. This aligns well with the IIS model, enabling you to manage
access to resources in a uniform way across the entire site. It also
enables you to securely isolate FastCGI applications in the same manner
as the rest of the site contents by using application pool isolation.
Modifying FastCGI Application Settings
When
creating the FastCGI application entry for the FastCGI executable, you
have a number of options that you can configure to modify the behavior
of the corresponding FastCGI process pool. Table 2 illustrates these options.
Table 2. Parameters for Editing FastCGI Application Definitions
Setting |
Description |
---|
fullPath |
The full path to the FastCGI executable. |
Arguments |
The arguments to pass to the FastCGI executable. |
maxInstances |
The maximum number of processes that can be started for this application. Default is four. |
idleTimeout |
The time in seconds that must pass after the
last request was processed by a FastCGI process before which it is shut
down due to inactivity. Default is 300 seconds. |
activityTimeout |
The time in seconds that must pass while
waiting for activity from the FastCGI process during request processing,
after which the process is considered deadlocked and will be forcefully
shut down. This is effectively a rolling script time-out. Default is 30
seconds. |
requestTimeout |
The maximum time in seconds that the FastCGI process can take to process a request. Default is 90 seconds. |
instanceMaxRequests |
The number of requests that each FastCGI process can process before being shut down. Default is 200. |
Protocol |
The FastCGI protocol to use to connect to the FastCGI process. The two allowed values are NamedPipe and Tcp. The default is NamedPipe. |
queueLength |
The maximum number of requests that can be
queued while waiting for the next available FastCGI process before
requests are rejected with a 503 error code. The default is 1000. |
flushNamedPipe |
Whether to flush the data sent to the FastCGI
process when using named pipes. This may be necessary for some FastCGI
applications that may otherwise hang while waiting for data from the FastCgiModule, at the cost of a potential performance decrease. The default is false. |
rapidFailsPerMinute |
How many FastCGI process failures are
allowed per minute. If the number of failures exceeds this value over a
60-second period, FastCGI will not create any more processes for the
FastCGI application. The default is 10. |
environmentVariables |
Enables a collection of additional environment variables to be specified for the FastCGI application process. Each environmentVariable element inside the collection can specify the name of the environment variable and its value. |
In Windows Server 2008, IIS Manager does
not provide a way to modify these settings. Therefore, if you need to
set them, you can edit the configuration directly, or use Appcmd or one
of the programmatic APIs to do it. For example, to use Appcmd to create a new FastCGI application entry with the instanceMaxRequests attribute set to 10, you can use the following syntax.
%systemroot%\system32\inetsrv\AppCmd.exe Set Config
/section:system.webServer/fastCgi
"/+[fullPath='Path',arguments='Arguments'instanceMaxRequests='10']"
Path is the required path to the executable, and Arguments are the optional arguments to pass. You can also specify any of the other attributes listed in Table 2 to set them to a specific value, as is done for instanceMaxRequests.
To list the existing entries, you can use the following syntax.
%systemroot%\system32\inetsrv\AppCmd.exe List Config
/section:system.WebServer/fastCgi
You can also set specific attributes on an existing element. For example, to set the idleTimeout attribute to 60 seconds, you can use the following syntax.
%systemroot%\system32\inetsrv\AppCmd.exe Set Config
/section:system.WebServer/fastCgi
"/[fullPath='Path',arguments='Arguments'].idleTimeout:60"
Path and Arguments are keys to match a corresponding existing application entry. You can use this syntax to set any of the attributes listed in Table 11-7.
Ensuring Availability of FastCGI Applications
Depending on the behavior of your
application framework, the specific application, and overall Web server
configuration, you may need to adjust the FastCGI application settings
to achieve optimal performance and availability of your application. You
may need to do some of the following:
-
Adjust the default setting for maxInstances
upward from four processes to allow for greater request concurrency.
Though this may increase CPU contention on your server by creating more
processes, it can help increase your application’s responsiveness,
especially if it makes long-running database or network operations.
-
Reduce the idleTimeout
setting to proactively shut down unused FastCGI processes during
periods of lower activity. This may be especially needed on shared
hosting servers that have multiple application pools and therefore
multiple FastCGI process pools for each FastCGI application.
-
If your application also experiences large request volumes that lead to temporary queuing, you may need to adjust queueLength upward to accommodate larger queue sizes during high request activity.
-
Adjust instanceMaxRequests
to improve performance by allowing each process to handle more requests
before being shut down. This may be a tradeoff with application
stability if your application leaks memory or develops unstable behavior over time. In addition, it is important to keep instanceMaxRequests
under the corresponding internal request limit of the FastCGI
executable. Otherwise, the FastCGI module may fail when the FastCGI
process terminates unexpectedly due to its internal request limit.
-
Adjust activityTimeout and requestTimeout to prevent errors for scripts that take a longer time to return response or complete.
More Info
PHP has an internal request limit of 500
requests by default, which can be overridden by setting the
PHP_FCGI_MAX_REQUESTS environment variable globally on the server or
specifically for the FastCGI application entry.
The exact values of these settings depend on
the specifics of the application framework, the application, the overall
Web server environment, and server hardware. As such, it is difficult
to recommend specific defaults, and you’ll need to do performance
testing to achieve the desired settings to meet your performance and
availability requirements.
Deploying Frameworks That Use CGI
IIS 7.0 continues to provide support for
CGI applications that use the open CGI protocol to communicate with the
Web server. The CGI protocol requires each new request to start a new
CGI process to handle it, which has a very heavy performance overhead on
Windows. FastCGI is a preferred alternative to CGI, because it offers
much greater performance due to process reuse. However, for application
frameworks that do not support FastCGI or any of the native IIS
mechanisms, CGI is an option.
To deploy a CGI program, you need to perform the following steps:
-
Create a scriptmap-based handler mapping
entry that maps the desired URL paths to the CGI executable path and any
required arguments. You can create this mapping at the server level or
for a specific site, application, or URL.
-
Add the CGI executable to the system.webServer/security/isapiCgiRestriction
configuration. This requires administrative privileges. This is a
required step to allow a unique CGI executable path and arguments
combination to be executed on the Web server.
Alternatively, CGI also supports the
ability to launch .exe files located within your application when the
client requests the executable file directly. This requires the
directory to have Execute permissions and requires the executable files
themselves to enable Execute permissions for the authenticated user.
When a handler mapping is used instead, with a
script processor configured to point to the CGI program, only Script
permissions are required. In both cases, the exact command lines (path to the CGI program and any arguments passed to it) must be listed in the system.webServer/security/isapiCGIRestriction configuration section.
Note
IIS Manager can automatically prompt you to create the CGI executable entry in the system.webServer/security/isapiCgiRestriction configuration section when you create the handler mapping. This requires you to be connected as a server administrator.
Note
It is not possible to set custom environment
variables for the CGI process. CGI always passes a fixed set of server
variables as environment variables for the CGI process, as defined in
the CGI protocol specification. If your application framework supports
the FastCGI protocol and if you are using FastCGI, you can set custom
environment variables.
Because CGI starts a new process each time a
request is received, it enables it to execute the CGI process under the
identity of the authenticated user, if one is available. This is the
default behavior. Because of this, CGI processes and the scripts the
processes execute will by default run under the identity of the
authenticated user, or under the IIS anonymous user (IIS_IUSR) for
anonymous requests. You can disable this behavior globally on the
machine by setting the createProcessAsUser attribute in the system.webServer/cgi configuration section to false.
You can set CGI configuration settings in IIS
Manager, from the command line by using Appcmd, or by using
configuration APIs. The system.webServer/cgi
configuration section is global and therefore can have only a single
set of settings for the entire server. You can set a configuration in
this section by using the following Appcmd syntax.
%systemroot%\system32\inetsrv\Appcmd set config
/section:system.WebServer/cgi [/createCGIWithNewConsole:bool]
[/createProcessAsUser:bool] [/timeout:timespan]
The parameters for setting CGI configuration are listed in Table 3.
Table 3. Parameters for Setting CGI Configuration
Setting |
Description |
---|
createCGIWithNewConsole |
Whether or not to create each CGI process with a new console. The default is false. |
createProcessAsUser |
Whether or not to create each CGI process under the identity of the authenticated user. The default is true. |
Timeout |
The request time-out in seconds after which the CGI process is terminated. The default is 15 minutes. |
Note
If
you use a custom account for the application pool, you need to grant
the custom account the Adjust Memory Quotas For A Process and Replace A
Process Level Token user rights. You can do this using the Local
Security Policy console.
In addition, you can configure a limit of CGI
processes that can be active simultaneously for any IIS worker process.
If the number is exceeded, all subsequent CGI requests to the worker
process will be queued until the number of CGI processes falls below the
limit. This setting can be configured only in the registry by creating
the MaxConcurrentCgisExecuting DWORD
value in the registry key,
HKLM\System\CurrentControlSet\Services\W3SVC\Parameters\. By default,
when this value is not set, the limit is 256 CGI processes per IIS
worker process.
Caution
Be aware that starting a large number of
CGI processes can quickly overwhelm a Web server due to both the memory
overhead of each process and the cost of starting a new process. This
occurs especially if you have multiple application pools, because the
limit is applied to each IIS worker process individually. Because of
this, you may need to set the MaxConcurrentCgisExecuting limit to a much lower value. Consider using FastCGI instead of CGI to reduce this overhead.