设为首页 收藏本站
查看: 716|回复: 0

[经验分享] ASP.NET Internals – IIS and the Process Model(http://dotnetslackers.com/articles

[复制链接]

尚未签到

发表于 2015-8-16 07:16:02 | 显示全部楼层 |阅读模式
  In this article I'm going to describe the bridge between managed and unmanaged worlds and how the two collaborate to set up the processing environment needed by ASP.NET requests to be processed.


See Part 1: ASP.NET Internals – IIS and the Process Model Introduction
  In the previous as well as first article of this series I've introduced the first steps performed by a generic web request once accepted by the web server, and what route it takes when it is identified as an ASP.NET resource request. You've seen how different releases of IIS deal with incoming ASP.NET-related requests until they finally dispatch them to an unmanaged Win32 component called aspnet_isapi.dll, which acts as a bridge between the web server and the managed ASP.NET infrastructure.
  In this article I'm going to resume the discussion exactly where I left it and start delving into the managed part of the processing environment I've presented in the previous article as those black boxes labeled ASP.NET Http Runtime Environment.

Note: The ASP.NET Http Runtime Environment is sometimes also referred to as the ASP.NET Pipeline, Http Runtime Pipeline or a mix of these words.Leaving the aspnet_isapi.dll extension for the managed world
  In the previous article I've explained how IIS 5 and IIS 6 manage ASP.NET requests. Regardless of how they deal with worker processes generation, management and recycling, all the information pertaining to the request is in the end forwarded to the aspnet_isapi.dll extension.
  This is the bridge between the unmanaged and managed world and is the least documented part of all the ASP.NET architecture.

Note: At the moment of the writing of this article IIS 7 has just been released with a Go Live license along with Longhorn Server Beta 3. A lot of things will change with IIS 7, and although these first articles have been focusing solely on previous versions of IIS, a future article will be dedicated to changes and improvements introduced by IIS 7.  As for the lack of documentation available on most parts of this topic, what I'm going to explain may not be completely correct, especially for what concerns the unmanaged parts of the infrastructure. However, my considerations on the undocumented topics are based on some tools which helped a lot in understanding and making sense of the inner workings of the framework:

  • Lutz Roeder's .NET Reflector, to analyze statically and decompile the code of .NET managed classes.
  • Microsoft CLR Profiler, to analyze the dynamic behavior of the framework by looking at method calls, memory allocation, class instantiation and a whole big number of other features it provides.
  • JetBrains dotTrace Profiler, a commercial profiler for .NET Applications. A free time limited version is available too.
  • Red Gate ANTS Profiler, another commercial profiler for .NET applications. A free time limited version is available.
  Going back to the bridge between the unmanaged and managed worlds, once the CLR has been loaded - either by the ISAPI Extension in case of IIS 6 process model or by the worker process in case of IIS 5 process model - the black magic occurs through a bunch of unmanaged COM interfaces calls that the ASP.NET ISAPI component makes to a couple of managed classes contained in the System.Web.Hosting namespace, the AppManagerAppDomainFactory class and the ISAPIRuntime class, which expose some methods via COM-callable interfaces.

Note: The Common Language Runtime - CLR - represents the execution environment of every .NET application. It's what actually provides both environment and services for running managed applications. It has to be hosted inside a Win32 process and ASP.NET is one of the available hosts for the CLR provided by the .NET framework. More specifically, the ASP.NET worker process (aspnet_wp.exe in IIS 5 and w3wp.exe in IIS 6) is the process who hosts the CLR in ASP.NET.  Before delving into the technical details of the interactions occurring between these classes let's see on the surface what actually happens for a request to be processed. I have introduced the previous two classes because the entry points in the processing of a request can be roughly grouped into two categories:

  • Setup of an AppDomain, in case one doesn't exist yet, to represent the application to which the request is targeted - this is accomplished by the AppManagerAppDomain class.
  • Handling and processing of the request - accomplished by the ISAPIRuntime class.
  Though the two categories are equally important, the first consists of interactions which are supposed to happen without the interference of the developer and which concern mostly the hosting environment of the application, while the second is the most configurable part of the infrastructure, which I will delve into completely in the following article of this series.
  Under another point of view, the first category comprises operations performed only once during the lifecycle of an application, that is, at startup, while the second consists of interactions occurring at each request targeting that specific application.
Setting up an AppDomain
  As seen in the previous article, an ASP.NET application is reserved and wrapped into an entity called Application Domain, aka AppDomain, which turns out to be represented by a class of the ASP.NET architecture, the AppDomain class. When a request to a particular application arrives, an AppDomain has to be setup, if it doesn't exist. This usually happens if the incoming request is the first one targeting that particular application, or if for some reasons the corresponding AppDomain has been shut down, which may happen for several reasons that I will talk about later. Note that only one AppDomain exists for a single ASP.NET application, which is itself mapped one-to-one with an IIS application - either created over a physical/virtual directory. So how does an instance of this class get created?
Figure 1: Call stack generated by the creation of an AppDomain instance as shown by JetBrains dotTrace Profiler
DSC0000.gif
(Click for larger image)  Using Reflector it's possible to realize that the AppDomain class has a private constructor which throws a NotSupportedException exception. Therefore this is obviously not the way to go. The entry point for the instantiation of an AppDomain is in fact the AppManagerAppDomainFactory.Create method. To find it out it's necessary to use a profiler which keeps track of the call stack generated when instantiating the object. Figure 1 displays a screenshot of JetBrains dotTrace Profiler, which shows the call stack generated to instantiate the AppDomain of a web application hosted on IIS. A lot of classes participate in the process, but it's something a developer will probably never have to put his hands on.
  Note that the AppManagerAppDomainFactory class is instantiated only once during and by the CLR initialization process. As its name suggests, it's used as the entry point for creating AppDomains as well as other critical objects.
  Figure 2 shows the same call stack as the previous image, this time captured from the output of the Call Tree view of Microsoft CLR Profiler. This provides some more information about the instantiation of the AppDomain. Actually, the highlighted line shows that there are two instances of the AppDomain class created by the principal thread.
Figure 2: Call stack generated by the creation of an AppDomain instance as shown by the Call Tree view of Microsoft CLR Profiler
DSC0001.gif
(Click for larger image)
  So, how does this additional instance get created, and why? Unluckily it's not an easy question. The call stack shown in the previous images represents the steps followed for instantiating the AppDomain which corresponds to the actual application being executed, so this additional instance looks like a helper object used for some purpose which is difficult to understand - as far as I can guess, it's used to host all the objects which don't belong to a specific application, and therefore are hosted in an isolated AppDomain, like the AppManagerAppDomainFactory class. As for the AppManagerAppDomainFactory class, this helper AppDomain is instantiated only once during and by the CLR initialization, and very very early during this stage, as shown in Figure 3.
Figure 3: Order and allocation method of the additional AppDomain instance
DSC0002.png
  Figure 3 represents a screenshot of Red Gate ANTS Profiler. It shows that the additional AppDomain instance is created very early and during the initialization of the CLR. It is obviously created earlier than the AppManagerAppDomainFactory class, since it is probably its container. The ID of the singleton AppManagerAppDomainFactory instance, in fact, in the profiling session of the previous figure turns out to be 52.
  Another way to see the instantiation process of the two AppDomains - which I present for completeness - is the Allocation Graph view provided by Microsoft CLR Profiler. It creates a graphical flow representation of the classes taking place in the process, as shown in Figure 4.
Figure 4: Instantiation of two AppDomains shown with the Allocation Graph view of Microsoft CLR Profiler
DSC0003.png
  This represents a compressed view which cuts out all the classes between the <root> element - the CLR - and the Thread class. However, it shows clearly the two routes followed when creating the two AppDomain instances.
  Another information about AppDomain instances that can be obtained from the previous figures is that each instance occupies exactly 100 bytes in memory. Not that it matters much, but one might think that an AppDomain is a huge class since it has to host an entire application. Actually, it provides a lot of services but doesn't store a lot of data.
  By now, the helper AppDomain instance has been created, as well as an instance of the AppManagerAppDomainFactory class, whose Create method is the entry point of the call stack shown in figures 1 and 2.
  This method is exposed and called via COM, thus unmanaged code. The AppManagerAppDomainFactory class implements the IAppManagerAppDomainFactory interface, whose structure is represented in Figure 5.
Figure 5: Structure of the IAppManagerAppDomainFactory interface
DSC0004.gif
  The interface is decorated with the ComImport and InterfaceType attribute, which bind the type to an unmanaged interface type. When this method is called it produces the call stack of figures 1 and 2 which in the end triggers the creation of an instance of the AppDomain class, the one used to host the web application targeted by the request.
  Once the AppDomain is up and running all that's left to do - and it's much more than what's been done so far - is processing the request. This is probably the most interesting part of the ASP.NET architecture, but before approaching the fun part I wanted to introduce some core topics.
Summary
  In this article I've introduced some very low level topics about the ASP.NET infrastructure, those concerning the interface between the unmanaged world - represented by the ASP.NET ISAPI extension - and the managed world, represented by the AppDomain hosting the web application. I've presented the mechanisms by which an AppDomain gets instantiated and which classes take part in the process. In the next article I will discuss of managed code only by presenting the HTTP Pipeline, which is in my opinion the most attractive chapter of the ASP.NET architecture, and what actually makes ASP.NET different from all the other web development frameworks out there. I hope you enjoyed reading this article as much as I did writing it. My advice is to fire up some profiler and try out this stuff by yourself, which is the best way to fully understand how it all works.
References

Simone Busoli - ASP.NET Internals &#8211; IIS and the Process Model
Rick Strahl - A low-level Look at the ASP.NET Architecture
Dino Esposito &#8211; Programming Microsoft ASP.NET 2.0 Core Reference
Dino Esposito &#8211; Programming Microsoft ASP.NET 2.0 Applications Advanced Topics

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-99500-1-1.html 上篇帖子: Net中如何操作IIS 下篇帖子: Windows性能查看器:系统的性能信息(I/O,IIS最大连接数,Sql) ,以及解决 asp.net IIS 一二百多用户并发
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表