Silky微服务框架之模块( 二 )

ShutdownModules()方法,实现对各个模块资源的释放;
public async Task ShutdownModules(){foreach (var module in _moduleContainer.Modules){await module.Instance.Shutdown(new ApplicationContext(_serviceProvider, _moduleContainer));}}模块的类型在Silky框架中,我将模块的类型划分为如下几种类型:

  1. 模块的定义SilkyModule: SilkyModule是一个抽象的模块,用于定义模块的概念;其他业务模块必须要派生自该类;
  2. 业务模块: 直接派生自SilkyModule类的非抽象类,Silky框架中,几乎所有的包在通过定义业务模块后从而实现模块化编程的,很多核心的包都是业务模块,如:SilkyModuleConsulModuleDotNettyModule等等模块都属于业务模块;
  3. Http类型的业务模块:该类型的业务模块派生自HttpSilkyModule,相比一般的业务模块,该类型的模块增加了Configure(IApplicationBuilder application)方法,该类型的模块一般用于通过web主机构建的微服务应用或是网关中,可以在Configure()方法中通过IApplicationBuilder引用http中间件,在silky框架中,诸如: CorsModuleIdentityModuleMiniProfilerModule等均是该类型的模块; 需要特别注意的是,需要http业务模块配置的中间件起效果的话 , 不要忘记需要在Startup类中的Configure进行如下配置:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.ConfigureSilkyRequestPipeline();}
  1. 启动模块:该类型的模块派生自StartUpModule的非抽象类;在模块加载过程中,通过指定启动模块,从而得知模块的依赖关系,模块加载器会通过模块的依赖对模块进行排序,从而影响应用在启动时各个模块的执行的先后顺序;Silky模块预定义了多个启动模块,可以用于不同silky主机的构成:A) DefaultGeneralHostModule 用于构建普通的业务主机,一般用于托管只提供RPC服务的微服务应用;B) WebSocketHostModule 用于构建提供WebSocket服务能力的业务主机;C) DefaultWebHostModule 用于构建能够提供Http服务的业务主机,对外可以提供http服务,也可以用于内部rpc通信;D) DefaultGatewayHostModule 用于构建网关微服务,一般为微服务集群暴露对外部的http访问端口,通过路由机制,将http请求转发到具体某个服务条目,对内通过RPC进行通信;
除此之外,开发者也可以自己的需求,为自己定义需要的启动模块,在构建微服务主机时,指定相应的启动模块 。
模块的加载Silky所有的模块是在什么时候以及如何进行加载和排序的呢?
在之前的构建服务引擎的一章中,我们知道在AddSilkyServices<T>()方法中,我们通过泛型T来指定应用程序的启用模块StartUpModule类型 。并构建了模块加载器对象ModuleLoader,并且将模块加载器对象作为服务引擎的LoadModules()方法参数:
public static IEngine AddSilkyServices<T>(this IServiceCollection services, IConfiguration configuration,IHostEnvironment hostEnvironment) where T : StartUpModule{var moduleLoader = new ModuleLoader();engine.LoadModules<T>(services, moduleLoader);}在服务引擎SilkyEngine实现类中,除了实现IEngine接口之外,还需要实现了IModuleContainer接口,IModuleContainer只定义了一个只读属性Modules,要求通过该属性获取所有的模块;在服务引擎中,我们通过模块加载器对象moduleLoader.LoadModules()方法实现对模块的加载与解析,并对属性Modules进行赋值;
internal sealed class SilkyEngine : IEngine, IModuleContainer{// 其他代码略...public void LoadModules<T>(IServiceCollection services, IModuleLoader moduleLoader)where T : StartUpModule{Modules = moduleLoader.LoadModules(services, typeof(T));}// 实现IModuleContainer定义的属性public IReadOnlyList<ISilkyModuleDescriptor> Modules { get; private set; }}模块加载器ModuleLoader要求传递两个参数,一个是IServiceCollection的对象services , 一个是启动模块StartupModule的的类型typeof(T);下面我们来描述模块加载的过程:
  1. 通过SilkyModuleHelper.FindAllModuleTypes(startupModuleType) 查找到启动模块StartupModule类型依赖的所有模块类型;
  2. 通过反射创建模块的实例,并通过IServiceCollection注册单例的模块实例,并创建模块描述符SilkyModuleDescriptor;
  3. 根据模块的依赖关系对模块进行排序;

    推荐阅读