Adhesive框架系列文章--公共模块实现

本文涉及的产品
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
日志服务 SLS,月写入数据量 50GB 1个月
简介: 公共模块是所有框架内部组件依赖的项目,其中包括一些基础实现和小工具。 首先是一个Bootstrapper的理念: 1、在需要的时候,我们可以把实现和接口进行分离,实现使用依赖注入(不一定要项目引用,只需要文件夹下有实现的DLL)。

公共模块是所有框架内部组件依赖的项目,其中包括一些基础实现和小工具。

首先是一个Bootstrapper的理念:

1、在需要的时候,我们可以把实现和接口进行分离,实现使用依赖注入(不一定要项目引用,只需要文件夹下有实现的DLL)。那么,我们就需要在网站应用程序或是其它应用程序启动的时候,把这些实现注入进来。这里需要提一点的是,正因为我们把实现和接口进行分离,使得我们可以让两个组件进行相互的引用,比如配置服务的实现可以调用信息中心的接口来记录日志,而信息中心的实现可以调用配置服务的接口来存储配置。

2、然后,我们需要针对每一个组件进行一些初始化工作,比如进行数据初始化,这步工作需要在1之后。

当然,还可以有3、4、5,这些工作我们称为BootstrapperTask,在应用程序启动的时候,只要程序集中有BootstrapperTask,Bootstrapper就会自动找到这些Task并且按照Order分组并行调用,在应用程序结束的时候,Bootstrapper也会依次调用所有的Dispose来清理。

因此,我们要求类似这样,调用框架的启动和结束方法:

public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AdhesiveFramework.Start();
        }

        protected void Application_End()
        {
            AdhesiveFramework.End();
        }
    }

 

然后是一些本地的组件,之所以有本地组件,是因为在某些情况下我们不能使用完整的非本地组件:

1、比如配置服务本身作为一个最底层的服务,如果使用信息中心模块记录错误日志的话,就产生了循环依赖的问题,因为信息中心模块在初始化的时候需要用到配置服务,如果配置服务在启动的时候发生异常记录一条日志,那么此时由于配置服务本身没启动,信息中心模块不可能启动成功,此时可以使用本地的日志服务。

2、有的时候我们需要进行测试或调试,不希望使用正式的基于数据库的配置服务(需要连接远程的配置服务服务端,如果需要修改数据的话需要到后台修改),而是希望使用简单的本地配置文件,那么可以使用本地的配置服务。

这些组件包括:

1、LocalConfigService:通过XML序列化把实体保存到config文件中,实现文件依赖方式的缓存,并且为了解决某些类型不能序列化的问题实现了SerializableDictionary以及SerializableTimeSpan等,使用方式如下:

        var config = LocalConfigService.GetConfig(new AdhesiveConfig
            {
                ApplicationName = "",
                ConfigServiceAddress = "192.168.129.143:18989/ConfigService",
                WcfConfigServiceAddress = "192.168.129.143:18888/WcfConfigService",
                LocalLoggingServiceLevel = LogLevel.Debug,
                StateServiceDefaultReportStateIntervalMilliSeconds = 1000 * 10,
            });

 

2、LocalLoggingService:以一小时为一个文件记录本地日志;并且对于DEBUG方式的编译,为了方便查看日志自动向控制台输出日志(使用不同颜色区分不同等级);另外还为日志附加了调用方法名、时间等信息,使用方式:

LocalLoggingService.Error("AdhesiveFramework.LocalServiceLocator 不能解析 '{0}',异常信息:{1}", typeof(T).FullName, ex.ToString());

在1中我们看到这是Adhesive框架最基础的配置,这是通过本地配置服务进行的,其中有一个就是本地日志服务的级别,如果配置了Warning,那么只有Warning和Error的日志才会记录到本地日志中。一般本地日志服务仅仅用于框架初始化时部分代码的日志,之后的日志记录都应该通过集中化的信息中心模块。

记录的日志差不多这样:

[Info] @17:48:34_1674 #8 Adhesive.Common.AdhesiveFramework Start() - AdhesiveFramework开始启动...
[Debug] @17:48:34_6604 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.AppInfoCenter.Imp.RegisterServiceTask' (注册日志、异常、性能、状态服务)
[Debug] @17:48:34_6674 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.Config.Imp.RegisterServiceTask' ()
[Debug] @17:48:34_6804 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.DistributedService.RegisterServiceTask' (注册Wcf定位服务)
[Debug] @17:48:34_7014 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.MemoryQueue.Imp.RegisterServiceTask' ()
[Debug] @17:48:34_7074 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.Mongodb.Imp.RegisterServiceTask' ()
[Debug] @17:48:34_7144 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.Mongodb.Server.Imp.RegisterServiceTask' ()
[Debug] @17:48:34_7214 #8 Adhesive.Common.Bootstrapper+<>c__DisplayClassc <Execute>b__8() - AdhesiveFramework.Bootstrapper 开始执行 'Adhesive.Mongodb.Server.Imp.InitServerTask' (初始化Mongodb服务端、进行第一次数据库元数据维护)

 

