.NET 6.0 已經發布,高性能雲原生開發框架。希望有更多的小伙伴加入大.NET陣營。這是本系列的第三篇文章:架構篇,喜歡的園友速度學起來吧。
本系列文章,主要分享一些.NET Core比較優秀的社區資料和微軟官方資料。我進行了知識點歸類,讓大家可以更清晰的學習.NET Core。
首先感謝資料原作者的貢獻。
介紹.NET歷史、開源之路、基礎、路由、依賴注入、HttpContext、cookie|session、HttpClient、gRPC、單元測試、發布部署等等。
介紹.NET工程化、AOP、異常處理、緩存、日志、響應優化、上傳下載、健康檢查、后台任務、認證和授權、安全性(Https、CORS、CSRF)、EF Core 等等
介紹.NET跨平台的包袱與演變、.NET運行機制、性能分析方案;架構相關知識(設計原則、設計模式、DDD、微服務、中台等);.NET相關的微服務開發框架、微服務技術、雲原生(docker、k8s)等
推薦資料:.NET開源github資源匯總(awesome-dotnet-core)
這是第三篇,知識點如圖:
深入.NET
#、.NET Core跨平台解讀
.NET Core跨平台的奧秘[下篇]:全新的布局(.NET Standard)
#、.NET Standard 與 .NET 5+
微軟停止更新.NET Standard,.NET 5 取而代之
選擇建議:
1. 用於在.NET Framework 和所有其他平台之間共享代碼,使用netstandard2.0
2. 用於在Mono,Xamarin 和.NET Core 3.x 之間共享代碼,使用netstandard2.1
3. 向后共享代碼,使用net5.0
#、運行機制
.NET 的執行模型(CoreCLR 執行模型和Native AOT執行模型)
200行代碼,7個對象——讓你了解ASP.NET Core框架的本質(帶源碼)
(HttpContext,RequestDelegate,Middleware,ApplicationBuilder,Server,HttpListenerServer,WebHost)
ASP.NET Core 服務是如何啟動、配置並運行的(IWebHost、CreateDefaultBuilder)
深入理解.NET Core的基元: deps.json, runtimeconfig.json, dll文件
補充:在vs中編譯core項目時,在bin下面會生成deps.json記錄nuget包依賴關系,並不會把依賴的nuget包拷貝到bin文件夾下。但執行dotnet publish命令發布core項目時,會將依賴的nuget包拷貝到發布目錄
.NET Core 運行時配置設置(小節包含幾篇文章,配置:依賴的包,加載路徑,網絡設置、線程設置等)
使用Directory.Build.props 文件管理多個csproj項目的配置
#、.NET Web 服務器
ASP.NET Core web服務器實現( kestrel&HTTP.sys )
為什么Linux 上的Asp.NET 5 需要 Kestrel ?
ASP.NET Core 的HTTP.sys Web 服務器
#、性能
性能分析
使用MiniProfiler 分析ASP.NET Core 、EF Core 性能
ASP.NET Core WebAPI中的分析工具MiniProfiler,集成swagger
分析快照堆棧、線程信息、異常信息、內存信息、GC信息等
分析.net core在linux下內存占用過高問題(dotnet-counters,dotnet-dump)
如何排查.NET 內存泄漏(dotnet-counters,dotnet-dump)
架構相關理論
#、設計理論
領域驅動架構及其演變史(EBI、DDD、端口適配、洋蔥、整潔)
The Clean Architecture(干凈體系架構)
API設計
四連問:API 接口應該如何設計?如何保證安全?如何簽名?如何防重?
緩存
一次緩存雪崩的災難復盤(並講解:緩存雪崩、緩存穿透、緩存擊穿)
(緩存雙刪方案、先寫數據庫,再刪緩存方案、刪除失敗重試機制)
業務設計
全網最全的權限系統設計方案(用戶、用戶組、角色、權限、權限組、組織等)
#、領域驅動設計(DDD)
領域驅動涉及的主要概念:領域、界限上下文、領域模型、統一建模語言(UML)、模塊、實體、值對象、應用服務&領域服務、領域事件、聚合、聚合根、倉儲、工作單元(Uow)等等
DDD中重要且難理解部分的摘抄:
1. 領域:一個領域本質上可以理解為就是一個問題域,只要是同一個領域,那問題域就相同。所以,只要我們確定了系統所屬的領域,那這個系統的核心業務,即要解決的關鍵問題、問題的范圍邊界就基本確定了。
2. 領域模型:就是將業務中涉及到的概念以面向對象的思想進行抽象,抽象出實體對象,確定實體所對應的方法和屬性,以及實體之間的關系。然后將這些實體和實體之間的關系以某種形式(比如UML、圖形、代碼、文字描述等)展現出來。
3. 模塊:
l 模塊通過分解領域模型為不同的模塊,以降低領域模型的復雜性,提高領域模型的可讀性。
l 模塊的設計要符合高內聚低耦合的設計思想。
4. 領域事件= 事件發布+ 事件存儲+ 事件分發+ 事件處理
5. 領域服務
l 領域服務是無狀態的,它存在的意義就是協調多個領域對象完成某個操作,所有的狀態還是都保存在相應的領域對象中。
l 領域服務還有一個很重要的功能就是可以避免領域邏輯泄露到應用層。因為如果沒有領域服務,那么應用層會直接調用領域對象完成本該是屬於領域服務該做的操作,這樣一來,領域層可能會把一部分領域知識泄露到應用層。因為應用層需要了解每個領域對象的業務功能,具有哪些信息,以及它可能會與哪些其他領域對象交互,怎么交互等一系列領域知識。因此,引入領域服務可以有效的防治領域層的邏輯泄露到應用層。
6. 聚合和聚合根
l 聚合的一些特點:
1) 每個聚合有一個根和一個邊界,邊界定義了一個聚合內部有哪些實體或值對象,根是聚合內的某個實體;
2) 聚合內實現事務一致性,聚合外實現最終一致性(使用領域事件進行事務拆分,實現最終一致性)。在一個事務中,只能創建或更新一個聚合。
3) 聚合內部的對象之間可以相互引用,但是聚合外部如果要訪問聚合內部的對象時,必須通過聚合根開始導航,絕對不能繞過聚合根直接訪問聚合內的對象,也就是說聚合根是外部訪問聚合的網關;
4) 聚合內除根以外的其他實體的唯一標識都是本地標識,也就是只要在聚合內部保持唯一即可,因為它們總是從屬於這個聚合的;
5) 基於聚合的以上概念,我們可以推論出從數據庫查詢時的單元也是以聚合為一個單元,也就是說我們不能直接查詢聚合內部的某個非根的對象;
6) 使用小聚合(大聚合會影響性能;大聚合容易導致並發沖突;大聚合擴展性差)
7) 聚合內部的對象可以保持對其他聚合根的引用;
8) 刪除一個聚合根時必須同時刪除該聚合內的所有相關對象,因為他們都同屬於一個聚合,是一個完整的概念;
9) 停下來重構模型。尋找模型中覺得有些疑問或者是蹩腳的地方,比如思考一些對象應該通過關聯導航獲得到還是應該從倉儲獲取?聚合設計的是否正確?考慮模型的性能怎樣,等等;
l 如何識別聚合:
先從業務的角度深入思考,然后慢慢分析出有哪些對象是:
1) 有獨立存在的意義,即它是不依賴於其他對象的存在它才有意義的;
2) 可以被獨立訪問的,還是必須通過某個其他對象導航得到的;
有分析報告顯示,通常在大部分領域模型中,有70%的聚合通常只有一個實體,即聚合根,該實體內部沒有包含其他實體,只包含一些值對象;另外30%的聚合中,基本上也只包含兩到三個實體。
l 如何識別聚合根:
如果一個聚合只有一個實體,那么這個實體就是聚合根;如果有多個實體,那么我們可以思考聚合內哪個對象有獨立存在的意義並且可以和外部直接進行交互。
7. 倉儲
l 倉儲里面存放的對象一定是聚合,原因是領域模型中是以聚合的概念去划分邊界的;聚合是我們更新對象的一個邊界,事實上我們把整個聚合看成是一個整體概念,要么一起被取出來,要么一起被刪除。我們永遠不會單獨對某個聚合內的子對象進行單獨查詢或做更新操作。因此,我們只對聚合設計倉儲
l 倉儲還有一個重要的特征就是分為倉儲定義部分和倉儲實現部分,在領域模型中我們定義倉儲的接口,而在基礎設施層實現具體的倉儲。這樣做的原因是:由於倉儲背后的實現都是在和數據庫打交道,但是我們又不希望客戶(如應用層)把重點放在如何從數據庫獲取數據的問題上,因為這樣做會導致客戶(應用層)代碼很混亂,很可能會因此而忽略了領域模型的存在。
l 倉儲定義的接口要有具體領域意義,不能是一個模糊的通用的接口。通用接口會導致取數據邏輯泄露到應用層或領域層。
#、微服務
.NET 微服務:適用於容器化.NET 應用程序的體系結構- 電子書
#、中台
.NET 微服務架構
#、ABP基礎開發框架
github:https://github.com/abpframework/abp
官方教程:https://docs.abp.io/zh-Hans/abp/latest
商業版demo:https://commercial.abp.io/demo
使用
get-started:https://www.abp.io/get-started
(使用Volo.Abp.Cli下載項目有時會失敗,可以在get-started網站上直接創建項目模板)
AbpHelper.CLI
示例
最佳實踐
基於ABP落地領域驅動設計-02.聚合和聚合根的最佳實踐和原則
基於ABP落地領域驅動設計-04.領域服務和應用服務的最佳實踐和原則
基於ABP落地領域驅動設計-06.正確區分領域邏輯和應用邏輯
其他:
Abp官方(https://www.abp.io/get-started)有提供社區版前端客戶端:Razor Pages、Blazor、Angular、ReactNative。暫時沒有提供Vue前端客戶端。這邊給出幾個vue-admin的社區資源:
abp+vue-vben-admin(vue3+typescript+ant design)
另外:
模板項目圖:
項目依賴圖:
因本人使用過ABP,所以文中以ABP基礎開發框架為例
在DotNet Core中還有很多其他的優秀基礎開發框架,如: WTM、Osharp、Blog.Core、Furioin、Silky 等等
#、.NET 微服務相關的技術
API網關:Kong、YARP(微軟開源)、Ocelot、Nginx
服務注冊與發現:Consul(Consul Tamplate+nginx)、etcd、ZooKeeper
身份認證中心:openiddict、IdentityServer4
服務調用:WebAPI、gRPC
消息事件總線:本地消息總線(進程內存緩存)、分布式消息總線(RabbitMQ、Kafka)
瞬態故障處理:Polly
分布式追蹤:SkyWalking、Cat、Zipkin、Elastc.APM
分布式系統監控:Prometheus、(App.Metrics+InfluxDB+Grafana)
分布式事務:CAP、MassTransit
分布式日志:ExceptionLess、ELK
分布式緩存:StackExchange.Redis、CSRedis、FreeRedis、ServiceStack.Redis(收費)、
分布式鎖:RedLock.NET
消息隊列:RabbitMQ、Kafka
配置中心:Apollo
DevOps:Jenkins、Docker、K8S、GitLab-ci、Azure Pipelines
相關資料推薦
API網關
高性能微服務網關.NETCore客戶端Kong.Net開源發布
基於Abp Vnext + YARP開發的API網關項目 [yarp github]
Ocelot簡易教程(簡介、配置、負載、認證、限流、聚合等)
認證授權
IdentityServer4實現了OAuth和OpenId Connect
OAuth只負責Authorization(授權). 那么誰來負責Authentication(認證)呢?那就是OpenId Connect, OpenId Connect是對OAuth的一種補充, 因為它能進行Authentication.
OAuth通常有以下幾種endpoint:authorize(授權端點),token(令牌端點,經過授權拿到對應的token),introspection(校驗端點,檢驗token的合法性),revocation(撤銷端點,撤銷授權)等
OpenId Connect 通常有以下幾種endpoints:userinfo,checksession,endsession,.well-known/openid-configuration,.well-known/jwks等
[曉晨Master]IdentityServer4 中文文檔與實戰
Asp.Net Core 中IdentityServer4 授權原理及刷新Token的應用
ABP 6.0.0 使用OpenIddict代替IDS(IdentityServer),因為IDS要收費了
分布式事務
聊聊分布式事務(ACID、CAP、BASE、2PC、TCC、本地消息表(異步確保)、MQ 事務消息)
配置中心
Apollo
Apollo github:https://github.com/ctripcorp/apollo
Apollo官方Demo:http://106.54.227.205/(賬戶密碼:apollo admin)
AgileConfig
AgileConfig github:https://github.com/dotnetcore/AgileConfig
AgileConfig 官方Demo:http://agileconfig_server.xbaby.xyz/ui (賬戶密碼:admin 123456)
分布式日志
Redis
Redis,全稱是Remote Dictionary Service,翻譯過來就是,遠程字典服務。
Redis屬於nosql非關系型數據庫。Nosql常見的數據關系,基本上是以key-value鍵值對形式存在的。
監控
ASP.NET Core之跨平台的實時性能監控(App.Metrics+InfluxDB+Grafana)
RabbitMQ
RabbitMQ:消息丟失 | 消息重復 | 消息積壓的原因+解決方案
.Net Core&RabbitMQ消息過期、死信隊列、延遲隊列
APM
使用 OpenTelemetry 構建 .NET 應用可觀測性
應用示例:
eShopOnContainers項目
[github]abp-samples/MicroserviceDemo項目
雲原生
TVP騰訊雲最具價值專家張善友,他給到的解釋是——“雲原生的本質是一系列最佳實踐的結合;雲原生是雲這種環境下的一種開發的理念、一種模式,無服務器、微服務、容器、DevOps都是雲原生理念里面的子集。
雲是和本地相對的,傳統的應用必須跑在本地服務器上,現在流行的應用都跑在雲端,雲包含了IaaS,、PaaS和SaaS。
原生就是土生土長的意思,我們在開始設計應用的時候就考慮到應用將來是運行雲環境里面的,要充分利用雲資源的優點,比如️雲服務的彈性和分布式優勢。
可以簡單地把雲原生理解為:雲原生= 微服務+ DevOps + 容器化+ 持續交付
給各種雲服務一個靈活度排序:IaaS(各種雲主機)> CaaS(Docker 等容器服務)> PaaS(BAE、SAE、GAE 等APP Engine)> FaaS > BaaS > SaaS(各種Web APP,如Google Doc)。(查看更多=>)
#、Docker 與Kubernetes(K8S)
Docker員工自述:我們為什么“輸”給了Kubernetes?
為什么要虛擬化,為什么要容器,為什么要Docker,為什么要K8S?
Docker
K8S
[Edison Zhou]ASP.NET Core on K8s 入門學習系列文章目錄
Kubernetes + .NET Core 的落地實踐(案例:本來生活網)
實例
如何使用vs將asp.net core項目添加容器支持並發布docker鏡像到私有dockerhub和添加k8s/helm管理
從零開始在Windows 上部署.NET Core 到 Kubernetes
#、自動化集成與部署
流程:編碼-> 構建-> 集成-> 測試-> 交付-> 部署
持續集成(Continuous Integration)簡稱CI
持續交付(Continuous Delivery)簡稱CD
GitHub Actions
兩種github action 打包.Net Core 項目docker鏡像推送到阿里雲鏡像倉庫
Azure Pipeline
使用Azure DevOps Pipeline實現.Net Core程序的CI
==============================================================================
over,謝謝查閱,覺得文章對你有收獲,請多幫推薦。歡迎向我提供更好的資料信息。