HTTP.SYS Kernel mode driver - iis

What is the big deal with HTTP.SYS in IIS 7?
From what I understand, it is low level which is good for security. Why?
There is no context switching which could be expensive. Why?
Please explain.
Thanks!

The benefits are already well documented,
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/a2a45c42-38bc-464c-a097-d7a202092a54.mspx?mfr=true
By using HTTP.sys to process requests, IIS 6.0 delivers the following
performance enhancements:
Kernel-mode caching. Requests for cached responses are served without switching to user mode.
Kernel-mode request queuing. Requests cause less overhead in context switching, because the kernel forwards requests directly to the correct worker process. If no worker process is available to accept a request, the kernel-mode request queue holds the request until a worker process picks it up.
Using HTTP.sys and the new WWW service architecture provides the following benefits:
When a worker process fails, service is not interrupted; the failure is undetectable by the user because the kernel queues the requests while the WWW service starts a new worker process for that application pool.
Requests are processed faster because they are routed directly from the kernel to the appropriate user-mode worker process instead of being routed between two user-mode processes.
http://learn.iis.net/page.aspx/101/introduction-to-iis-7-architecture/
HTTP.sys provides the following benefits:
Kernel-mode caching. Requests for cached responses are served without switching to user mode.
Kernel-mode request queuing. Requests cause less overhead in context switching because the kernel forwards requests directly to the correct worker process. If no worker process is available to accept a request, the kernel-mode request queue holds the request until a worker process picks it up.
Request pre-processing and security filtering.

Related

Tuning gRPC thread pool

I'm dealing with a legacy synchronous server that has operations running for upto a minute and exposes 3 ports to overcome this problem. There is "light-requests" port, "heavy-but-important" requests port and "heavy" port.
They all expose the same service, but since they run on separate ports, they end up with dedicated thread pools.
Now this approach is running into a problem with load balancing, as Envoy can't handle a single services exposing the same proto on 3 different ports.
I'm trying to come up with a single threadpool configuration that would work (probably an extremely overprovisioned one), but I can't find any documentation on what the threadpool settings actually do.
NUM_CQS
Number of completion queues.
MIN_POLLERS
Minimum number of polling threads.
MAX_POLLERS
Maximum number of polling threads.
CQ_TIMEOUT_MSEC
Completion queue timeout in milliseconds.
Is there some reason why you need the requests split into three different thread pools? By default, there is no limit to the number of request handler threads. The sync server will spawn a new thread for each request, so the number of threads will be determined by the number of concurrent requests -- the only real limit is what your server machine can handle. (If you actually want to bound the number of threads, I think you can do so via ResourceQuota::SetMaxThreads(), although that's a global limit, not one per class of requests.)
Note that the request handler threads are independent from the number of polling threads set via MIN_POLLERS and MAX_POLLERS, so those settings probably aren't relevant here.
UPDATE: Actually, I just learned that my description above, while correct in a practical sense, got some of the internal details wrong. There is actually just one thread pool for both polling and request handlers. When a request comes in, an existing polling thread basically becomes a request handler thread, and when the request handler completes, that thread is available to become a polling thread again. The MIN_POLLERS and MAX_POLLERS options allow tuning the number of threads that are used for polling: when a polling thread becomes a request handler thread, if there are not enough polling threads remaining, a new one will be spawned, and when a request handler finishes, if there are too many polling threads, the thread will terminate. But none of this affects the number of threads used for request handlers -- that is still unbounded by default.

How does Network I/O happens in node.js?

I have been searching about the node.js internal thread pool for I/O and found out that Network I/O does not use threads for requests.
1) Then what puts the cap on limit of network request processed asynchronously in my node.js server? I am trying to use cluster module on my octa core processor and would be using 8 forked instances. I just want to know that how many network I/O requests to 3rd party Api can each forked instance handle!
I have kind of an intuition that the network requests currently not processed might be queued in somwhere!
2) Asynchronous work like File I/O uses thread pool, how is that handled with internal thread pool of a fixed size?
How many requests(in this case, threads used) are too many?

How HTTP.sys forward request to worker process

