ABP VNext从单体切换到微服务

发布时间:2021-12-08 07:32:10

注:此处的微服务只考虑服务部分,不考虑内外层网关、认证等。


ABP VNext从单体切换到微服务,提供了相当大的便利性,对于各模块内部不要做任何调整,仅需要调整承载体即可。



ABP can help you in that point by offerring a?microservice-compatible, strict module architecture?where your module is splitted into multiple layers/projects and developed in its own VS solution completely isolated and independent from other modules. Such a developed module is a natural microservice yet it can be easily plugged-in a monolithic application.



分层架构

    ABP VNext自身提供的分层方式如下图,核心部分是Application、Domain与EntityFrameworkCore层,至于HttpApi.Client与HttpApi都是属于将应用去承载到其他系统之上的。



    Controller层在ABP VNext中被削弱了,VNext提供了将Application提供动态Controller,所以可能*惯了将部分逻辑写在控制器中的会有些唐突,但理解就行。



规划层次结构

    新建空文件夹,取名随意(本次取名GravelService),用于存放整体项目。

    在上一步的空文件夹内新建空白解决方案,可以用VS去生成或是按照dotnet的命令生成。



    *惯*凑誂BP VNext给定的微服务Demo中的格式创建三个文件夹,思路清晰。当然提供的微服务Demo还有更多文件夹,但是这次只关注这三个。



增加三个模块

    设计三个限界上下文并绘制上下文映射。依照常见的订单、产品与客户划分成三个限界上下文。并规划好订单作为下游依赖产品与客户作为的上游。



    从官网直接下载三个模块,或是按照命令行去生成(前提是已经安装了ABP CLI),无论哪种方式,确保准备好就行,依照模块化思想,将其存到modules文件夹下。



    如本次准备了三个模块Product,Order,Customer,依照实际需要,可以去精简一下内部文件,此处各模块内部我只留着src和test文件夹。



    对于customer模块的src内部,具体生成的文件夹如下,对于其中的HttpApi、HttpApi.Client及MongoDB,我采取了剔除,无需这部分(在稍后的承载体中有同等功能)。



清理之后变得简简单单的。



对于test内部,同样采取剔除无需的HttpApi.CLient、MongoDB文件夹(注:此处的无需只是针对我而言,如果有需要还是留着吧)。



清理之后,层次划分变得简简单单的。



    改造下各模块内给定的Sample案例,改造成各模块命名开头,方便加以区分。以Customer模块为例,将自带的Sample案例更名成Customer,仅作该项改动。



模拟服务调用

    对于Order与Product模块内增加一个下游访问上游服务的链路,方便验证从单体跨越到微服务,底层服务的无需任何改动。对于下游访问上游服务的调用形式,了解到的有两种方式。


当前上下文的应用层直接依赖其他上下文的应用服务;

当前上下文设定出防腐层(在限界上下文间增加一层隔离,方便保证依赖限界上下文存在变动时只需更改隔离层),在防腐层的实现中去依赖或远程调用其他上下文的应用服务;


    我个人倾向于增加防腐层,虽然在VNext中并无相关说法。具体使用时,在领域层或应用层增加防腐层接口,及在EF Core层给与防腐层实现,此时的EF Core层,更应该更名为基础设施层,而不单单是作为资源库的形式。



    在Order中Domain层增加ServiceClients文件夹用于存放防腐层接口,而在EntityFrameworkCore层增加ServiceClients文件夹用于存放防腐层实现。


在防腐层接口中增加IProductServiceClient。


public interface IProductServiceClient : ITransientDependency
{
? ? Task GetProductId();
}

在防腐层实现中增加ProductServiceClient。

在Order中的EntityFrameworkCore层引用Product模块内的Application.Contracts层。

依赖ProductAppService并完成调用。


public class ProductServiceClient : IProductServiceClient
{
? ? private readonly IProductAppService _productAppService;
? ? public ProductServiceClient(IProductAppService productAppService)
? ? {
? ? ? ? _productAppService = productAppService;
? ? }
? ? public async Task GetProductId()
? ? {
? ? ? ? var productDto = await _productAppService.GetAsync();
? ? ? ? return productDto.Value;
? ? }
}

在OrderAppService中依赖防腐层接口,并完成调用。


public class OrderAppService : OrderManagementAppService, IOrderAppService
{
? ? private readonly IProductServiceClient _productServiceClient;
? ? public OrderAppService(IProductServiceClient productServiceClient)
? ? {
? ? ? ? _productServiceClient = productServiceClient;
? ? }
? ? public async Task GetAsync()
? ? {
? ? ? ? var productId = await _productServiceClient.GetProductId();
? ? ? ? ...
? ? }
}

    这样一来,在防腐层实现中便可以使用到Product上下文的应用服务了,对于这个应用服务的请求是当前进程内的还是进程间的,由具体的承载方式而决定。



