.NetCore 结合微服务项目设计总结下实践心得

以下内容全是在项目中的体验,个人理解心得

起源

2017年7月开始接触.NetCore,当时还是因为Idr4的原因,之前的项目都是用的Idr3做,后面接触到Idr4后,决定以后所有项目都使用.NetCore来搭建项目架构,随后我开始研究Idr4的相关使用,后面又接触到了Ocelot、Cap、Consul、Skywalking、AspectCore、MediatR等优秀库,从此我决定搭建微服务项目,从此就走上了一条不归路,接下来我阐述下我在在架构思想上的心得。

项目介绍

项目是一个学生体检体检项目,整体分为了认证中心、用户服务、体检服务三个部分

我建立了三个服务,这里各自的项目人员开发自己的项目功能模块,分布开发,多个项目组同时协作,用户服务,体检服务分别建立2个数据库,当然这里业务会存在服务调用服务的情况,前面的文章我也有说过,如果只是查询,其实在UI端访问2个不同服务接口就行了,但是如果存在内部业务需要调用另外一个服务的情况,这里保证数据库最终数据一致就行了,采用了消息队列RabbitMQ来处理,接口调用接口会出现的网络原因我也结合了Polly重试来处理,并记录操作日志,操作日志采用面向切面是来实现(AOP),结合Exceptionless保存日志信息,记录参数详细信息

接下来就看是搭建项目结构基础了,大体上我想的是下面这个结构,把所有的配置单独出来,Domain层添加领域实体,这里参见了eshopscontainer

领域层

大体结构已经建立好了后,根据业务添加好领域模型,确定了领取模型中领域职责事件,这是我对DDD的个人理解,这里涉及到 聚合根(AggregateRoot)、值对象(ValueObject)等一些东西,为什么要要说聚合根以及值对象,这可能涉及到一个认知改变,就是把EFCore模型中建立的关系型思想转化为领域对象的认知思维,在以前的项目中记得经常有一个Model层一样的东东,经常被用来承载数据,穿梭在各个结构层之间,这里要说的Model在思想上可以认为是一个领域或者子领域,我个人是这么理解 领域对象模型:定义或描述一个领域对象自身属性、附属关系(边界)及领域行为的对象。

聚合根其实个人觉得跟EF中的上下文对象DbContext类似,打个比方:在DbContext中有很多 DbSet<T> 的对象,其实也可认为这个就是 DbContext下的边界,而DbContext本生看作一个聚合根,所有的访问都是DbContext下的 DbSet<T>实现对不同实体操作,定义这个边界就是为了不让从外部访问它,需要通过在聚合根中的定义的边界访问,在实际的使用的过程中根据业务定义,这里我在代码中为了不让这个关系呈现在我的数据中,所以基本上我的每个领域模型我都是聚合根,这样是我不想 因为聚合根中的边界的依赖关系产生生成数据库关联关系成强主外键关系,所以在这个项目中我 聚合根及值对象基本就被忽略了,从而我更加关注领域模型本生及领域模型中行为。

基础层

基础层我封装了Exceptionless日志处理,使用EFCore生产数据库的Mapper配置及业务实现处理,以及上下问对象处理,这里需要说的领域中的界限上下文,这里我一个领域所以我只有一个上下文,这个根据业务划分存在多个领域上下文对象,没有划分核心领域,子领域,一般一个领域(或子领域)对应有一个界限上下文,在服务上我已经分开了用户服务于体检服务,实际每个服务都是一个子领域,在结构上已经区分开了。在基础层做了对IRepositry的仓储以及MediatR的扩展从而实现消费领域事件。

应用层

应用层相对比较容易了,采用MediatR实现了命令式处理,在这中间我使用AOP封装了操作日志记录操作信息,查询使用了Dapper实现了读写分离查询,在MySql上做了一个主从,这里特别害怕数据同步延迟,所以这里的查询我只用了那些只单单是查询的方法,如果跟业务相关的查询还是使用了EFCore,比如要根据查询某一条结果然后某一条数据,使用MediatR 中的 INotification 去消费领域事件,另外我还在引用层添加了AggregateServices聚合服务相关处理,关于文件存储这块使用了AliyunOSS,目前关于缓存使用Redis做简单的权限信息缓存。

WebAPI

采用Autofac处理了接管了.NetCore的 DI,封装了相关注入方式简化了代码,另外对验证做了扩展操作,采用Swagger构建API接口说明文档,处理了WebAPI的版本信息

分布式目标

做了上面的架构后以实现下面的部署结构

以上是这段时间使用的技术构建的一套框架结构,以及在实际使用过程中的心得,以及思想上的认知

猜你喜欢

转载自www.cnblogs.com/liyouming/p/9895461.html