I wanted to get an overview of the way HTTP.sys forwards request to work process in IIS 7.0 and above. For that purpose I read the post at http://www.iis.net/learn/get-started/introduction-to-iis/introduction-to-iis-architecture. However, there are two points in this post that seem to be contradicting and is confusing me.
Point 1: 2nd bullet point mentioned under section "Hypertext Transfer Protocol Stack (HTTP.sys)" is as follows.
Kernel-mode request queuing. Requests cause less overhead in context switching because the kernel forwards requests directly to the correct worker process. If no worker process is available to accept a request, the kernel-mode request queue holds the request until a worker process picks it up.
My conclusion according to this point is as follows:
HTTP.sys forwards request "directly" to worker process bypassing the WWW service. In case no worker process is available, HTTP.sys queues the request in kernel-mode request queue while WAS service starts a new worker process. This worker process then picks up requests from the kernel-mode queue on its own.
Point 2: Process Management subsection under the section "Windows Process Activation Service(WAS)" is as follows.
WAS manages application pools and worker processes for both HTTP and non-HTTP requests. When a protocol listener picks up a client request, WAS determines if a worker process is running or not. If an application pool already has a worker process that is servicing requests, the listener adapter passes the request onto the worker process for processing. If there is no worker process in the application pool, WAS will start a worker process so that the listener adapter can pass the request to it for processing.
My conclusion according to this point is as follows:
HTTP.sys forwards request to the worker process "through WWW service" as that is the listener adapter. In case no worker process is available, HTTP.sys queues the request in kernel-mode request queue while WAS service starts a new worker process. The request from the kernel-mode queue is then picked up by WWW service and forwarded to the worker process.
Could anyone please let me know which of my above two conclusions is correct? If both are incorrect, please let me know the right flow.
I dont think either is correct. I was also trying to figure out the exact workings and finally found the HTTP Server API, https://learn.microsoft.com/en-us/windows/desktop/http/http-version-2-0-architecture.
"HTTP.sys forwards request to the worker process "through WWW service" as that is the listener adapter." From the documentation above, and here https://learn.microsoft.com/en-us/windows/desktop/http/process-isolation, you can seen the HTTP Kernel Mode(http.sys) routes requests to queues that are associated with urls. The queue would have been configured when the app pool was created in iis mgr and the urls would have been associated with the queue when you create a website in IIS mgr and tie the website to a pool. http.sys puts stuff in queues. The app pool process processes stuff from the queues. No direct interaction between http.sys and worker process.
"In case no worker process is available,..." this is not true either from the Process Isolation documentation above:
Creator or controller process: The controller process can run with, or without, administrative privileges to monitor the health and configure the service. The controller process typically creates a single server session for the service and defines the URL groups under the server session. The URL group that a particular URL is associated with determines which request queue services the namespace denoted by the particular URL. The controller process also creates the request queue and launches the worker processes that can access the request queue.
Worker Process: The worker processes, launched by the controller process, perform IO on the request queue that is associated with the URLs they service. The web application is granted access to the request queue by the controller process in the ACL when the request queue is created. Unless the web application is also the creator process, it does not manage the service or configure the request queue. The controller process communicates the name of the request queue to the worker process and the worker process opens the request queue by name. Worker processes can load third party web applications without introducing security vulnerabilities in other parts of the application.
So the controller process would create the workers. This is without a doubt the WAS, exactly how it detects when to create a process is not defined, but its definitely the "controller process" spoken about above.
Interesting, in asp.net core you can run your app on top of http.sys, Microsoft.AspNetCore.Server.HttpSys. Interntally it uses this api to configure things. https://github.com/aspnet/HttpSysServer/blob/master/src/Microsoft.AspNetCore.Server.HttpSys/NativeInterop/HttpApi.cs.
This documentation cleared up a lot of confusion for me. I hope it helps.

Is requests in IIS httppipeline processed serially?

Based on iis architecture, request from client hitting IIS will pass through httppipeline, specifically through each httpmodule and finally reaches respective httphandlers and then to worker process. Is this happening serially, one after the other?
Say if 10,000 requests hits the webserver concurrently in a sec, is each request get processed one by one? If the webserver has multi-core CPU and high memory capacity, does this helps IIS to handle the requests simultaneously?
Is there any webserver capable to handle requests in parallel?
I just replied to this guys question - very similar, and the answer is the same:
IIS and HTTP pipelining, processing requests in parallel