大单体承载

将依照如下图,将三个模块承载到GravelService.Host上。



    新建一个GravelService.Host的项目,采用WebApi类型即可。存放到microservices文件夹下,这样方便理解整个层级划分。



    其次依赖一些基本的Nuget包,诸如ABP自身的及方便展示Api的Swagger。本次不考虑实体的创建,也就不考虑EF Core包的依赖了。


Volo.Abp

Volo.Abp.AspNetCore.MultiTenancy

Volo.Abp.AspNetCore.Mvc

Volo.Abp.Autofac

Swashbuckle.AspNetCore


    引用各模块内的Application层及EntityFrameworkCore层。模仿着给定的微服务Demo,完成一波CV操作。增加一个类出来承担着服务与中间件的配置。



    在其中依赖引用的各Application层及EntityFrameworkCore层中的Module,这样一来模块依赖就搞定了。


[DependsOn(
? ? typeof(AbpAutofacModule),
? ? typeof(AbpAspNetCoreMvcModule),
? ? typeof(AbpAspNetCoreMultiTenancyModule),
? ? typeof(CustomerManagementApplicationModule),
? ? typeof(CustomerManagementEntityFrameworkCoreModule),
? ? typeof(OrderManagementApplicationModule),
? ? typeof(OrderManagementEntityFrameworkCoreModule),
? ? typeof(ProductManagementApplicationModule),
? ? typeof(ProductManagementEntityFrameworkCoreModule)
? ?)]
public class GravelServiceHostModule : AbpModule
{
...
}

    增加服务配置,将各模块中的应用服务动态转换成Api控制器。


Configure(options =>
{
? ? options.ConventionalControllers
? ? ? ? .Create(typeof(CustomerManagementApplicationModule).Assembly,
opts =>
? ? ? ? {
? ? ? ? ? ? opts.RootPath = "CustomerManagement";
? ? ? ? })
? ? ? ? .Create(typeof(OrderManagementApplicationModule).Assembly,
opts =>
? ? ? ? {
? ? ? ? ? ? opts.RootPath = "OrderManagement";
? ? ? ? })
? ? ? ? .Create(typeof(ProductManagementApplicationModule).Assembly,
opts =>
? ? ? ? {
? ? ? ? ? ? opts.RootPath = "ProductManagement";
? ? ? ? });
});

    然后,启动即可,所有模块中的接口都承载到了该承载体中。



    通过访问Order的api/OrderManagement/order接口获得返回的9527,也就验证了,防腐层内去访问Product上下文的应用服务。



此时是在同一进程内,使用到的是ProductAppService的具体实现,断点查看也可看出当前进程内的请求,依赖其他上下文服务的应用服务为ApplicationServiceProxy。



多服务承载

依照如下图开始切换承载模式,只更改承载体,将一个大的承载体切分成各上下文独自承载体。



    新建三个和GravelService.Host同等的WebApi项目。在GravelService.Host上裁剪即可,每个独立的承载体只拥有自身的上下文。



    依据上下文映射关系,对处于下游的Order承载体增加对上游Product的依赖,在Order承载体中增加对Product模块中Application.Contracts层的依赖。并在服务配置中完成依赖(第7行)。


[DependsOn(
? ? typeof(AbpAutofacModule),
? ? typeof(AbpAspNetCoreMvcModule),
? ? typeof(AbpAspNetCoreMultiTenancyModule),
? ? typeof(OrderManagementApplicationModule),
? ? typeof(OrderManagementEntityFrameworkCoreModule),
? ? typeof(ProductManagementApplicationContractsModule)
? ? )]
public class OrderServiceHostModule : AbpModule
{
...
}

    配置远程服务代理,在服务配置中设置从Order承载体到Product承载体的远程服务请求。在Order承载体中增加Volo.Abp.Http.Client包并在服务配置中完成依赖。


[DependsOn(
? ? ...
? ? typeof(AbpHttpClientModule),
...
? ? )]
public class OrderServiceHostModule : AbpModule
{
? ? public override void ConfigureServices(ServiceConfigurationContext context)
? ? {
? ? ? ? var configuration = context.Services.GetConfiguration();
...? ?
context.Services.AddHttpClientProxies( typeof(ProductManagementApplicationContractsModule).Assembly);
? ? ? ? ...
? ? }
}

    在配置源appsettings文件中加入对Product承载体的远程调用地址