3、LocalServiceLocator:通过Unity提供接口到实现的解析。

 

除了这些之外,公共组件还放一些公共类库和扩展方法:

1、公共类库:比如序列化、加密等等。

2、公共扩展方法:比如Unity注册和解析的扩展方法、类型的扩展、枚举扩展方法、Json的扩展方法等等。

 

在开发的过程中遇到几个很诡异的问题,在此希望分享一下。

1、有一次在调试网站项目的时候发现,同样一个静态字段居然在框架启动的时候和页面请求的时候是两个不同对象,也就是对象的HashCode不一致,我们戏称“平行宇宙”问题。后来发现,我们为了解决没有引用的程序集中的BootstrapperTask也能执行,动态加载所有bin目录下的程序集,这就导致在启动的时候加载的程序集所在的应用程序域和网站的应用程序域不同。解决办法是对于网站使用:

BuildManager.GetReferencedAssemblies().Cast<Assembly>().Where(assembly => !assembly.GlobalAssemblyCache).ToList()

来获得所有的程序集。

 

2、在写配置服务的时候发现配置服务的实现死活不能解析成功,但查看Unity发现确实已经注册进去了,后来发现如果接口和实现位于同一个程序集中,Unity居然不能成功解析,把接口和实现分离到两个不同的程序集之后问题解决。

作者: lovecindywang
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
相关文章
|
消息中间件 Java 关系型数据库
后端接口性能优化分析
后端接口性能优化分析
479 0
|
移动开发 前端开发 JavaScript
js实现图片压缩上传
最近在研究H5前端图片处理相关技术,方向有图片压缩、裁切、旋转、模糊等。
420 0
|
2月前
|
人工智能 数据处理
Qoder 全新「上下文压缩」功能正式上线,省 Credits !
Qoder 全新「上下文压缩」功能正式上线,高效管理会话上下文,节省开发成本,同时保持高效协作!
|
2月前
|
安全 Linux Shell
Linux系统提权方式全面总结:从基础到高级攻防技术
本文全面总结Linux系统提权技术,涵盖权限体系、配置错误、漏洞利用、密码攻击等方法,帮助安全研究人员掌握攻防技术,提升系统防护能力。
235 1
|
2月前
|
前端开发 Java 开发者
MVC 架构模式技术详解与实践
本文档旨在全面解析软件工程中经典且至关重要的 MVC(Model-View-Controller) 架构模式。内容将深入探讨 MVC 的核心思想、三大组件的职责与交互关系、其优势与劣势,并重点分析其在现代 Web 开发中的具体实现,特别是以 Spring MVC 框架为例,详解其请求处理流程、核心组件及基本开发实践。通过本文档,读者将能够深刻理解 MVC 的设计哲学,并掌握基于该模式进行 Web 应用开发的能力。
389 1
|
存储 监控 安全
企业如何应对网络攻击的威胁
企业如何应对网络攻击的威胁【10月更文挑战第10天】
357 3
|
JavaScript
Selenium--WebDriverWait--你知道显示等待?(结合源码让你更加得心应手)
Selenium--WebDriverWait--你知道显示等待?(结合源码让你更加得心应手)
312 0
|
存储 数据采集 机器学习/深度学习
大数据基础:收集、处理与分析
【5月更文挑战第30天】本文探讨了大数据的基本概念、关键技术及应用案例。大数据是海量、多源、快速处理的数据集合,涉及数据采集、存储、处理和分析。关键技术包括使用Flume进行数据采集、Hadoop HDFS和NoSQL数据库存储数据、MapReduce和Spark进行批处理、以及Python的pandas和scikit-learn进行数据分析。应用案例涵盖了金融风控、医疗健康和智能交通等领域,展示大数据在风险评估、疾病诊断和交通管理等方面的潜力。随着技术发展,大数据将在更多领域发挥作用。
492 3
|
存储 安全 关系型数据库
技术人必修课:利用金字塔原理高效思考与表达
作者写这篇文章的目的就是希望能够帮助更多同学了解金字塔原理并合理应用,不只是写作,更是要着眼于思考和表达。本文将围绕认识金字塔结构、表达的逻辑、思考的逻辑、解决问题的框架、演示的逻辑这几个方面带领大家深入学习金字塔原理。