ABP VNext从单体切换到微服务
注:此处的微服务只考虑服务部分,不考虑内外层网关、认证等。
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的命令生成。
习惯上按照ABP 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<int> 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<int> 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<OrderDto> 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<AbpAspNetCoreMvcOptions>(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的版本中才做了修复,但是这丝毫不影响这一巨人的前行。
ABP VNext从单体切换到微服务相关推荐
- 敏捷水手——单体法到微服务之旅
\ 本文要点 \\ 探究持续四年多的渐进式改革是什么样子:\\t 探索为什么在变革软件和组织设计时要遵循康威定律:\\t 看看如何将领导力应用到不同的团队.领域和层级:\\t 举例说明变革管理如何依赖 ...
- java调用webservice_笃学私教:Java开发网站架构演变过程-从单体应用到微服务架构详解...
原标题:笃学私教:Java开发网站架构演变过程-从单体应用到微服务架构详解 Java开发网站架构演变过程,到目前为止,大致分为5个阶段,分别为单体架构.集群架构.分布式架构.SOA架构和微服务架构.下 ...
- 从单体结构到微服务架构的转变,微服务入门
单体架构 VS 微服务架构 1.1从单体架构说起 一个工程对应一个归档包(war),这个war包 包含了该工程的所有功 能.我们成为这种应用为单体应用,也就是我们常说的单体架构(一个 war包打天下) ...
- 如何拆分大型单体系统为微服务
单体系统如何拆分为微服务 购物优惠券 https://www.cqfenfa.com/ 当单体系统越来越大,并难于维护时,很多企业开始有意把单体系统拆分为微服务风格架构.这么做很有意义,但不容易.要做 ...
- nodejs微服务:单体架构与微服务架构
单体架构 单体架构在中小企业内部用的是非常多的,就是完整独立的web服务 当业务不复杂,团队规模不大的时候,单体架构比微服务架构具有更高的生产率 1 ) 单体架构的程序部署在单台服务器 这种架构是目前 ...
- 系统由单体架构到微服务架构到底是如何演进的?
随着互联网的发展,互联网企业的业务也在不断的飞速发展,进而导致系统的架构也在不断的发生着变化.总体来说,系统的架构大致经历了:单体应用架构->垂直应用架构->分布式架构->SOA架构 ...
- 单体架构到微服务架构的带来的变化
单体架构 分布式架构 假设一个电商的下单场景,完成一笔订单入库,需要做几个操作 1. 创建订单 2. 卡券抵扣 3. 库存扣减 那么在分布式架构下的调用链,可能是下面这种情况.那么服务和服务之间势必会 ...
- 华为架构师8年经验谈:从单体架构到微服务的服务化演进之路
本次分享的技术大纲如下: 传统应用开发面临的挑战 服务化实践 服务化不是银弹 服务化架构的演进方向 一 .传统应用开发面临的挑战 挑战1-- 研发成本高 主要体现在如下几个方面: 代码重复率高 在实际 ...
- 漫谈单体架构与微服务架构(上):单体架构
最近微服务架构特别火爆,就跟人工智能.区块链一样,软件架构设计如果不提微服务,感觉就像是与世界先进的架构风格和开发技术脱了节似的,各方各面都无法彰显高大上的气质. 本来再打算使用一套系列文章来讨论微服 ...
最新文章
- 微信小程序提示 出现脚本错误或者未正确调用 Page()
- 微信小程序如何搭建本地环境开发
- 《分布式系统:概念与设计》一3.5.2 IEEE 802.11无线LAN
- OpenGL使用计算着色器进行GPU光线跟踪
- JavaScript历史状态管理
- [Python学习] 专题二.条件语句和循环语句的基础知识
- CNN卷积神经网络深度解析
- 学习笔记11-C语言-指针
- 5shift shell
- ajax 传字符串到后台,JSON.stringify()将JSON对象转换为字符串通过Ajax传入到后台处理...
- 特斯拉副总裁陶琳:Model Y 本月开始陆续交付
- Linux基于升序链表的定时器
- java+c#+json+时间_Java与C#间json日期格式互转完美解决方案
- C++配置OpenCv:一劳永逸
- 信息检索与利用(第三版)第五章 信息法与综合性信息检索
- 《算法笔记》2.3小节——C/C++快速入门-选择结构
- Invalid configuration of tez jars, tez.lib.uris is not defined in the configuration
- 狂神说JAVA 数组、三种初始化和内存分析
- 送外卖优先级_【超新人\超现实】送外卖需要了解的那些事
- OJ每日一练——津津的储蓄计划
热门文章
- PHP常用工具方法集...
- TP框架表单验证 【包含ajax方法】
- 团队第二次冲刺第三天
- 【转】R语言 RStudio快捷键
- php基础系列:从用户登录处理程序学习mysql扩展基本操作
- pdf文档遇到了共享冲突_如何将链接共享为PDF格式的Google文档链接
- 为什么Android Geeks购买Nexus设备
- macos剪切_如何使用macOS的内置“ Kill and Yank”作为替代剪切和粘贴
- [PHP] 多表外连接性能测试及优化
- Question | 网站被黑客扫描撞库该怎么应对防范?