<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ABP VNext從單體切換到微服務(wù)

          共 6115字,需瀏覽 13分鐘

           ·

          2020-09-30 10:00

          https://www.cnblogs.com/CKExp/p/13735261.html

          作者:微笑刺客D

          注:此處的微服務(wù)只考慮服務(wù)部分,不考慮內(nèi)外層網(wǎng)關(guān)、認(rèn)證等。

          ABP VNext從單體切換到微服務(wù),提供了相當(dāng)大的便利性,對(duì)于各模塊內(nèi)部不要做任何調(diào)整,僅需要調(diào)整承載體即可。

          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.

          分層架構(gòu)

          1. ABP VNext自身提供的分層方式如下圖,核心部分是Application、Domain與EntityFrameworkCore層,至于HttpApi.Client與HttpApi都是屬于將應(yīng)用去承載到其他系統(tǒng)之上的。

          1. Controller層在ABP VNext中被削弱了,VNext提供了將Application提供動(dòng)態(tài)Controller,所以可能習(xí)慣了將部分邏輯寫在控制器中的會(huì)有些唐突,但理解就行。

          規(guī)劃層次結(jié)構(gòu)

          1. 新建空文件夾,取名隨意(本次取名GravelService),用于存放整體項(xiàng)目。

          2. 在上一步的空文件夾內(nèi)新建空白解決方案,可以用VS去生成或是按照dotnet的命令生成。

          1. 習(xí)慣上按照ABP VNext給定的微服務(wù)Demo中的格式創(chuàng)建三個(gè)文件夾,思路清晰。當(dāng)然提供的微服務(wù)Demo還有更多文件夾,但是這次只關(guān)注這三個(gè)。

          增加三個(gè)模塊

          1. 設(shè)計(jì)三個(gè)限界上下文并繪制上下文映射。依照常見(jiàn)的訂單、產(chǎn)品與客戶劃分成三個(gè)限界上下文。并規(guī)劃好訂單作為下游依賴產(chǎn)品與客戶作為的上游。

          1. 從官網(wǎng)直接下載三個(gè)模塊,或是按照命令行去生成(前提是已經(jīng)安裝了ABP CLI),無(wú)論哪種方式,確保準(zhǔn)備好就行,依照模塊化思想,將其存到modules文件夾下。

          1. 如本次準(zhǔn)備了三個(gè)模塊Product,Order,Customer,依照實(shí)際需要,可以去精簡(jiǎn)一下內(nèi)部文件,此處各模塊內(nèi)部我只留著src和test文件夾。

          1. 對(duì)于customer模塊的src內(nèi)部,具體生成的文件夾如下,對(duì)于其中的HttpApi、HttpApi.Client及MongoDB,我采取了剔除,無(wú)需這部分(在稍后的承載體中有同等功能)。

          清理之后變得簡(jiǎn)簡(jiǎn)單單的。

          對(duì)于test內(nèi)部,同樣采取剔除無(wú)需的HttpApi.CLient、MongoDB文件夾(注:此處的無(wú)需只是針對(duì)我而言,如果有需要還是留著吧)。

          清理之后,層次劃分變得簡(jiǎn)簡(jiǎn)單單的。

          1. 改造下各模塊內(nèi)給定的Sample案例,改造成各模塊命名開(kāi)頭,方便加以區(qū)分。以Customer模塊為例,將自帶的Sample案例更名成Customer,僅作該項(xiàng)改動(dòng)。

          模擬服務(wù)調(diào)用

          1. 對(duì)于Order與Product模塊內(nèi)增加一個(gè)下游訪問(wèn)上游服務(wù)的鏈路,方便驗(yàn)證從單體跨越到微服務(wù),底層服務(wù)的無(wú)需任何改動(dòng)。對(duì)于下游訪問(wèn)上游服務(wù)的調(diào)用形式,了解到的有兩種方式。

          • 當(dāng)前上下文的應(yīng)用層直接依賴其他上下文的應(yīng)用服務(wù);

          • 當(dāng)前上下文設(shè)定出防腐層(在限界上下文間增加一層隔離,方便保證依賴限界上下文存在變動(dòng)時(shí)只需更改隔離層),在防腐層的實(shí)現(xiàn)中去依賴或遠(yuǎn)程調(diào)用其他上下文的應(yīng)用服務(wù);

          1. 我個(gè)人傾向于增加防腐層,雖然在VNext中并無(wú)相關(guān)說(shuō)法。具體使用時(shí),在領(lǐng)域?qū)踊驊?yīng)用層增加防腐層接口,及在EF Core層給與防腐層實(shí)現(xiàn),此時(shí)的EF Core層,更應(yīng)該更名為基礎(chǔ)設(shè)施層,而不單單是作為資源庫(kù)的形式。

          1. 在Order中Domain層增加ServiceClients文件夾用于存放防腐層接口,而在EntityFrameworkCore層增加ServiceClients文件夾用于存放防腐層實(shí)現(xiàn)。

          • 在防腐層接口中增加IProductServiceClient。

          public interface IProductServiceClient : ITransientDependency
          {
          ? ? Task<int> GetProductId();
          }
          • 在防腐層實(shí)現(xiàn)中增加ProductServiceClient。

          • 在Order中的EntityFrameworkCore層引用Product模塊內(nèi)的Application.Contracts層。

          • 依賴ProductAppService并完成調(diào)用。

          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中依賴防腐層接口,并完成調(diào)用。

          public class OrderAppService : OrderManagementAppService,   IOrderAppService
          {
          ? ? private readonly IProductServiceClient _productServiceClient;
          ? ? public OrderAppService(IProductServiceClient productServiceClient)
          ? ? {
          ? ? ? ? _productServiceClient = productServiceClient;
          ? ? }
          ? ? public async Task GetAsync()
          ? ? {
          ? ? ? ? var productId = await _productServiceClient.GetProductId();
          ? ? ? ? ...
          ? ? }
          }
          1. 這樣一來(lái),在防腐層實(shí)現(xiàn)中便可以使用到Product上下文的應(yīng)用服務(wù)了,對(duì)于這個(gè)應(yīng)用服務(wù)的請(qǐng)求是當(dāng)前進(jìn)程內(nèi)的還是進(jìn)程間的,由具體的承載方式而決定。

          大單體承載

          將依照如下圖,將三個(gè)模塊承載到GravelService.Host上。

          1. 新建一個(gè)GravelService.Host的項(xiàng)目,采用WebApi類型即可。存放到microservices文件夾下,這樣方便理解整個(gè)層級(jí)劃分。

          1. 其次依賴一些基本的Nuget包,諸如ABP自身的及方便展示Api的Swagger。本次不考慮實(shí)體的創(chuàng)建,也就不考慮EF Core包的依賴了。

          • Volo.Abp

          • Volo.Abp.AspNetCore.MultiTenancy

          • Volo.Abp.AspNetCore.Mvc

          • Volo.Abp.Autofac

          • Swashbuckle.AspNetCore

          1. 引用各模塊內(nèi)的Application層及EntityFrameworkCore層。模仿著給定的微服務(wù)Demo,完成一波CV操作。增加一個(gè)類出來(lái)承擔(dān)著服務(wù)與中間件的配置。

          1. 在其中依賴引用的各Application層及EntityFrameworkCore層中的Module,這樣一來(lái)模塊依賴就搞定了。

          [DependsOn(
          ? ? typeof(AbpAutofacModule),
          ? ? typeof(AbpAspNetCoreMvcModule),
          ? ? typeof(AbpAspNetCoreMultiTenancyModule),
          ? ? typeof(CustomerManagementApplicationModule),
          ? ? typeof(CustomerManagementEntityFrameworkCoreModule),
          ? ? typeof(OrderManagementApplicationModule),
          ? ? typeof(OrderManagementEntityFrameworkCoreModule),
          ? ? typeof(ProductManagementApplicationModule),
          ? ? typeof(ProductManagementEntityFrameworkCoreModule)
          ? ?)]
          public class GravelServiceHostModule : AbpModule
          {
          ...
          }
          1. 增加服務(wù)配置,將各模塊中的應(yīng)用服務(wù)動(dòng)態(tài)轉(zhuǎn)換成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";
          ? ? ? ? });
          });
          1. 然后,啟動(dòng)即可,所有模塊中的接口都承載到了該承載體中。

          1. 通過(guò)訪問(wèn)Order的api/OrderManagement/order接口獲得返回的9527,也就驗(yàn)證了,防腐層內(nèi)去訪問(wèn)Product上下文的應(yīng)用服務(wù)。

          此時(shí)是在同一進(jìn)程內(nèi),使用到的是ProductAppService的具體實(shí)現(xiàn),斷點(diǎn)查看也可看出當(dāng)前進(jìn)程內(nèi)的請(qǐng)求,依賴其他上下文服務(wù)的應(yīng)用服務(wù)為ApplicationServiceProxy。

          多服務(wù)承載

          依照如下圖開(kāi)始切換承載模式,只更改承載體,將一個(gè)大的承載體切分成各上下文獨(dú)自承載體。

          1. 新建三個(gè)和GravelService.Host同等的WebApi項(xiàng)目。在GravelService.Host上裁剪即可,每個(gè)獨(dú)立的承載體只擁有自身的上下文。

          1. 依據(jù)上下文映射關(guān)系,對(duì)處于下游的Order承載體增加對(duì)上游Product的依賴,在Order承載體中增加對(duì)Product模塊中Application.Contracts層的依賴。并在服務(wù)配置中完成依賴(第7行)。

          [DependsOn(
          ? ? typeof(AbpAutofacModule),
          ? ? typeof(AbpAspNetCoreMvcModule),
          ? ? typeof(AbpAspNetCoreMultiTenancyModule),
          ? ? typeof(OrderManagementApplicationModule),
          ? ? typeof(OrderManagementEntityFrameworkCoreModule),
          ? ? typeof(ProductManagementApplicationContractsModule)
          ? ? )]
          public class OrderServiceHostModule : AbpModule
          {
          ...
          }
          1. 配置遠(yuǎn)程服務(wù)代理,在服務(wù)配置中設(shè)置從Order承載體到Product承載體的遠(yuǎn)程服務(wù)請(qǐng)求。在Order承載體中增加Volo.Abp.Http.Client包并在服務(wù)配置中完成依賴。

          [DependsOn(
          ? ? ...
          ? ? typeof(AbpHttpClientModule),
          ...
          ? ? )]
          public class OrderServiceHostModule : AbpModule
          {
          ? ? public override void ConfigureServices(ServiceConfigurationContext context)
          ? ? {
          ? ? ? ? var configuration = context.Services.GetConfiguration();
          ...? ?
          context.Services.AddHttpClientProxies( typeof(ProductManagementApplicationContractsModule).Assembly);
          ? ? ? ? ...
          ? ? }
          }
          1. 在配置源appsettings文件中加入對(duì)Product承載體的遠(yuǎn)程調(diào)用地址

          ?{
          "RemoteServices": {
          ? "Default": {
          ? ? "BaseUrl": "http://localhost:57687"
          ? }
          }
          1. 更改項(xiàng)目配置,啟動(dòng)多個(gè)文件,一并啟動(dòng)三個(gè)獨(dú)立承載體,再次調(diào)用Order中的Get請(qǐng)求,同樣獲得了從Product上下文的應(yīng)用服務(wù)中的數(shù)據(jù)

          1. 這次采用的不同進(jìn)程間的承載方式,通過(guò)防腐層,然后經(jīng)ABP提供的Http代理服務(wù)調(diào)用Product承載體,可以斷點(diǎn)查看當(dāng)前在防腐層中的AppService類型,已經(jīng)不再是直接使用ProductAppService了。

          真香

          從大單體承載切換多服務(wù)承載,Modules部分不需要做任何更改,著實(shí)方便。至于內(nèi)部的遠(yuǎn)程調(diào)用,本身ABP VNext還存在一些問(wèn)題像類似集合的Get請(qǐng)求在3.1的版本中才做了修復(fù),但是這絲毫不影響這一巨人的前行。

          瀏覽 76
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  40岁女人做爱视频 | 亚洲无码视频在线观看观看 | 爽爽人人爽爽 | 三级在线播放视频 | A一级黄色片 |