• 寄宿 和 应用程序域(一)


    概念: 

    寄宿(hosting),准确的说是CLR所支持的寄宿,是程序A(宿主,可以是托管或非托管代码)中调用第三方代码(寄宿代码)B。

      这个调用过程与我们直接引用第三方代码不同之处在于,通过CLR应用程序域对第三方代码进行了隔离。

      也就是说第三方代码B运行于CLR创建的应用程序域内。

      其优点就是对第三方代码很好的隔离作用。防止第三方代码破坏程序本身的代码或数据。

    应用程序域(Appdomain),简言之是CLR创建的一个逻辑隔离区,这个隔离区内运行的代码不能访问其他应用程序域中的代码。

      CLR初始化后会创建一个默认 应用程序域,在我们不人为创建新的appdomain的前提下,我们所写的代码就会在这个默认appdomain中运行。这个默认appdomain 直到进程终止才会被销毁。

    注:因为寄宿代码是依赖于CLR运行,所以寄宿代码(第三方代码)必须是CLR可以支持的代码,直白些说,必须为exe或者dll

    对于寄宿,大概有以下情况: 

    1、如果宿主是非托管代码,宿主程序进程会根据寄宿代码的版本加载对应版本的CLR,CLR会在默认的应用程序域内执行寄宿代码。

      非托管代码的寄宿调用大致如下:

      宿主通过调用 C:WindowsSystem32MSCorEE.dll中CLRCreateInstance函数返回ICLRMetaHost接口

      调用ICLRMetaHost接口的GetRuntime函数返回一个指向非托管接口ICLRRuntimeInfo的指针

      通过这个指针调用GetInterface方法会的ICLRRuntimeHost接口。

        通过ICLRRuntimeHost接口可以做如下控制:

        设置宿主管理器,宿主可以参与CLR的内存分配,线程调度,垃圾回收以及特定操作的超时通知等。

        获取CLR管理器。告诉CLR阻止使用的类型及成员。以及特定事件发生时素质应调用的方法。

        初始化启动CLR。

        加载程序集,并执行其中代码。

        停止CLR。

    2、如果宿主为托管代码,且宿主运行CLR版本与寄宿代码CLR版本不同。

      假设宿主运行于.net framework 4.0,寄宿代码运行于.net framework 2.0,这时 宿主会在进程中加载.net framework 2.0,并以此版本CLR运行寄宿代码。  

      当CLR加载到进程后,就永远不能被卸载,直到该进程结束为止。意味着,上面同时加载两种版本CLR后,即使寄宿代码 应用程序卸载,内存被回收,CLR 2.0依然存在,直到进程终止。

      一个进程中同时支持两种CLR版本是在.net framework 4.0引进的。之前的版本只能支持一种CLR。

    3、如果寄宿代码为托管代码,且宿主与寄宿代码CLR版本相同。

      则宿主以当前CLR创建应用程序域 运行寄宿代码。

    Appdomain提供功能如下:

    1、  隔离,appdomain间代码不能直接访问。

      为了提供良好的隔离性,每个appdomain会单独加载程序集,即使两个appdomain用了同一个程序集,这个程序集也会被分别加载进两个appdomain中,这当然会造成资源的浪费,但其优点是,不会发生当某个appdomain被卸载时,会对其他appdomain产生影响。

      对于常用的程序集,则会有多个appdomain共享,如MSCorLib.dll。对于此种程序集,CLR会维护一个特殊的Loader堆,给Loader堆中所有的类型、对象、代码会被进程中所有的appdomain共享。其缺点是,这个方式加载的程序集永远不能被卸载,直到进程结束。

    2、Appdomain可以被卸载

      CLR提供了卸载appdomain的能力。卸载一个appdomain,其中包含的所有程序集都会被卸载。

    3、appdomain可以单独权限设置 

      创建appdomain可以对其配置权限信息。这可以限制寄宿代码无权限对宿主进行破坏。

    4、appdomain可以单独配置

      可对appdomain中程序集的加载方式、搜索路径、版本绑定及加载器优化等进行相关配置。

    寄宿 AppDomain用途:

    例子:假如我们需要开发一个web服务器程序主要用于运行asp.net。
    我们已经开发了大部分功能,但是对于动态页面服务器代码的解析并不擅长。
    不过这正是CLR的所擅长的,所以对于静态资源的请求我们可以直接返回。对于动态页面的请求。我们可以通过CLR的寄宿功能的执行动态页面代码,而后返回html。


    实际上,aps.net正是这么做的。

    当客户端首次请求一个web应用程序时。
    asp.net会加载CLR,并告诉CLR为此web应用程序创建一个AppDomain,该AppDomain会加载与请求相关的程序集,创建类型实例,调用执行,返回客户端的请求。
    当该web应用的第二第三个请求到来时,会在此已有的AppDomain中执行。
    当有新的web应用请求时,则会创建新的AppDomain处理请求。

    此时,每一个web应用程序对应一个AppDomain,每一个web应用程序异常或是停止,都不会影响其他web应用程序的正常运行。

    使用场景:

    以下场景或许我们可以用到 寄宿 AppDomain

    1、非托管代码可以利用寄宿而运行已有的第三方代码。
    2、不同安全级别的程序集,可以放在不同权限的AppDomain中运行。
    3、当某些代码不稳定 或 资源消耗较大 等情况时,可以放在一个单独的AppDomain中运行。出现问题,则卸载该AppDomain
    4、由于进程的创建较慢 并有较大的资源消耗,或可以在AppDomain运行代码 代替以进程运行。
    5、由于.net framework 兼容性的提升,可以在程序中运行两个不同版本的程序集

    对于真正掌握这个技术后,或许可以使用的场景成千上万,只是局限于自己的想象力。

  • 相关阅读:
    The control collection cannot be modified during DataBind, Init, Load, PreRender or Unload phases.
    线程安全思考
    微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异
    从构建分布式秒杀系统聊聊分布式锁
    基于Redis实现延时队列服务
    Redis分布式锁的正确实现方式
    探究 Redis 4 的 stream 类型
    JAVA 异常分类与理解
    缓存穿透,缓存击穿,缓存雪崩解决方案分析
    分布式之数据库和缓存双写一致性方案解析(一)
  • 原文地址:https://www.cnblogs.com/qingzhuo/p/3944498.html
Copyright © 2020-2023  润新知