?{
"RemoteServices": {
? "Default": {
? ? "BaseUrl": "http://localhost:57687"
? }
}

    更改项目配置,启动多个文件,一并启动三个独立承载体,再次调用Order中的Get请求,同样获得了从Product上下文的应用服务中的数据



    这次采用的不同进程间的承载方式,通过防腐层,然后经ABP提供的Http代理服务调用Product承载体,可以断点查看当前在防腐层中的AppService类型,已经不再是直接使用ProductAppService了。



真香

从大单体承载切换多服务承载,Modules部分不需要做任何更改,着实方便。至于内部的远程调用,本身ABP VNext还存在一些问题像类似集合的Get请求在3.1的版本中才做了修复,但是这丝毫不影响这一巨人的前行。

相关文档

  • 用美图秀秀把图片背景设置成白色
  • python 数据挖掘工具_12款最好用的数据挖掘工具
  • 植物抒情作文五年级优秀范文
  • 给身边的人送上秋天的祝福
  • 销售激励人的话语
  • 有关励志的800字演讲稿3篇
  • 2010第三季度安全文明工作总结
  • 高中学籍可以重办吗可以有两个学籍吗
  • 桥接模式使手机和电脑,虚拟机在同一个局域网下
  • 设计及监理合同范本
  • 萌萌的漫画图片大全可爱
  • 澳洲高中留学的升学途径有哪些
  • 毕业生暑期实习自我鉴定
  • 有关中秋晚会主持词
  • 2017高雅微信名女生简单气质
  • 编制记账凭证的步骤
  • 选择卓越读后感
  • 青春演讲稿400字左右
  • 前端面试题收藏(1)
  • 手机掉水里了没声音了怎么办
  • 鸡枞几月份出
  • 苹果第三方app可信吗
  • 文件上传黑名单和白名单校验
  • 读《刑场上的婚礼》有感
  • 同学之间主题黑板报素材
  • 百融金服榕树数据运算,百融金服榕树引入标志符概念
  • 汨罗江江水为什么会倒流 你知道吗?
  • 我的小白兔茜茜作文
  • 网页中这 10 种字体的运用方式,不会让人觉得 Low
  • 拉丁舞教学中形体训练的重要性
  • 猜你喜欢

  • 医生您好,我有个问题想咨询下.docx
  • 复旦大学2011年在职人员攻读环境工程领域工程硕士专业学位研究生招生信息
  • 数学人教版五年级下册《探索图形》课后练*
  • 2014-2015学年下学期 外研版七年级英语下册 一般将来时知识讲解+练*题(无答案)
  • 标准化主副井及井上下1
  • 四川省乐山市晶晶涂料厂成都经营部企业信用报告-天眼查
  • 巴彦县增收植物医院企业信用报告-天眼查
  • 实用非谓语动词语法专题讲解与训练课件 (1) - 副本
  • 演讲比赛主持人串词3篇
  • 重庆景晖国际商务顾问有限公司企业信用报告-天眼查
  • 水利工程新定额与工程量清单计价规范应用手册
  • 2012届《教学导航》高三生物复*课件:必修3第27讲_种群特征、种群数量的变化
  • 连拱隧道施工方法介绍
  • 服装立体裁剪教案部分
  • 简历模板2(有工作经验者)【可编辑版】
  • 市政给排水管道施工技术要点分析
  • 怎么把照片弄清楚点
  • 农业银行行长个人述职报告
  • 【最新文档】国家公务员法学*心得(一)-精选word文档 (2页)
  • 哈尔滨市海龙二手车经纪有限公司企业信用报告-天眼查
  • 迷你弹力带在雾霾天气室内体育课运用
  • 今天我又参加考试_初中初二作文800字
  • 带着责任上路励志日志
  • 2014届名师导学高考物理第一轮复*课件:第三章 牛顿运动定律 人教版
  • 2012年讲解员知识问答复*题
  • 武汉市2001年市售电热蚊香及电热液体蚊香的质量情况
  • 激发人奋斗的语句
  • 社会工作者《初级社会工作综合能力》复*题集(第628篇)
  • 四川省2017年监理工程师执业资格:工程师的口头指示考试试卷
  • 古诗晚登三山还望京邑翻译赏析
  • Android 仿微信通讯录列表侧边栏(2)
  • 女友想要买房才结婚怎么办
  • 录用条件说明书
  • 数学教学中的理性与感性——优化数学课堂教学的些许策略
  • 肺部继发性真菌感染相关因素分析
  • 6S大气校正模型源码
  • 食用葡萄的注意事项有哪些
  • 2018-2019学年苏教版选修5专题3 常见的烃单元测试题
  • 2020考研-王道数据结构-树和二叉树-二叉树的遍历
  • 上海佳昊投资管理有限公司企业信用报告-天眼查
  • 存储器集成电路项目立项申请书
  • 毕业设计任务书开题报告等表格范例(1)
  • 电脑版