Relation between HTTP.sys request queue and IIS app pool

I read this from < IIS 7.0 resource kit >
HTTP.sys maintains a request queue for each worker process. It sends the HTTP requests to the request queue for the worker process that serves the application pool where the requested application is located.
For each application, HTTP.sys maintains the URI namespace routing table with one entry. The routing table data is used to determine which application pool responds to requests from what parts of the namespace. Each request queue corresponds to one application pool. And application pool corresponds to one request queues within HTTP.sys and one or more worker processes.
The bold parts confused me.
My understanding is: HTTP.sys matain a request queue for each worker process. An application pool can have one or more worker processes. So an application pool should also corresponds to one or more request queues. Why only one in the bold sentence?
And btw, could anyone give a more clear explanation about the URI namespace routing table? Some examples would be better.
Thanks.
To discuss a paragraph in a book, you should give more info.
This paragraph comes from "IIS 7.0 Core Components" section, and the version at Safari Books Online is different from what you pasted,
HTTP.sys maintains a request queue for each worker process. It sends
the HTTP requests it receives to the request queue for the worker
process that serves the application pool where the requested
application is located. For each application, HTTP.sys maintains the
URI namespace routing table with one entry. The routing table data is
used to determine which application pool responds to requests from
what parts of the namespace. Each request queue corresponds to one
application pool. An application pool corresponds to one request queue
within HTTP.sys and one or more worker processes.
So the last sentence should be understood as,
An application pool corresponds to one request queue within http.sys.
An application pool corresponds to one or more worker processes.
Thus, your understanding of "HTTP.sys maintains a request queue for each worker process" is not correct. The correct one should be "HTTP.sys maintains a request queue for each application pool". So no matter how many worker processes are there for a single application pool, they only serve requests from a single request queue in http.sys.
"For each application, HTTP.sys maintains the URI namespace routing
table with one entry"
I think it should be "for each application pool, HTTP.sys maintains the URI namespace routing table with one entry". This routing table makes it easier to dispatch requests (whose URL is clear) to the pools. Very similar to a hash table.
The table can be constructed from <sites> tag in applicationHost.config, by combining sites, their bindings, applications, and their application pool association. There is no further information from Microsoft on the exact table structure.
I am struggling with the same question... but I think the process is as follows:
Request intercepted by HTTP.sys
HTTP.sys makes initial contact with WAS
WAS read the ApplicationHost.config and passes it the WWW service.
WWW service configures HTTP.sys (from this point, the HTTP.sys has set up the corresponding application pool queue I guess)
HTTP.sys checks if an worker process is available, (contacts WAS via WWW) if not, the request is stored in the application queue.
=> if a worker process is available, the request is now forwarded to the correct worker pool
If no worker process is available, the request is stored in the application queue. HTTP.sys will now notify WAS (via the WWW service) that a new request has been added to the queue. The WWW service will ask WAS for a worker process. WAS will spawn one and let WWW know that an app pool has been created. Now WWW can pass the request to the corresponding worker process(by adding it to its queue queue). Then WWW will let HTTP.sys know that a worker process is spawned, so the next request, HTTP.sys can forward the request immmediatly...
I am not completely sure if this is technically all correct, so if anyone could correct/confirm this, that would be great!
A listener needs to receive messages. For this, it needs to open a socket (or a pipe handle, or start an MSMQ read, and so on). However, in order to receive the proper messages, it needs to obtain the necessary addressing information from WAS. This is accomplished during listener startup. The protocol's listener adapter calls a function on the WAS listener adapter interface and essentially says, "I am now listening on the net.tcp protocol; please use this set of callback functions I'm handing you to tell me what I need to know." In response, WAS will call back with any configuration it has for applications that are set up to accept messages over the protocol in question. For example, a TCP listener would be informed that there were two applications (*:7777/Foo and *:7777/Bar) configured to use TCP. WAS also assigns to each application a unique listener channel ID used for associating requests with their destination applications.
The listener process uses the configuration information provided by WAS to build up a routing table, which it will use to map incoming requests to listener channel IDs as they arrive.
An application pool can have one or more worker processes
This is not correct 1 App Pool = 1 Worker Process

Resources