Original article address: ASP. NET Internals-The bridge between ISAPI and Application Domains.
2007.06.13
Simone Busoli
ASP. NET internal working principle sometimes looks like the dark magic behind the scenes, providing developers with a high-level abstraction, so that they only focus on the business logic of the application, it does not need to deal with the underlying mechanism of the HTTP protocol. ASP. NET is developed based on the. NET Framework and applied to the. NET Framework. Therefore, most of the Code is hosted. However, the web request entry point is a web server written using native code. Therefore, a communication mechanism is required. In this article, I will describe the bridges between managed and unmanaged worlds, and how they collaborate to set the processing environment required for ASP. NET to process requests.
Refer to Part 1: ASP. NET insider-IIS Processing Model
Introduction
In the previous article, this is also the first article in this series. I introduced the first step after the web server receives the web request, and if it is determined as ASP.. NET resource requests. You already know that different IIS versions are processing ASP. NET requests are distributed to an unmanaged Win32 component called aspnet_isapi.dll. The role of this component is web server and ASP. NET architecture.
In this article, I will continue to discuss the legacy issues in the previous article and start to study the hosting part of the processing environment. In the previous article, it is called ASP. NET runtime environment, as mentioned in a black box.
Note: The ASP. NET runtime environment is sometimes called an ASP. NET pipeline, an Http runtime pipeline, or a mix of these words.
Extended from aspnet_isapi.dll to managed World
In the previous article, I explained how IIS 5 and IIS 6 manage ASP.. NET requests, ignoring how they process the creation, management, and recovery of work processes. Finally, all request-related messages are attributed to the aspnet_isapi.dll extension.
This is a bridge between the unmanaged and hosted worlds, and is also part of the most lacking documentation in all ASP. NET architectures.
Note: At the time of writing this article, IIS 7 was released along with Longhorn Server Beta 3 with a launch license. Many things will change in IIS 7. Although these earlier articles only focus on the earlier versions of IIS, the later articles will focus on the improvements introduced in IIS 7.
Due to the lack of documentation available in many aspects of this topic, the explanations I will explain may not be completely correct, especially those that involve the unmanaged structure. However, my considerations for undocumented topics are based on some tools that are helpful for understanding the internal working principles of the framework:
- Lutz Roeder's. NET
Reflector: Static Analysis and decompilation of. NET hosted code.
-
Microsoft CLR Profiler analyzes the dynamic behavior of the framework by viewing method calls, memory allocation, class structure, and many other features it provides.
- JetBrains dotTrace
Profiler is a commercial analysis tool for. NET applications. You can also obtain a free version with time constraints.
- Red Gate
ANTS Profiler, another commercial analysis tool for. NET applications, can obtain a free version with time constraints.
Return to the bridge between the unmanaged and hosted worlds, whether it is through ISAPI extension in IIS 6 processing mode, or through a worker process in IIS 5 processing mode, after CLR loading, dark magic appears. ASP. the. net isapi component is located in the System. web. two managed classes in the Hosting namespace call the unmanaged COM interface of the Hosting and expose these methods using the COM interface. The classes are AppManagerAppDomainFactory and ISAPIRuntime.
Note: When running in a common language, the CLR manages the execution environment of every. NET application. It provides the environment and services for running hosted applications. CLR must run in Win32 process, ASP. NET is. NET Framework is one of the hosts provided by CLR, specifically in ASP. NET, ASP. NET Worker Process (aspnet_wp.exe in IIS 5 and w3wp.exe in IIS 6) is the process that runs CLR.
Before studying the technical details of interaction behaviors in these classes, let's take a rough look at what happened during request processing. I have already introduced these two classes, because the entry points for processing requests can be roughly divided into two aspects.
1. If the AppDomain does not exist, create an APPDomain and assign the AppDomain to the application corresponding to the request, which is implemented through the AppManagerAppDomain class.
2. Submit and process requests, implemented by the ISAPIRuntime class.
These two aspects are very important. The first one includes some interactive actions that do not require developers to participate, mainly involving the running environment of the application, the second part is the most configurable structure. I will discuss it in subsequent articles in this series.
From another point of view, the first step contains only one operation in the lifetime of the application, that is, at startup, the interaction contained in step 2 appears every time the target application of the request is located.
Create AppDomain
As mentioned in the previous article, an ASP. NET application is encapsulated into an entity called an application domain, abbreviated as AppDomain, represented by an AppDomain class in the ASP. NET architecture. When a request from a specific application arrives, an AppDomain object must be created if it does not exist. This usually occurs when a request from a specific application arrives for the first time, or, for some reason, the corresponding AppDomain is closed. I will talk about several reasons that may cause this problem later. Note that only one AppDomain exists in an ASP. NET application. It maps to an IIS application one-to-one and may be created based on a physical or virtual directory. So how is this class instance created?
Figure 1: Call Stack generated by JetBrains dotTrace Profiler when an AppDomain instance is created
Using Reflector, we can infer that the AppDomain has a private constructor that throws the NotSupportedException exception. Therefore, this method obviously does not work. In fact, the entrance point for initializing an AppDomain instance is the AppManagerAppDomainFactory. Create method. To find this point, you need to use a analyzer to track the call stack generated when initializing the object. Figure 1 shows the screenshot of JetBrains dotTrac Profiler. It shows the call stack generated when a web application running on IIS initializes AppDomain. There are many classes involved in this process, which may never be used by developers.
Note: The AppManagerAppDomainFactory class only runs once during CLR initialization, as its name implies, and serves as the entry point for creating AppDomain and other important objects.
Figure 2 shows a call stack that is the same as Figure 1. This time, it is intercepted from the output of the Microsoft CLR Profiler call tree and provides more information for AppDomain initialization. In fact, the highlighted line indicates that the main thread has created two AppDomain class instances.
Figure 2: Call Stack displayed in the call Tree View of Microsoft CLR Profiler during AppDomain instance Creation
So how to create this additional instance and why? Unfortunately, this is not an easy problem. The call stack shown in the preceding figure shows the steps used to create an AppDomain instance related to the actual application. Therefore, this additional instance, it looks like a secondary object for some hard-to-understand purposes. I guess it is used to hold all objects that do not belong to any application, such as AppManagerAppDomainFactory, therefore, it is placed in an isolated AppDomain. For the AppManagerAppDomainFactory class, this auxiliary AppDomain is instantiated only once during CLR initialization, and is carried out very early during CLR initialization, as shown in 3.
Figure 3: Order and allocation of additional AppDomain instances
Figure 3 shows a screenshot of the Red Gate ANTS Profiler. It shows that the additional AppDomain instance was created early in CLR initialization. Obviously, it was created earlier than the AppManagerAppDomainFactory class, because it is likely to be the container of AppManagerAppDomainFactory. In fact, in the preceding analysis session graph, the ID of the single-instance AppManagerAppDomainFactory instance is 52.
The other method for viewing the initialization process of the two AppDomain instances mentioned above is the allocation view provided by Microsoft CLR Profiler. It creates a graphical process to display the position of classes used in processing, as shown in figure 4.
Figure 4: Two AppDomain initialization processes displayed in the Microsoft CLR Profiler allocation View
It shows a flat view where all classes are cropped from the root element, namely CLR, and thread classes. However, it clearly shows the call sequence when two AppDomains are created.
As shown in the preceding figure, another information about the AppDomain instance is that each instance occupies 100 bytes of memory. This will not cause many problems, but some people will think that AppDomain is a very large class, because it must accommodate the entire application. In fact, it provides many services, but does not store too much data.
Until now, the auxiliary AppDomain instance has been created, including the AppManagerAppDomainFactory class. Its Create method is the call stack entry method shown in Figure 1 and 2.
This method is exposed through COM and provided to the caller, so it is not managed code. The AppManagerAppDomainFactory class implements the IAppManagerAppDomainFactory interface. Its structure is shown in Figure 5.
Figure 5: IAppManagerAppDomainFactory INTERFACE STRUCTURE
This interface is modified using the ComImport and InterfaceType attributes. They bind the type to the type of the unmanaged interface. When this method is called, the call stack graphics shown in Figure 1 and figure 2 will be generated, and the creation of the AppDomain class instance will be triggered to accommodate the target application for processing the request.
After the AppDomain object is created and run, the remaining work is to process the request, which is more than the previous work content, which may be ASP. NET architecture is the most interesting part, but before this interesting part begins, I have introduced some key topics.
Summary
This article introduces ASP. some underlying topics in the NET infrastructure are related to those created by ASP.. net isapi extended display of the unmanaged world, as well as some interfaces between managed worlds displayed by the AppDomain running web applications. I demonstrate the mechanism for initializing AppDomain and which classes are involved in this process. In the next article, I will discuss the managed code through the HTTP pipeline. In my image, this should be ASP. NET architecture, in fact it makes ASP. NET is different from all other web development frameworks. I hope that you will be as interested in reading this article. My suggestion is to open some analysis tools and try it on your own. This is the best way to fully understand how it works.
Reference
Simone Busoli-ASP. NET Internals-IIS and the Process
Model
Rick Strahl-
A low-level Look at the ASP. NET Architecture
Dino Esposito-
Programming Microsoft ASP. NET 2.0 Core Reference
Dino Esposito-
Programming Microsoft ASP. NET 2.0 Applications Advanced Topics