ASP.NET Core开源Web应用程序框架ABP
"作為面向服務(wù)架構(gòu)(SOA)的一個(gè)變體,微服務(wù)是一種將應(yīng)用程序分解成松散耦合服務(wù)的新型架構(gòu)風(fēng)格. 通過細(xì)粒度的服務(wù)和輕量級(jí)的協(xié)議,微服務(wù)提供了更多的模塊化,使應(yīng)用程序更容易理解,開發(fā),測(cè)試,并且更容易抵抗架構(gòu)侵蝕. 它使小型團(tuán)隊(duì)能夠開發(fā),部署和擴(kuò)展各自的服務(wù),實(shí)現(xiàn)開發(fā)的并行化.它還允許通過連續(xù)重構(gòu)形成單個(gè)服務(wù)的架構(gòu). 基于微服務(wù)架構(gòu)可以實(shí)現(xiàn)持續(xù)交付和部署."
—?維基百科
介紹
ABP框架的主要目標(biāo)之一就是提供便捷的基礎(chǔ)設(shè)施來創(chuàng)建微服務(wù)解決方案.
此示例演示了一個(gè)簡(jiǎn)單而完整的微服務(wù)解決方案;
擁有多個(gè)可獨(dú)立可單獨(dú)部署的微服務(wù).
多個(gè)Web應(yīng)用程序, 每一個(gè)都使用不同的API網(wǎng)關(guān).
使用Ocelot庫開發(fā)了多個(gè)網(wǎng)關(guān)?/ BFFs (用于前端的后端).
包含使用IdentityServer框架開發(fā)的?身份認(rèn)證服務(wù). 它也是一個(gè)帶有UI的SSO(單點(diǎn)登陸)應(yīng)用程序.
有多個(gè)數(shù)據(jù)庫. 一些微服務(wù)有自己的數(shù)據(jù)庫,也有一些服務(wù)/應(yīng)用程序共享同一個(gè)數(shù)據(jù)庫(以演示不同的用例).
有不同類型的數(shù)據(jù)庫:?SQL Server?(與?Entity Framework Core?ORM) 和?MongoDB.
有一個(gè)控制臺(tái)應(yīng)用程序使用身份驗(yàn)證展示使用服務(wù)最簡(jiǎn)單的方法.
使用Redis做分布式緩存.
使用RabbitMQ做服務(wù)間的消息傳遞.
使用?Docker?&?Kubernates?來部署&運(yùn)行所有的服務(wù)和應(yīng)用程序.
使用?Elasticsearch?&?Kibana?來存儲(chǔ)和可視化日志 (使用Serilog寫日志).
下圖顯示了該系統(tǒng):
源碼
你可以從GitHub倉庫獲取源碼.
狀態(tài)
此示例仍處于開發(fā)階段,尚未完成.
運(yùn)行解決方案
您可以從?源代碼?或者預(yù)先配置好的?docker-compose?文件運(yùn)行.
使用Docker容器
預(yù)先要求
由于所有依賴項(xiàng)都已預(yù)先配置, 因此作為Docker容器運(yùn)行更容易. 你只需要安裝最新的docker.
運(yùn)行容器
克隆或下載?ABP倉庫.
在存儲(chǔ)庫的samples/MicroserviceDemo文件夾中打開命令行.
從Docker Hub中拉取image:
docker-compose -f docker-compose.yml -f docker-compose.migrations.yml pull如果要在本地構(gòu)建映像, 可以跳過上述步驟, 使用build命令:
docker-compose -f docker-compose.yml -f docker-compose.migrations.yml build根據(jù)你的電腦配置, 構(gòu)建image可能需要很長(zhǎng)時(shí)間.
還原 SQL Server 數(shù)據(jù)庫:
docker-compose -f docker-compose.yml -f docker-compose.migrations.yml run restore-database啟動(dòng)容器:
docker-compose up -d將此行添加到hosts文件的末尾:
127.0.0.1 auth-serverhosts文件位于Windows上的C:\Windows\System32\Drivers\etc\hosts文件夾, Linux/MacOS的/etc/hosts中.
運(yùn)行應(yīng)用程序
你可能想要了解容器中運(yùn)行一些應(yīng)用程序:
后端管理應(yīng)用程序 (BackendAdminApp.Host):?http://localhost:51512?(用于管理系統(tǒng)中的用戶和產(chǎn)品)
公共網(wǎng)站 (PublicWebsite.Host):?http://localhost:51513?(用于列出產(chǎn)品并運(yùn)行/管理博客模塊)
認(rèn)證服務(wù)器 (AuthServer.Host):?http://auth-server:51511/?(用作使用IdentityServer4構(gòu)建的單點(diǎn)登錄和身份驗(yàn)證服務(wù)器)
Kibana UI:?http://localhost:51510?(用于顯示/跟蹤所有服務(wù)/應(yīng)用程序/網(wǎng)關(guān)寫入的日志)
從源代碼運(yùn)行
預(yù)先要求
為了能夠從源代碼運(yùn)行解決方案, 應(yīng)在你的計(jì)算機(jī)上安裝并運(yùn)行以下工具:
SQL Server?2015+ (可以是?express edition)
Redis?5.0+
RabbitMQ?3.7.11+
MongoDB?4.0+
ElasticSearch?6.6+
Kibana?6.6+ (可選,建議顯示日志)
打開并構(gòu)建Visual Studio解決方案
在Visual Studio 2017 (15.9.0+)中打開samples\MicroserviceDemo\MicroserviceDemo.sln.
在samples\MicroserviceDemo文件夾中的命令行運(yùn)行dotnet restore命令.
在Visual Studio中構(gòu)建解決方案.
還原數(shù)據(jù)庫
在samples\MicroserviceDemo\databases文件夾中打開MsDemo_Identity.zip和MsDemo_ProductManagement.zip并恢復(fù)到SQL Server.
請(qǐng)注意:這些數(shù)據(jù)庫在解決方案中具有EF Core遷移,但它們沒有種子數(shù)據(jù),尤其是IdentityServer4所需的配置. 因此,恢復(fù)數(shù)據(jù)庫要容易得多.
運(yùn)行項(xiàng)目
按以下順序運(yùn)行項(xiàng)目(右鍵單擊每個(gè)項(xiàng)目設(shè)置為啟動(dòng)項(xiàng)目,按Ctrl+F5運(yùn)行,無需調(diào)試):
AuthServer.Host
IdentityService.Host
BloggingService.Host
ProductService.Host
InternalGateway.Host
BackendAdminAppGateway.Host
PublicWebSiteGateway.Host
BackendAdminApp.Host
PublicWebSite.Host
解決方案簡(jiǎn)介
Visual Studio解決方案由多個(gè)項(xiàng)目組成,每個(gè)項(xiàng)目在系統(tǒng)中具有不同的角色:
應(yīng)用程序(Applications)
這些是具有用戶界面以與用戶交互并使用系統(tǒng)的實(shí)際應(yīng)用程序.
AuthServer.Host: 托管IdentityServer4以向其他服務(wù)和應(yīng)用程序提供身份驗(yàn)證服務(wù). 它是一個(gè)單點(diǎn)登錄服務(wù)器,包含登錄頁面.
BackendAdminApp.Host: 這是一個(gè)后端管理應(yīng)用程序,用于托管身份和產(chǎn)品管理模塊的UI.
PubicWebSite.Host: 作為包含簡(jiǎn)單產(chǎn)品列表頁面和博客模塊UI的公共網(wǎng)站.
ConsoleClientDemo: 一個(gè)簡(jiǎn)單的控制臺(tái)應(yīng)用程序,用于演示C#應(yīng)用程序中使用服務(wù).
網(wǎng)關(guān)/BFF(前端后端)
網(wǎng)關(guān)用于為應(yīng)用程序提供單一入口點(diǎn).它還可以用于速率限制,負(fù)載平衡等. 使用Ocelot類庫.
BackendAdminAppGateway.Host: 由BackendAdminApp.Host應(yīng)用程序用作后端.
PublicWebSiteGateway.Host: 由PublicWebSite.Host應(yīng)用程序用作后端.
InternalGateway.Host: 用于服務(wù)間通信(微服務(wù)之間的通信).
微服務(wù)
微服務(wù)沒有UI,但暴露了一些REST API.
IdentityService.Host: 托管用于管理用戶和角色的ABP Identity模塊. 它沒有其他服務(wù),僅托管Identity模塊的API.
BloggingService.Host: 托管ABP博客模塊,該模塊用于管理博客和帖子(典型的博客應(yīng)用程序). 它沒有其他服務(wù),僅托管Blogging模塊的API.
ProductService.Host: 托管用于管理產(chǎn)品的產(chǎn)品模塊(位于解決方案內(nèi)). 它還包含用于創(chuàng)建/更新產(chǎn)品管理數(shù)據(jù)庫架構(gòu)的EF Core遷移.
模塊
產(chǎn)品: 使用模塊開發(fā)最佳實(shí)踐開發(fā)的分層模塊. 它可以嵌入到單個(gè)應(yīng)用程序中,也可以通過單獨(dú)部署API和UI作為微服務(wù)托管(如本演示解決方案中所述).
數(shù)據(jù)庫
此解決方案使用多個(gè)數(shù)據(jù)庫:
MsDemo_Identity: 一個(gè)SQL數(shù)據(jù)庫. 默認(rèn)使用** SQL Server **,但可以是EF Core支持的任何DBMS. 由AuthServer和IdentityService共享. 審計(jì)日志,權(quán)限和設(shè)置也存儲(chǔ)在此數(shù)據(jù)庫中(雖然它們可以輕松擁有自己的數(shù)據(jù)庫,共享相同的數(shù)據(jù)庫以保持簡(jiǎn)單).
MsDemo_ProductManagement: 一個(gè)SQL數(shù)據(jù)庫. 同樣默認(rèn)使用?SQL Server,但可以是EF Core支持的任何DBMS. 由ProductService用作專用數(shù)據(jù)庫.
MsDemo_Blogging:?MongoDB數(shù)據(jù)庫. 由BloggingService使用.
Elasticsearch: 用于在Serilog上寫日志.
應(yīng)用
認(rèn)證服務(wù)器 (AuthServer.Host)
所有其他服務(wù)和應(yīng)用程序都使用此項(xiàng)目進(jìn)行身份驗(yàn)證和單點(diǎn)登錄. 主要使用IdentityServer4來提供這些服務(wù). 它使用了一些預(yù)構(gòu)建ABP模塊?如?Identity,?Audit Logging?和?Permission Management.
數(shù)據(jù)庫和EF Core配置
此應(yīng)用程序使用SQL數(shù)據(jù)庫(將其命名為MsDemo_Identity)并通過Entity Framework Core遷移維護(hù)其架構(gòu).
它有一個(gè)名為AuthServerDbContext的DbContext,定義如下:
在OnModelCreating方法中, 你會(huì)看到?ConfigureX()?方法調(diào)用. 具有數(shù)據(jù)庫模式的模塊通常聲明這樣的擴(kuò)展方法,以便為其自己的實(shí)體配置EF Core映射. 這是一種靈活的方法, 可以在其中安排數(shù)據(jù)庫和模塊; 可以為每個(gè)模塊使用不同的數(shù)據(jù)庫,或者將它們中的一些組合在一個(gè)共享數(shù)據(jù)庫中. 在AuthServer項(xiàng)目中,我們決定在單個(gè)物理數(shù)據(jù)庫中將單個(gè)EF Core DbContext中的多個(gè)模塊模式組合在一起. 這些模塊是Identity,IdentityServer,AuditLogging,PermissionManagement和SettingManagement模塊.
請(qǐng)注意,此DbContext僅用于數(shù)據(jù)庫遷移. 所有模塊都有自己的DbContext類,模塊在運(yùn)行時(shí)使用這些類.
用戶界面
AuthServer有一個(gè)簡(jiǎn)單的主頁,如果當(dāng)前用戶已登錄,則顯示當(dāng)前用戶信息:
它還提供登錄和注冊(cè)頁面:
這些頁面不包含在項(xiàng)目本身中. 相反,AuthServer項(xiàng)目使用帶有IdentityServer擴(kuò)展的預(yù)構(gòu)建ABP帳戶模塊. 這意味著它還可以充當(dāng)具有必要UI和邏輯的OpenId Connect服務(wù)器.
依賴
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
后端管理應(yīng)用程序 (BackendAdminApp.Host)
這是一個(gè)Web應(yīng)用程序,用于管理系統(tǒng)中的用戶,角色,權(quán)限和產(chǎn)品.
認(rèn)證
BackendAdminApp重定向到AuthServer進(jìn)行身份驗(yàn)證. 用戶輸入正確的用戶名和密碼后,頁面將再次重定向到后端應(yīng)用程序. 身份驗(yàn)證配置在BackendAdminAppHostModule類中設(shè)置:
它將"Cookies"身份驗(yàn)證添加為主要身份驗(yàn)證類型.
"oidc"身份驗(yàn)證配置為使用AuthServer應(yīng)用程序作為身份驗(yàn)證服務(wù)器.
它需要額外的身份范圍(scopes)?role,?email?and?phone.
It requires the API resource scopes?BackendAdminAppGateway,?IdentityService?and?ProductServicebecause it will use these services as APIs.
它需要API資源范圍?BackendAdminAppGateway,?IdentityService?和?ProductService,因?yàn)樗鼘⑦@些服務(wù)用作API.
IdentityServer客戶端設(shè)置存儲(chǔ)在appsettings.json文件中:
用戶界面
BackendAdminApp.Host項(xiàng)目本身沒有單個(gè)UI元素/頁面. 它僅用于提供身份和產(chǎn)品管理模塊的UI頁面.
BackendAdminAppHostModule將依賴關(guān)系添加到AbpIdentityWebModule(Volo.Abp.Identity.Web?包)和ProductManagementWebModule(ProductManagement.Web項(xiàng)目)為此目的.
用戶管理頁面的屏幕截圖:
來自權(quán)限的權(quán)限管理模式的屏幕截圖:
使用微服務(wù)
后端管理應(yīng)用程序通過后端管理網(wǎng)關(guān)對(duì)所有操作使用Identity和Product微服務(wù)(BackendAdminAppGateway.Host).
遠(yuǎn)程端點(diǎn)
appsettings.json文件包含RemoteServices部分,用于聲明遠(yuǎn)程服務(wù)端點(diǎn). 每個(gè)微服務(wù)通常都有不同的端點(diǎn). 但是,此解決方案使用API網(wǎng)關(guān)模式為應(yīng)用程序提供單個(gè)端點(diǎn):
http://localhost:65115/?是?BackendAdminAppGateway.Host?項(xiàng)目的URL. 它知道身份和產(chǎn)品服務(wù)的位置.
HTTP Clients
ABP應(yīng)用程序模塊通常提供C#客戶端庫以輕松地使用服務(wù)(API)(它們通常使用ABP框架的Dynamic C# API客戶端). 這意味著如果你需要使用Identity Service API, 你可以引用其客戶端軟件包,并通過提供的接口輕松使用API.
為此BackendAdminAppHostModule類聲明了AbpIdentityHttpApiClientModule和ProductManagementHttpApiClientModule的依賴關(guān)系.
一旦引用這些客戶端軟件包,就可以直接注入應(yīng)用程序服務(wù)接口(例如IIdentityUserAppService)并使用其方法,如本地方法調(diào)用. 它實(shí)際上通過HTTP調(diào)用到相關(guān)服務(wù)端點(diǎn)的遠(yuǎn)程服務(wù)調(diào)用.
傳遞訪問令牌(Access Token)
由于微服務(wù)需要身份驗(yàn)證和授權(quán),因此每個(gè)遠(yuǎn)程服務(wù)調(diào)用都應(yīng)包含Authentication頭. 該頭是從當(dāng)前用戶的當(dāng)前HttpContext中的access_token獲得的. 當(dāng)你使用Volo.Abp.Http.Client.IdentityModel包時(shí),會(huì)自動(dòng)執(zhí)行此操作.?BackendAdminAppHostModule聲明對(duì)此包和相關(guān)的AbpHttpClientIdentityModelModule類的依賴. 它集成到上面解釋的HTTP客戶端.
依賴
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
公共網(wǎng)站 (PublicWebSite.Host)
這是一個(gè)公共網(wǎng)站項(xiàng)目,具有Web博客和產(chǎn)品列表頁面.
認(rèn)證
公共網(wǎng)站可以在不登錄的情況下顯示博客文章和產(chǎn)品列表. 如果你登錄,你還可以管理博客. 它重定向到AuthServer進(jìn)行身份驗(yàn)證. 用戶輸入正確的用戶名和密碼后,頁面將再次重定向到公共網(wǎng)站應(yīng)用程序. 身份驗(yàn)證配置在PublicWebSiteHostModule類中設(shè)置:
它將"Cookies"身份驗(yàn)證添加為主要身份驗(yàn)證類型.
"oidc"身份驗(yàn)證配置為使用AuthServer應(yīng)用程序作為身份驗(yàn)證服務(wù)器.
它需要額外的身份范圍?role,?email?and?phone.
它需要API資源范圍?PublicWebSiteGateway,BloggingService和ProductService,因?yàn)樗鼘⑦@些服務(wù)用作API.
IdentityServer客戶端設(shè)置存儲(chǔ)在appsettings.json文件中:
用戶界面
PublicWebSite.Host項(xiàng)目有一個(gè)列出產(chǎn)品的頁面 (Pages/Products.cshtml). 它還使用博客模塊中的UI. 為此PublicWebSiteHostModule加入了BloggingWebModule(Volo.Blogging.Web?包)的依賴項(xiàng).
產(chǎn)品頁面的屏幕截圖:
使用微服務(wù)
公共網(wǎng)站應(yīng)用程序使用Blogging和Product微服務(wù)通過公共網(wǎng)站網(wǎng)關(guān)進(jìn)行所有操作(PublicWebSiteGateway.Host).
遠(yuǎn)程端點(diǎn)
appsettings.json文件包含RemoteServices部分,用于聲明遠(yuǎn)程服務(wù)端點(diǎn). 每個(gè)微服務(wù)通常都有不同的端點(diǎn). 但是,此解決方案使用API網(wǎng)關(guān)模式為應(yīng)用程序提供單個(gè)端點(diǎn):
http://localhost:64897/?是PublicWebSiteGateway.Host項(xiàng)目的URL. 它知道Blogging和產(chǎn)品服務(wù)的位置.
HTTP Clients
PublicWebSiteHostModule類聲明BloggingHttpApiClientModule和ProductManagementHttpApiClientModule的依賴關(guān)系,以便能夠?yàn)檫@些服務(wù)使用遠(yuǎn)程HTTP API.
傳遞訪問令牌(Access Token)
正如后端管理應(yīng)用程序部分中所述, Public Web Site項(xiàng)目還使用AbpHttpClientIdentityModelModule將access_token傳遞給調(diào)用服務(wù)進(jìn)行身份驗(yàn)證.
Dependencies
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
控制臺(tái)客戶端演示
最后,該解決方案包括一個(gè)非常簡(jiǎn)單的控制臺(tái)應(yīng)用程序,名為ConsoleClientDemo,它通過AuthServer進(jìn)行身份驗(yàn)證來使用Identity和Product服務(wù). 它使用內(nèi)部網(wǎng)關(guān)(InternalGateway.Host)來執(zhí)行HTTP API調(diào)用.
遠(yuǎn)程服務(wù)配置
appsettings.json文件中的RemoteService配置很簡(jiǎn)單:
http://localhost:65129/?是內(nèi)部網(wǎng)關(guān)的URL. 對(duì)服務(wù)的所有API調(diào)用都是通過此URL執(zhí)行的.
身份驗(yàn)證(IdentityServer客戶端)配置
appsettings.json還有一個(gè)IdentityServer身份驗(yàn)證配置:
此示例使用client_credentials?授予類型,該類型需要ClientId和ClientSecret進(jìn)行身份驗(yàn)證過程. 還有其他授予類型. 例如, 你可以使用以下配置切換到password(Resource Owner Password)授予類型:
除客戶端憑據(jù)外,Resource Owner Password還需要UserName?和?UserPassword. 此授權(quán)類型對(duì)于代表用戶調(diào)用遠(yuǎn)程服務(wù)很有用.
Scope?聲明API(和網(wǎng)關(guān))以授予訪問權(quán)限. 此應(yīng)用程序使用內(nèi)部網(wǎng)關(guān).
HTTP Client依賴
ConsoleClientDemoModule與AbpIdentityHttpApiClientModule和ProductManagementHttpApiClientModule有依賴關(guān)系,以便使用Identity和Product API. 它還具有“AbpHttpClientIdentityModelModule”依賴性,可通過IdentityServer進(jìn)行身份驗(yàn)證.
使用服務(wù)
使用這些服務(wù)非常簡(jiǎn)單. 請(qǐng)參閱ClientDemoService類,它只是注入IIdentityUserAppService和IProductAppService并使用它們. 該類還顯示了使用HttpClient對(duì)象的手動(dòng)HTTP調(diào)用. 有關(guān)詳細(xì)信息,請(qǐng)參閱ClientDemoService的源代碼.
API網(wǎng)關(guān)/ BFF(前端后端)
網(wǎng)關(guān)用于為應(yīng)用程序提供?單一入口點(diǎn). 通過這種方式,應(yīng)用程序僅處理單個(gè)服務(wù)地址(API端點(diǎn)),而不是每個(gè)服務(wù)的不同地址. 網(wǎng)關(guān)還用于速率限制,安全性,身份驗(yàn)證,負(fù)載平衡和更多要求.
"后端前端"(BFF)是一種常見的架構(gòu)模式,可為每種不同的應(yīng)用程序/客戶端類型構(gòu)建專注而專業(yè)的網(wǎng)關(guān). 此解決方案使用此模式并具有多個(gè)網(wǎng)關(guān).
此解決方案使用Ocelot庫來構(gòu)建API網(wǎng)關(guān). 它是ASP.NET核心廣泛接受的API網(wǎng)關(guān)庫.
后端管理應(yīng)用程序網(wǎng)關(guān) (BackendAdminAppGateway.Host)
這是"后端管理應(yīng)用程序"的后端(服務(wù)器端API)(不要混淆命名;后端管理應(yīng)用程序?qū)嶋H上是前端Web應(yīng)用程序,但系統(tǒng)管理員而不是普通用戶使用).
認(rèn)證
此網(wǎng)關(guān)使用IdentityServer?Bearer身份驗(yàn)證并配置如下:
AddIdentityServerAuthentication?擴(kuò)展方法來自?IdentityServer4.AccessTokenValidation?包, IdentityServer4項(xiàng)目的一部分 (參見?identityserver文檔).
ApiName是受保護(hù)的API,在這種情況下是BackendAdminAppGateway. 因此,此解決方案將網(wǎng)關(guān)定義為API資源. 其余配置與聲明映射(計(jì)劃在下一個(gè)ABP版本中自動(dòng)化)相關(guān).?appsettings.json中的身份驗(yàn)證相關(guān)的配置很簡(jiǎn)單:
Ocelot配置
Ocelot需要知道微服務(wù)的真實(shí)URL才能重定向HTTP請(qǐng)求. 此網(wǎng)關(guān)的配置如下所示:
ReRoutes是一個(gè)URL映射數(shù)組.?GlobalConfiguration部分中的BaseUrl是該網(wǎng)關(guān)的URL(Ocelot需要知道自己的URL). 參見?ocelot文檔?更好地了解配置.
Ocelot is a finalizer ASP.NET Core middleware and should be written as the last item in the pipeline:
Ocelot是一個(gè)終結(jié)ASP.NET核心中間件,應(yīng)該寫成管道中的最后一項(xiàng):
它根據(jù)上面的配置處理和重定向請(qǐng)求.
ABP 配置端點(diǎn)
ABP提供了一些內(nèi)置API,以從服務(wù)器獲取一些配置和信息. 例子:
/api/abp/application-configuration?返回本地化文本,權(quán)限和設(shè)置值 (http://localhost:65115/api/abp/application-configuration).
/Abp/ServiceProxyScript?返回動(dòng)態(tài)javascript代理以從javascript客戶端調(diào)用服務(wù) (http://localhost:65115/Abp/ServiceProxyScript ).
這些端點(diǎn)應(yīng)由網(wǎng)關(guān)服務(wù)提供,而不是由微服務(wù)提供. 微服務(wù)只能知道與該微服務(wù)相關(guān)的權(quán)限. 但是,一旦正確配置,網(wǎng)關(guān)就可以將多個(gè)服務(wù)的權(quán)限值聚合為一個(gè)更適合客戶端的列表.
為此, ASP.NET Core管道配置為通過MVC而不是Ocelot處理某些特定路由. 為了實(shí)現(xiàn)這一點(diǎn),MapWhen擴(kuò)展方法使用如下:
當(dāng)請(qǐng)求路徑以?/api/abp/?或?/Abp/.開頭時(shí),此配置使用標(biāo)準(zhǔn)MVC中間件.
Swagger
此網(wǎng)關(guān)配置為使用swagger UI, 這是一種用于發(fā)現(xiàn)和測(cè)試HTTP API的流行工具. 通常,Ocelot不支持在swagger上顯示API,因?yàn)樗鼰o法了解每個(gè)微服務(wù)API的詳細(xì)信息. 但是當(dāng)你遵循ABP分層模塊架構(gòu)最佳實(shí)踐時(shí),它是可能的.
BackendAdminAppGatewayHostModule將依賴性添加到AbpIdentityHttpApiModule(Volo.Abp.Identity.HttpApi包)和ProductManagementHttpApiModule(ProductManagement.HttpApi?項(xiàng)目)以包含它們的HTTP API控制器. 通過這種方式,swagger可以發(fā)現(xiàn)它們. 雖然它引用了API層,但它沒有引用應(yīng)用程序服務(wù)的實(shí)現(xiàn),因?yàn)樗鼈儗⒃谙嚓P(guān)的微服務(wù)端點(diǎn)中運(yùn)行,并由Ocelot根據(jù)請(qǐng)求URL重定向.
無論如何,當(dāng)你打開URLhttp://localhost:65115/swagger/index.html時(shí), 你將看到所有已配置的微服務(wù)的API.
權(quán)限管理
后端管理應(yīng)用程序提供權(quán)限管理UI(之前見過),并使用此網(wǎng)關(guān)獲取/設(shè)置權(quán)限. 權(quán)限管理API托管在網(wǎng)關(guān)內(nèi),而不是單獨(dú)的服務(wù). 這是一個(gè)設(shè)計(jì)決策,但如果您愿意,它可以作為另一個(gè)微服務(wù)托管.
Dependencies
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
公共網(wǎng)站網(wǎng)關(guān) (PublicWebSiteGateway.Host)
這是"公共網(wǎng)站"應(yīng)用程序的后端(服務(wù)器端API網(wǎng)關(guān)).
認(rèn)證
此網(wǎng)關(guān)使用IdentityServer?Bearer身份驗(yàn)證并配置如下:
AddIdentityServerAuthentication?擴(kuò)展方法來自?IdentityServer4.AccessTokenValidation包, IdentityServer4項(xiàng)目的一部分 (參見?identityserver文檔).
ApiName是受保護(hù)的API,在這種情況下是PublicWebSiteGateway. 其余配置與聲明映射(計(jì)劃在下一個(gè)ABP版本中自動(dòng)化)相關(guān). 與appsettings.json中的身份驗(yàn)證相關(guān)的配置很簡(jiǎn)單:
Ocelot配置
Ocelot需要知道微服務(wù)的真實(shí)URL才能重定向HTTP請(qǐng)求. 此網(wǎng)關(guān)的配置如下所示:
參見?ocelot文檔?更好地了解配置.
其它
請(qǐng)參閱"后端管理應(yīng)用程序網(wǎng)關(guān)"部分中的"ABP配置端點(diǎn)"和"Swagger"主題,這些主題與此網(wǎng)關(guān)非常相似.
依賴
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
內(nèi)部網(wǎng)關(guān) (InternalGateway.Host)
該網(wǎng)關(guān)不是BFF. 它專為微服務(wù)間通信而設(shè)計(jì),不會(huì)公開.
認(rèn)證
此網(wǎng)關(guān)使用IdentityServer?Bearer身份驗(yàn)證并配置如下:
AddIdentityServerAuthentication?擴(kuò)展方法來自?IdentityServer4.AccessTokenValidation包, IdentityServer4項(xiàng)目的一部分 (參見?identityserver文檔).
ApiName是受保護(hù)的API,在這種情況下是InternalGateway. 其余配置與聲明映射(計(jì)劃在下一個(gè)ABP版本中自動(dòng)化)相關(guān). 與appsettings.json中的身份驗(yàn)證相關(guān)的配置很簡(jiǎn)單:
Ocelot 配置
Ocelot需要知道微服務(wù)的真實(shí)URL才能重定向HTTP請(qǐng)求. 此網(wǎng)關(guān)的配置如下所示:
ReRoutes配置涵蓋了系統(tǒng)中的所有微服務(wù). 參見?ocelot文檔?更好地了解配置.
其它
請(qǐng)參閱"后端管理應(yīng)用程序網(wǎng)關(guān)"部分中的"ABP配置端點(diǎn)"和"Swagger"主題,這些主題與此網(wǎng)關(guān)非常相似.
依賴
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
微服務(wù)
微服務(wù)是獨(dú)立的HTTP API,它們以分布式方式實(shí)現(xiàn)系統(tǒng)業(yè)務(wù).
它們由應(yīng)用程序和其他微服務(wù)通過網(wǎng)關(guān)和HTTP API使用.
他們可以提升或注冊(cè)系統(tǒng)中的事件.
它們可以通過異步消息傳遞相互通信.
Identity Service (IdentityService.Host)
此服務(wù)提供用戶和角色管理API.
數(shù)據(jù)庫
與AuthServer應(yīng)用程序共享相同的數(shù)據(jù)庫(MsDemo_Identity).
Identity模塊
該服務(wù)實(shí)際上只托管ABP身份包/模塊. 不包含任何API本身. 為了托管它,添加以下依賴項(xiàng):
AbpIdentityHttpApiModule?(Volo.Abp.Identity.HttpApi?包) 提供身份API.
AbpIdentityApplicationModule?(Volo.Abp.Identity.Application?包)承載模塊的應(yīng)用程序和域?qū)拥膶?shí)現(xiàn).
AbpIdentityEntityFrameworkCoreModule?(Volo.Abp.Identity.EntityFrameworkCore?包) 使用EF Core作為數(shù)據(jù)庫API.
請(qǐng)參閱module architecture best practice guide以更好地理解分層.
認(rèn)證
這個(gè)微服務(wù)使用IdentityServerBearer身份驗(yàn)證,并配置如下:
ApiName是受保護(hù)的API,在這種情況下是IdentityService. 其余配置與聲明映射(計(jì)劃在下一個(gè)ABP版本中自動(dòng)化)相關(guān). 與appsettings.json中的身份驗(yàn)證相關(guān)的配置很簡(jiǎn)單:
Swagger
Swagger UI已配置,是此服務(wù)的默認(rèn)頁面. 如果你導(dǎo)航到URLhttp://localhost:63568/, 你將被重定向到swagger頁面以查看和測(cè)試API.
依賴
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
博客服務(wù) (BloggingService.Host)
此服務(wù)托管博客API.
數(shù)據(jù)庫
它有一個(gè)專門的MongoDB數(shù)據(jù)庫(MsDemo_Blogging)來存儲(chǔ)博客和帖子. 它還使用MsDemo_Identity SQL數(shù)據(jù)庫來審核日志,權(quán)限和設(shè)置. 因此,appsettings.json文件中有兩個(gè)連接字符串:
博客模塊
該服務(wù)實(shí)際上只托管ABP Blogging包/模塊. 不包含任何API本身. 為了托管它,添加以下依賴項(xiàng):
BloggingHttpApiModule?(Volo.Blogging.HttpApi?包) 提供Blogging API.
BloggingApplicationModule?(Volo.Blogging.Application?包) 承載模塊的應(yīng)用程序和域?qū)拥膶?shí)現(xiàn).
BloggingMongoDbModule?(Volo.Blogging.MongoDB?包) 使用MongoDB作為數(shù)據(jù)庫.
請(qǐng)參閱module architecture best practice guide以更好地理解分層.
認(rèn)證
這個(gè)微服務(wù)使用IdentityServer?Bearer身份驗(yàn)證,并配置如下:
ApiName是受保護(hù)的API,在這種情況下是BloggingService. 其余配置與聲明映射(計(jì)劃在下一個(gè)ABP版本中自動(dòng)化)相關(guān).與appsettings.json中的身份驗(yàn)證相關(guān)的配置很簡(jiǎn)單:
IdentityServer Client
此微服務(wù)還通過內(nèi)部網(wǎng)關(guān)使用Identity微服務(wù)API, 因?yàn)樵谀承┣闆r下它需要查詢用戶詳細(xì)信息(username, email, phone, name and surname). 因此,它也是IdentityServer的客戶端,并在appsettings.json文件中定義了一個(gè)部分:
由于它使用內(nèi)部網(wǎng)關(guān), 因此它還應(yīng)配置網(wǎng)關(guān)的遠(yuǎn)程端點(diǎn):
當(dāng)你將UseCurrentAccessToken設(shè)置為false時(shí),ABP會(huì)忽略當(dāng)前HttpContext中的當(dāng)前access_token,并使用上面定義的憑據(jù)對(duì)AuthServer進(jìn)行身份驗(yàn)證.
為什么不在當(dāng)前請(qǐng)求中使用當(dāng)前用戶的令牌? 因?yàn)?用戶可能沒有Identity模塊所需的權(quán)限,因此它不能直接將當(dāng)前身份驗(yàn)證令牌傳遞給Identity服務(wù). 此外,某些博客服務(wù)API是匿名的(不需要經(jīng)過身份驗(yàn)證的用戶),因此在某些情況下,HTTP請(qǐng)求中沒有"當(dāng)前用戶". 出于這些原因,應(yīng)將Blogging服務(wù)定義為具有自己的憑據(jù)和權(quán)限的Identity服務(wù)的客戶端.
如果檢查MsDemo_Identity數(shù)據(jù)庫中的AbpPermissionGrants表,則可以看到blogging-service-client的相關(guān)權(quán)限.
Swagger
Swagger UI已配置,是此服務(wù)的默認(rèn)頁面. 如果你導(dǎo)航到URLhttp://localhost:62157/, 你將被重定向到swagger頁面以查看和測(cè)試API.
依賴
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
產(chǎn)品服務(wù) (ProductService.Host)
此服務(wù)托管產(chǎn)品管理API.
數(shù)據(jù)庫和EF核心遷移
它有一個(gè)單獨(dú)的SQL數(shù)據(jù)庫,名為MsDemo_ProductManagement,用于產(chǎn)品管理模塊. 它使用EF Core作為數(shù)據(jù)庫提供程序,并具有名為ProductServiceMigrationDbContext的DbContext:
實(shí)際模型配置在modelBuilder.ConfigureProductManagement()擴(kuò)展方法內(nèi)完成. 此項(xiàng)目使用EF Core遷移維護(hù)數(shù)據(jù)庫模式.
請(qǐng)注意,此DbContext僅用于數(shù)據(jù)庫遷移. Product Management模塊有自己的DbContext類,它在運(yùn)行時(shí)使用(參見ProductManagement.EntityFrameworkCore項(xiàng)目中的ProductManagementDbContext類).
appsettings.json文件中有兩個(gè)連接字符串:
Default連接字符串指向MsDemo_Identity數(shù)據(jù)庫,該數(shù)據(jù)庫用于審計(jì)日志記錄,權(quán)限和設(shè)置存儲(chǔ). 產(chǎn)品模塊使用ProductManagement連接字符串.
產(chǎn)品模塊
該服務(wù)實(shí)際上只托管產(chǎn)品管理模塊. 不包含任何API本身. 為了托管它,添加以下依賴項(xiàng):
ProductManagementHttpApiModule?提供產(chǎn)品管理API.
ProductManagementApplicationModule?承載模塊的應(yīng)用程序和域?qū)拥膶?shí)現(xiàn).
ProductManagementEntityFrameworkCoreModule?使用EF Core作為數(shù)據(jù)庫API.
請(qǐng)參閱module architecture best practice guide以更好地理解分層. 有關(guān)此模塊的更多信息,請(qǐng)參閱下面的"產(chǎn)品管理"模塊部分
認(rèn)證
這個(gè)微服務(wù)使用IdentityServer?Bearer身份驗(yàn)證,并配置如下:
ApiName是受保護(hù)的API,在這種情況下是ProductService. 其余配置與聲明映射(計(jì)劃在下一個(gè)ABP版本中自動(dòng)化)相關(guān). 與appsettings.json中的身份驗(yàn)證相關(guān)的配置很簡(jiǎn)單:
Swagger
Swagger UI已配置,是此服務(wù)的默認(rèn)頁面. 如果你導(dǎo)航到URLhttp://localhost:60244/, 你將被重定向到swagger頁面以查看和測(cè)試API.
依賴
RabbitMQ?用于向其他服務(wù)發(fā)送消息.
Redis?用于分布式/共享緩存.
Elasticsearch?用于存儲(chǔ)日志.
模塊
ABP提供強(qiáng)大的基礎(chǔ)架構(gòu),通過提供服務(wù)和架構(gòu),使模塊化應(yīng)用程序開發(fā)更容易(參見模塊開發(fā)最佳實(shí)踐指南).
此解決方案演示了如何在分布式體系結(jié)構(gòu)中使用預(yù)構(gòu)建的應(yīng)用程序模塊. 該解決方案還包括一個(gè)簡(jiǎn)單的"產(chǎn)品管理"模塊,用于顯示分層模塊示例的實(shí)現(xiàn).
產(chǎn)品管理
產(chǎn)品管理是一個(gè)由多個(gè)層和包/項(xiàng)目組成的模塊:
ProductManagement.Domain.Shared?包含所有層之間共享的常量和類型.
ProductManagement.Domain?包含域邏輯并定義實(shí)體,域服務(wù),域事件,業(yè)務(wù)/域異常.
ProductManagement.Application.Contracts?包含應(yīng)用程序服務(wù)接口和DTO.
ProductManagement.Application?包含應(yīng)用程序服務(wù)的實(shí)現(xiàn).
ProductManagement.EntityFrameworkCore?包含DbContext和其他與EF Core相關(guān)的類和配置.
ProductManagement.HttpApi?包含API控制器.
ProductManagement.HttpApi.Client?包含C#代理以遠(yuǎn)程直接使用HTTP API. 使用ABP的Dynamic C#API客戶端功能.
ProductManagement.Web?包含UI元素(頁面,腳本,樣式..等).
通過此分層的幫助,可以在單個(gè)應(yīng)用程序中使用相同的模塊作為包引用,或者用作在另一個(gè)服務(wù)器中運(yùn)行的服務(wù). 可以分離UI(Web)和API層,因此它們可以在不同的服務(wù)器中運(yùn)行.
在此解決方案中,Web層在后端管理應(yīng)用程序中運(yùn)行,而API層由產(chǎn)品微服務(wù)托管.
本教程將重點(diǎn)介紹該模塊的一些重要方面. 但是,建議查看源代碼以便更好地理解.
Domain Layer
Product是這個(gè)模塊的主要聚合根:
它的所有屬性都有私有的set方法,可以防止屬性從類中直接更改. 產(chǎn)品類通過自己的構(gòu)造函數(shù)和方法確保其自身的完整性和有效性.
它有兩個(gè)構(gòu)造函數(shù):
默認(rèn)(無參數(shù))構(gòu)造函數(shù)是私有的,不在應(yīng)用程序代碼中使用. 這是必需的,因?yàn)榇蠖鄶?shù)ORM在從數(shù)據(jù)庫獲取時(shí)需要在反序列化實(shí)體時(shí)使用無參數(shù)構(gòu)造函數(shù).
第二個(gè)構(gòu)造函數(shù)是internal,這意味著它只能在域?qū)觾?nèi)使用. 這強(qiáng)制在創(chuàng)建新的Product時(shí)使用ProductManager. 因?yàn)?#96;`ProductManager`應(yīng)該在新產(chǎn)品創(chuàng)建上實(shí)現(xiàn)業(yè)務(wù)規(guī)則. 此構(gòu)造函數(shù)僅需要最少的必需參數(shù)來創(chuàng)建具有一些可選參數(shù)的新產(chǎn)品. 它會(huì)檢查一些簡(jiǎn)單的業(yè)務(wù)規(guī)則,以確保將實(shí)體創(chuàng)建為有效產(chǎn)品.
該類的其余部分具有操縱實(shí)體屬性的方法. 例:
SetPrice方法用于以安全的方式更改產(chǎn)品的價(jià)格(通過檢查驗(yàn)證規(guī)則).
SetStockCount是另一種用于更改產(chǎn)品庫存數(shù)量的方法:
此方法還觸發(fā)分布式事件,其中帶有ProductStockCountChangedEto參數(shù)(Eto是傳統(tǒng)的后綴代表Event?Transfer?Object,但不是必需的)通知產(chǎn)品庫存數(shù)量的聽眾已發(fā)生變化. 任何訂戶都可以接收此事件并根據(jù)該知識(shí)執(zhí)行操作.
RabbitMQ為此解決方案分發(fā)事件. 但是ABP通過提供必要的抽象來獨(dú)立于消息代理Event Bus文檔).
如前所述,該模塊強(qiáng)制始終使用ProductManager來創(chuàng)建新的Product.?ProductManager是一個(gè)簡(jiǎn)單的域服務(wù),定義如下:
它檢查之前是否使用過給定的代碼. 否則拋出ProductCodeAlreadyExistsException.
使用GuidGenerator(IGuidGenerator)服務(wù)來創(chuàng)建一個(gè)新的Guid.
它將實(shí)體插入存儲(chǔ)庫.
因此,通過這種設(shè)計(jì),產(chǎn)品代碼的唯一性得到保證.
ProductCodeAlreadyExistsException是一個(gè)域/業(yè)務(wù)異常,定義如下:
PM:000001是發(fā)送給客戶端的異常類型的代碼,因此他們可以理解錯(cuò)誤類型. 在這種情況下沒有實(shí)現(xiàn),但也可以本地化業(yè)務(wù)異常. 請(qǐng)參閱異常處理文檔.
應(yīng)用層
該模塊的應(yīng)用層有兩個(gè)服務(wù):
ProductAppService主要由后端管理應(yīng)用程序用于管理(創(chuàng)建,更新,刪除.)產(chǎn)品. 它需要許可才能執(zhí)行任何操作.
公共網(wǎng)站使用PublicProductAppService來向訪問者顯示產(chǎn)品列表. 它不需要任何權(quán)限,因?yàn)榇蠖鄶?shù)訪問者都沒有登錄到應(yīng)用程序.
請(qǐng)注意; 每個(gè)應(yīng)用程序分離應(yīng)用程序?qū)涌赡苁歉玫脑瓌t, 而不是將兩個(gè)應(yīng)用程序服務(wù)放入同一個(gè)項(xiàng)目中. 但是我們?cè)谶@個(gè)解決方案中簡(jiǎn)化了它們.
例如,ProductAppService具有以下更新產(chǎn)品的方法:
它定義了所需的權(quán)限(ProductManagementPermissions.Products.Update是一個(gè)值為ProductManagement.Update的常量)來執(zhí)行此操作.
獲取產(chǎn)品的ID,DTO包含要更新的值.
從存儲(chǔ)庫中獲取相關(guān)的產(chǎn)品實(shí)體.
使用Product類的相關(guān)方法(如SetName)來更改屬性,因?yàn)樗鼈兪撬接衧et方法,更改值的唯一方法是使用實(shí)體方法.
通過使用ObjectMapper向客戶端返回更新的ProductDto(客戶端可能由于某種原因需要它).
實(shí)施可能會(huì)根據(jù)要求而有所不同. 此實(shí)現(xiàn)遵循此處提供的最佳實(shí)踐.
其他層
請(qǐng)參閱源代碼中的其他層.
基礎(chǔ)設(shè)施
消息和RabbitMQ
異步消息傳遞是分布式系統(tǒng)中的關(guān)鍵概念. 它可以以松散耦合的方式與容錯(cuò)進(jìn)行通信. 在發(fā)送消息時(shí),它不要求雙方都在線. 因此,它是微服務(wù)架構(gòu)中廣泛使用的通信模式.
分布式事件總線
分布式事件(事件總線)是一種消息傳遞方式,其中服務(wù)引發(fā)/觸發(fā)事件,而其他服務(wù)注冊(cè)/偵聽這些事件,以便在發(fā)生重要事件時(shí)得到通知. ABP通過提供約定,服務(wù)和集成使分布式事件更易于使用.
您已經(jīng)看到Product類使用以下代碼行發(fā)布事件:
ProductStockCountChangedEto?was defined as shown below:
該對(duì)象存儲(chǔ)有關(guān)該事件的必要信息. 通過使用通用的ProductStockCountChangedEto參數(shù)實(shí)現(xiàn)IDistributedEventHandler接口,另一個(gè)服務(wù)可以輕松注冊(cè)到此事件:
當(dāng)你使用Volo.Abp.EventBus.RabbitMQ包時(shí),所有集成和通信都由ABP框架完成.如果需要從實(shí)體發(fā)布事件,只需注入IDistributedEventBus并使用PublishAsync方法.
有關(guān)分布式事件系統(tǒng)的更多信息, 請(qǐng)參見Event Bus文檔.
RabbitMQ配置
在此解決方案中,?RabbitMQ用于消息傳遞和分布式事件.
Volo.Abp.EventBus.RabbitMQ包需要集成到RabbitMQ以用于分布式事件系統(tǒng). 然后你需要為模塊的AbpEventBusRabbitMqModule添加依賴項(xiàng). 例如ProductServiceHostModule聲明了這種依賴.
默認(rèn)情況下,abpEventBusRabbitMqModule從appsettings.json獲取配置. 例如產(chǎn)品服務(wù)具有以下配置:
緩存和Redis
分布式系統(tǒng)顯然需要分布式和共享緩存,而不是每個(gè)服務(wù)的隔離內(nèi)存緩存.
Redis在此解決方案中用作分布式緩存. 該解決方案使用Microsoft的標(biāo)準(zhǔn)Microsoft.Extensions.Caching.Redis包進(jìn)行集成. 使用和配置此程序包時(shí),所有應(yīng)用程序和服務(wù)都使用Redis緩存. 有關(guān)詳細(xì)信息請(qǐng)參閱Microsoft的文檔.
該解決方案還使用Microsoft.AspNetCore.DataProtection.StackExchangeRedis包在Redis緩存上共享應(yīng)用程序和服務(wù)之間的數(shù)據(jù)保護(hù)密鑰.
Logging,Serilog,Elasticsearch和Kibana
該解決方案使用Serilog作為日志庫. 它是一個(gè)廣泛使用的庫,有許多數(shù)據(jù)源集成,包括Elasticsearch.
使用類似于下面給出的代碼塊在Program.cs文件中完成日志配置:
這會(huì)配置多個(gè)日志輸出目標(biāo):File和Elasticsearch.對(duì)于此示例,Application屬性設(shè)置為ProductService. 這是一種區(qū)分單個(gè)數(shù)據(jù)庫中多個(gè)服務(wù)的日志的方法. 然后, 你可以通過Application名稱查詢?nèi)罩?
從appsettings.json配置文件中讀取Elasticsearch URL:
如果你使用Kibana, 它是一個(gè)與Elasticsearch完美集成的可視化工具,可以看到有關(guān)你的日志的一些UI:
Figure - 一個(gè)儀表板,顯示服務(wù)/應(yīng)用程序的日志和錯(cuò)誤計(jì)數(shù).
Figure - 日志條目列表
Kibana URL默認(rèn)為http://localhost:5601/.
審計(jì)日志
ABP提供自動(dòng)審計(jì)日志記錄,詳細(xì)保存每個(gè)請(qǐng)求(當(dāng)前用戶,瀏覽器/客戶端,執(zhí)行了哪些操作,哪些實(shí)體更改,甚至實(shí)體的哪些屬性已更新). 有關(guān)詳細(xì)信息,請(qǐng)參閱審計(jì)日志文檔.
所有服務(wù)和應(yīng)用程序都配置為編寫審核日志. 審核日志將保存到MsDemo_Identity SQL數(shù)據(jù)庫中. 因此,您可以從單個(gè)點(diǎn)查詢所有應(yīng)用程序的所有審核日志.
審核日志記錄具有CorrelationId屬性,可用于跟蹤請(qǐng)求. 當(dāng)服務(wù)在單個(gè)Web請(qǐng)求中調(diào)用另一個(gè)服務(wù)時(shí),它們都會(huì)使用相同的CorrelationId保存審核日志. 請(qǐng)參閱數(shù)據(jù)庫中的AbpAuditLogs表.
原文地址:https://cn.abp.io/documents/abp/latest/Samples/Microservice-Demo
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core开源Web应用程序框架ABP的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET Core应用程序容器化、
- 下一篇: ASP.NET Core 借助 K8S