本來想在Dpar 1.0GA時發布這篇文章,由於其他事情耽擱了放到現在。時下微服務和雲原生技術如火如荼,微軟也不甘示弱的和阿里一起適時推出了Dapr(https://dapr.io/),園子里關於dapr的文章不太多,所以今天就借這篇文章分享一下如何通過dapr跑起來一個簡易的電商系統,讓大家通過這個系統來觀察dapr如何運作的,權當拋磚引玉。
目錄:
一、通過Dapr實現一個簡單的基於.net的微服務電商系統
二、通過Dapr實現一個簡單的基於.net的微服務電商系統(二)——通訊框架講解
三、通過Dapr實現一個簡單的基於.net的微服務電商系統(三)——一步一步教你如何擼Dapr
四、通過Dapr實現一個簡單的基於.net的微服務電商系統(四)——一步一步教你如何擼Dapr之訂閱發布
五、通過Dapr實現一個簡單的基於.net的微服務電商系統(五)——一步一步教你如何擼Dapr之狀態管理
六、通過Dapr實現一個簡單的基於.net的微服務電商系統(六)——一步一步教你如何擼Dapr之Actor服務
七、通過Dapr實現一個簡單的基於.net的微服務電商系統(七)——一步一步教你如何擼Dapr之服務限流
八、通過Dapr實現一個簡單的基於.net的微服務電商系統(八)——一步一步教你如何擼Dapr之鏈路追蹤
九、通過Dapr實現一個簡單的基於.net的微服務電商系統(九)——一步一步教你如何擼Dapr之OAuth2授權 && 百度版Oauth2
十、通過Dapr實現一個簡單的基於.net的微服務電商系統(十)——一步一步教你如何擼Dapr之綁定
十一、通過Dapr實現一個簡單的基於.net的微服務電商系統(十一)——一步一步教你如何擼Dapr之自動擴/縮容
十二、通過Dapr實現一個簡單的基於.net的微服務電商系統(十二)——istio+dapr構建多運行時服務網格
十三、通過Dapr實現一個簡單的基於.net的微服務電商系統(十三)——istio+dapr構建多運行時服務網格之生產環境部署
十四、通過Dapr實現一個簡單的基於.net的微服務電商系統(十四)——開發環境容器調試小技巧
十五、通過Dapr實現一個簡單的基於.net的微服務電商系統(十五)——集中式接口文檔實現
十六、通過Dapr實現一個簡單的基於.net的微服務電商系統(十六)——dapr+sentinel中間件實現服務保護
十七、通過Dapr實現一個簡單的基於.net的微服務電商系統(十七)——服務保護之動態配置與熱重載
附錄:(如果你覺得對你有用,請給個star)
一、電商Demo地址
首先第一個話題,什么是dapr?
要說dapr,首先我們得了解什么是服務網格,而要說服務網格還是得先講講微服務。微服務的概念相信現在大家已經耳熟能詳了。在微服務體系中,開發者通過拆分設計不同的服務,通過服務間協同作業的方式聚合業務實現相關的功能。
服務與服務之間涉及服務調用、事件傳播、狀態流轉等等概念,再細分相關功能會涉及到服務調用時限流、重試、降級,事件傳播時確保一致性,對整個服務系統的拓撲追蹤、監控等等功能。以java為例,一般是采用dubbo或者springcloud這樣的侵入性框架,通過開發人員手動集成到項目里。並在外部搭建諸如zookeeper、eureka這樣的分布式協調器來實現服務的注冊、發現。通過網關如zuul、kong實現對外部對內部服務的調用,通過feign ribbon hystrix這樣或那樣的組件實現服務間通訊時負載均衡、熔斷、限流、降級。通過設計eventbus來實現事件在服務間流轉。
說了這么一大堆,和服務網格有什么關系呢?服務網格本質上就是微服務架構在雲原生基礎上對網絡通訊相關的功能做了解耦和下沉。讓運行於雲原生之上的應用(一般呈現方式主要是容器)可以不再關心服務間通訊相關的一大堆技術實現。通過對每一個應用附加一個獨立進程的代理(也叫sidecar)實現。
這樣開發人員只關心應用如何實現具體的業務,而不用去關心具體的服務間治理,服務網格幫應用完成服務注冊、發現、負載均衡、重試、限流等等相關功能。
所以dapr是什么就一目了然了,dapr就是服務網格的一種實現方式。只不過相比傳統的服務網格關注的可能是流量治理來講dapr更關注服務間狀態變化,用官方的原話來講“Dapr 是一個可移植的、事件驅動的運行時,它使任何開發人員能夠輕松構建出彈性的、無狀態和有狀態的應用程序,並可運行在雲平台或邊緣計算中,它同時也支持多種編程語言和開發框架。”
什么是事件驅動?
什么是事件驅動?我們知道在一個分布式系統里,當某個服務需要其他服務協同作業時,有兩種辦法,一種就是通過強一致性的方式調用,比如RPC call或者restapi。這種方式有一個弊端,就是必須確保下游服務必須可用,否則可能會導致同步調用時調用過程超時、或者下游服務不響應導致的失敗。
在分布式系統里由於網絡IO不可靠等等因素,我們往往很難100%確保同步調用能夠將一個業務在多個服務間協同完成,所以一般會采用訂閱-發布的方式。也就是大家比較熟悉的事件總線這樣的異步模型,通過將我們的請求以發布事件的方式灌入消息隊列后不等待立即返回,通過訂閱方訂閱消息完成后續操作,若需要回滾同樣發布事件,由發送方訂閱失敗消息進行補償操作即可。
通過這樣的方式我們可以構建一個以事件來驅動的異步的,最終一致性的響應式系統。而dapr則是將事件驅動在雲原生層面發揚光大,通過對不同中間件的集成屏蔽了構建事件驅動架構的各種復雜性,讓開發人員幾乎不寫或者少寫代碼的情況下完成一個事件驅動架構的分布式系統。
Dapr如何助力微服務設計落地的?
Dapr提供了哪些功能來助力我們微服務落地呢?可以從上圖看到有7,8種功能,我們從左至右一個一個來講。
第一個就是服務間調用,也就是常見的同步調用。dapr在服務間調用封裝了服務注冊發現、ssl、自動重試、熔斷、限流(需單獨配置支撐)。一般當應用請求下游服務時daprd會發起一個https請求、若超時會重試數次,若下游服務下線不可用則會返回一個友好的json格式的50x供上游服務做異常冗余處理。
第二個是狀態管理,提供了對於存儲鍵/值對的狀態管理,同時對大部分主流的狀態存儲中間件進行了支持,而無需開發者去對特定中間件做相應的sdk集成。
第三個是訂閱發布,通過該api可以輕松實現一個異構的語言無關的事件總線,同時和狀態管理一樣,它的訂閱發布中間件是可插拔的。
第四個是資源綁定,帶觸發器的資源綁定通過接收和發送事件到任何外部源(如數據庫、隊列、文件系統等)來進一步構建事件驅動架構,以實現擴展性和彈性,此特性有一點Serverless的思想。
第五個是大名鼎鼎的actor模型,很多沒接觸過actor的同學可能會一頭霧水的問actor模型是什么呢?簡單來講就是一個分布式的並發的無鎖線程同步對象。舉一個簡單的例子它可以解決在並發下商品超賣的問題,假設我們有一個api可以通過訪問來扣商品庫存,在無鎖無事務的情況下,由於讀寫數據庫時間差的問題,一定會導致商品超賣,即便是我們將商品庫存放在對象上通過內存保存,如果不引入原子操作,也一樣會有線程同步導致的數據不一致問題,而actor則可以在不引入任何內部或外部api/sdk的情況下實現多線程訪問下數據的完全一致性。 簡單來講就是每一個actor是通過對mailbox隊列來阻塞消費實現多線程訪問下數據一致性的,具體大家可以多了解一下這個模型。 而Dapr 在其 actor 運行時提供了很多能力,包括並發,狀態管理,用於 actor 激活/停用的生命周期管理,以及喚醒 actor 的計時器和提醒器。
第六個是可觀測性,dapr通過一些三方組件提供了諸如鏈路追蹤和應用監控等等相關觀測手段來方便開發人員更加直觀的定位網絡問題等等。
第七個是安全性,默認dapr之間調用不管是同步調用還是actor調用或者訂閱發布,均會通過雙向https的方式加密通訊,避免明文傳遞消息。
最后一個是豐富的擴展組件,熟悉dapr的開發者可以自定義各種組件通過中間件的方式插入到sidecar的pipline中去實現自定義功能的擴展。
另外需要關注的是dapr對上層應用提供了兩種請求模式,一種是http api一種是grpc api,通過這種語言無關的方式我們可以輕易的在不同語言之間通過dapr搭建起一個異構的分布式系統而不用關心不同語言之間的差異。
Dapr與其他服務網格的區別
目前市場上的服務網格框架基本都被諸如linkerd、istio這樣的老牌服務網格占據。這些服務網格的關注點和dapr有一定區別。如果非要說相同或者相似點的話那就是他們的架構都是由數據平面和控制平面組成,其中數據平面主要是由集群內的各種sidecar組成,而控制平面就是調度中心。 另外一個相同點就是他們都實現了對應用程序的代碼無侵入性(dapr提供了簡單的sdk,只是對dapr api的簡易封裝,不是必選項),但是從功能層面來講,兩者的關注點則完全不一樣了,例如service mesh霸主istio他提供了對流量切分、流量鏡像、監控、智能路由、故障注入,自動化的度量指標、日志以及追蹤等等功能,可以看到它更關心流量代理這部分邏輯。而dapr在這部分目前來講還稍弱,但是dapr提供了其他服務網格幾乎沒有關心的狀態服務、事件、actor模型等等功能,兩者可以說是互補的(dapr是可以和istio這樣的服務網格集成工作的,未來可期)
更多了解dapr
訪問https://dapr.io了解更多
talk is cheap, show me the code!
說了那么多概念,最終還是需要落地到具體的系統設計上,我們就從這個電商系統開始吧。
技術概要、設計規范
整個電商系統分為兩個具體的repo
https://github.com/sd797994/Oxygen-Dapr
該repo是針對Dapr通訊相關的API統一了編程模型封裝實現的一個rpc框架,類似於dapr提供的.net SDK,該repo我已經將打包到了nuget,所以電商系統不需要依賴該repo的源代碼,有興趣的朋友可以copy下來,可以的話請star一下。該框架基於.net5
https://github.com/sd797994/Oxygen-Dapr.EshopSample
該repo為本次演示電商系統源代碼,其結構如下:
Depoly主要是一些yaml和bat方便讀者朋友通過k8s快速啟動之用。
Public包含一些領域業務的抽象(DomainBase)和工具層(InfrastructureBase)以及RPC的接口層(Remote-IApplicationService)以及前端(WebPage-www)及后端(WebPage-Admin)頁面
Services文件夾包含后端的微服務,分為賬戶服務、商品服務、商城公共服務以及交易服務,另外包含兩個通用支撐服務:圖片服務以及作業服務。
業務微服務類主要是以清潔架構分層,清潔架構是領域驅動設計的一個概念:
整個代碼結構是以Domain為核心,外部依次是應用層、基礎設施,是一個從內及外的設計。
Domain包含了整個服務所需的具體的業務聚合,Domain的核心數聚合,包含聚合根、實體以及值對象,剩余部分則是圍繞聚合形成的規約、DTO、領域服務、倉儲抽象等等。
應用層通過讀寫分離的方式來實現對領域層的操作和對查詢業務的操作,另外包含事件訂閱器用於接收其他應用發起的領域事件。其結構如下:
用例(UseCaseService)類型的應用服務主要作用就是聚合操作當前服務的領域,同時調用基礎設施層實現持久化以及事務,同時可以發送領域事件亦或是調用遠程RPC。
查詢(QueryService)類型的應用服務主要是對各種客戶端發起的業務指令調用基礎設施層的ORM或es或者dapr的statemanager或者遠程RPC進行具體的操作查詢。
事件訂閱器(EventHandler)類型的應用服務主要是接收事件並進行業務操作,其操作邏輯和用例類似。
基礎設施層則包含了對上層的一系列支撐,包括各種通用組件、工具、ORM、持久化實體、倉儲實現等等,其中用到的外部持久化設備有postgres、elasticsearch以及redis,所有的業務表存儲主要依賴於postgres,elasticsearch主要是包含移動端的商品列表查詢,redis則主要是對dapr以及作業系統的持久化支撐。此處不再贅述。
Host作為服務啟動的入口,主要是啟動通用主機注入依賴注入框架,注入Oxygen框架初始化各種配置、AOP、鑒權服務等等來啟動RPC服務。不再贅述
部署網絡拓撲圖
Tips:如何部署可以參考repo的readme.md
整個系統前、后端以及各種通用服務都是以容器化的方式運行在k8s之上的。其中在最前端是k8s的ingress-controller,由於這個場景相對比較簡單,不需要各種復雜的流量切分邏輯,所以我目前選型的是k8s官方推薦的nginx。當請求從客戶端發起的時候,流量最先流入ingress-controller,通過已配置好的ingress規則會再次發送到各個k8s service再流入具體的pod進行作業。
其中對www.dapreshop.com的訪問會直接請求到后端頁面pod、對m.dapreshop.com的訪問會請求到移動端頁面pod,這兩個頁面上發起的api.dapreshop.com則會統一先流入到一個叫apigateway的pod上,該pod附加了一個dapr的sidecar,該pod只是一個包含路由重寫規則的nginx,它的作用是將源地址請求重新組裝為dapr可識別的api地址並調用sidecar,這樣通過sidecar和內網的其他掛載了sidecar的各種子服務進行相應的互操作。
如何運行它?
Tips:如何運行可以參考repo的readme.md
通過kubectl查詢兩個命名空間看到如下情況則代碼系統已經完全啟動完畢。
這個時候訪問admin.dapreshop.com會進入該頁面:
當初始化后會自動創建一個管理員、一個用於模擬下單的用戶以及相關的權限、角色。
同時會自動創建商城的基礎設置、商品分類、商品,以及隨機創建幾個商品的折扣活動。
此時訪問m.dapreshop.com就能看到一個包含商品的下單頁面了
隨意選擇幾個商品,選擇結算后,后端即可創建一個訂單,后台就可以模擬訂單的剩余流程、注意該訂單會在5分鍾內被作業系統取消,庫存會回滾。
觀察
當我們在前后端做了各種操作后,登錄zipkin.dapreshop.com即可觀察到流量的變化
可以觀察到相應的請求和鏈路細節
以前端下訂單為例:
流量通過網關路由到交易服務,交易服務會調用賬戶服務獲取一個mock account、然后會調用商品RPC查詢商品基礎信息,接下來調用商品Actor對象做具體的庫存減扣,最后發布事件,同時交易服務的交易記錄訂閱器和作業訂閱器會訂閱該事件做后續相關操作。由於所有的請求都通過daprd這個sidecar完成,所以所有的請求和流量都能通過zipkin直觀的觀察到。
最后我們可以在daprcli中通過dapr dashborad -k 來觀測dapr目前控制平面的基本情況,此部分就不贅述了,大家可以登錄dapr的官網多了解
以上就是本次關於dapr如何落地一個電商demo的入門級的相關分享,Dapr本身包含了太多的內容由於時間關系無法一一呈現還需要讀者朋友們在實際使用中去挖掘,如果喜歡的話請給repo一個star,歡迎轉發fork~