Spring Cloud爲開發者提供了快速構建分佈式系統中的一些常見工具,如分佈式配置中心,服務發現與註冊中心,智能路由,服務熔斷及降級,消息總線,分佈式追蹤的解決方案等。html
本次實戰以模擬下單流程爲背景,結合Spring Cloud Netflix和分佈式事務解決方案中Try Confirm Cancel模式與基於事件驅動的服務架構做爲實戰演示。java
本實例遵循的是Atomikos公司對微服務的分佈式事務所提出的RESTful TCC解決方案。mysql
RESTful TCC模式分3個階段執行git
本實例中的order-ms與membership-ms之間的通訊是基於事件驅動的。當訂單被成功建立而且付款成功以後,該訂單的部分信息將會發往membership-ms以進行積分的增長。github
從系統層面看,order-ms在EDA中是屬於Publisher角色,天然而然地membership-ms就是Subscriber。web
Publisher中的事件狀態轉換以下:spring
Subscriber中的事件狀態轉換以下:sql
部分功能介紹:docker
Zuul在本實例中僅做爲路由所使用,配置下降Ribbon的讀取與鏈接超時上限。數據庫
多個對等Eureka節點組成高可用集羣,並將註冊列表的自我保護的閾值適當下降。
{cipher}*
,那麼該密文的解密將會延遲至客戶端啓動的時候. 所以客戶端須要配置AES的對稱密鑰encrypt.key
,而且客戶端所使用的JRE須要安裝Java 8 JCE,不然將會拋出Illegal key size
相關的異常。 (本例中Docker Compose構建的容器已經安裝了JCE,若是遠程配置文件沒有使用{cipher}*
也沒必要進行JCE的安裝)@com.github.prontera.Delay
控制方法的延時返回時間;@com.github.prontera.RandomlyThrowsException
隨機拋出異常,人爲地製造異常。order
,product
,account
和tcc
中的全部Controller上都添加了以上兩個註解,當遠程配置的更新時候,能夠手工刷新/refresh
或經過webhook等方法自動刷新本地配置. 以達到模擬微服務繁忙或熔斷等狀況。此應用提供了管理Spring Boot服務的簡單UI,下圖是在容器中運行時的服務健康檢測頁
提供近實時依賴的統計和監控面板,以監測服務的超時,熔斷,拒絕,降級等行爲。
Zipkin Server
Zipkin是一款開源的分佈式實時數據追蹤系統,其主要功能是彙集來自各個異構系統的實時監控數據,用來追蹤微服務架構下的系統時延問題. 下圖是對order
服務的請求進行追蹤的狀況。
首次啓動時經過Flyway自動初始化數據庫。
對spring cloud config server採用fail fast策略,一旦遠程配置服務沒法鏈接則沒法啓動業務服務。
用於獲取用戶信息,用戶註冊,修改用戶餘額,預留餘額資源,確認預留餘額,撤銷預留餘額。
用於獲取產品信息,變動商品庫存,預留庫存資源,確認預留庫存,撤銷預留庫存。
TCC資源協調器,其職責以下:
order
服務是本項目的入口,儘管所提供的功能很簡單:
account
與product
發起預留資源請求,而且記錄入庫。tcc
統一進行確認,若是發生衝突即記錄入庫,等待人工處理。用於訂單付款成功後,對下單用戶的積分進行增長操做。該服務與訂單服務是基於消息驅動以進行通訊,達到事務的最終一致性。
下圖爲product
服務的Swagger接口文檔,根據下文的服務字典可知,本接口文檔可經過http://localhost:8040/swagger-ui.html
進行訪問. order
,account
和tcc
的文檔訪問方式亦是如出一撤。
在項目根路徑下執行腳本build.sh
,該腳本會執行Maven的打包操做,並會迭代目錄下的*-compose.yml
進行容器構建。
構建完成後須要按照指定的順序啓動,須要注意的一點是容器內服務的啓動是須要備留預熱時間,並不是Docker容器啓動後容器內的全部服務就能立刻啓動起來,要注意區分容器的啓動和容器內的服務的啓動,建議配合docker-compse logs來觀察啓動狀況。並且容器之間的服務是有依賴的,如account-ms
和product-ms
此類業務服務的啓動是會快速失敗於config-ms
的失聯。因此建議按照如下順序啓動Docker容器,而且在一組Docker容器服務徹底啓動後,再啓動下一組的Docker容器。
由於程序自己按照Docker啓動,因此對於hostname須要在hosts文件中設置正確才能正常運行:
## solar
127.0.0.1 eureka1
127.0.0.1 eureka2
127.0.0.1 rabbitmq
127.0.0.1 zipkin_server
127.0.0.1 solar_mysql
127.0.0.1 gitlab複製代碼
根據依賴關係,程序最好按照如下的順序執行
docker mysql > docker rabbitmq > eureka server > config server > zipkin server > 其餘業務微服務(account-ms, product-ms, order-ms, tcc-coordinator-ms等)
根據附表中的服務字典,咱們經過Zuul或Swagge對order
服務進行預訂單生成操做。
POST http://localhost:7291/order/api/v1/orders
Content-Type: application/json;charset=UTF-8
{
"product_id": 7,
"user_id": 1
}複製代碼
成功後咱們將獲得預訂單的結果
{
"data": {
"id": 15,
"create_time": "2017-03-28T18:18:02.206+08:00",
"update_time": "1970-01-01T00:00:00+08:00",
"delete_time": "1970-01-01T00:00:00+08:00",
"user_id": 1,
"product_id": 7,
"price": 14,
"status": "PROCESSING"
},
"code": 20000
}複製代碼
此時咱們再確認訂單
(若是想測試預留資源的補償狀況,那麼就等15s後過時再發請求,注意容器與宿主機的時間)
POST http://localhost:7291/order/api/v1/orders/confirmation
Content-Type: application/json;charset=UTF-8
{
"order_id": 15
}複製代碼
若是成功確認則返回以下結果
{
"data": {
"id": 15,
"create_time": "2017-03-28T18:18:02.206+08:00",
"update_time": "2017-03-28T18:21:32.78+08:00",
"delete_time": "1970-01-01T00:00:00+08:00",
"user_id": 1,
"product_id": 7,
"price": 14,
"status": "DONE"
},
"code": 20000
}複製代碼
至此就完成了一次TCC事務,固然你也能夠測試超時和衝突的狀況,這裏就再也不贅述。
本例中默認使用Github或GitOsc中的公開倉庫,出於自定義的須要,咱們能夠在本地構建Git倉庫,這裏選用Gitlab爲例。
將如下配置添加至docker compose中的文件中並啓動Docker Gitlab容器:
gitlab:
image: daocloud.io/daocloud/gitlab:8.16.7-ce.0
ports:
- "10222:22"
- "80:80"
- "10443:443"
volumes:
- "./docker-gitlab/config/:/etc/gitlab/"
- "./docker-gitlab/logs/:/var/log/gitlab/"
- "./docker-gitlab/data/:/var/opt/gitlab/"
environment:
- TZ=Asia/Shanghai複製代碼
將項目的config-repo
添加至Gitlab中,並修改config-ms
中git倉庫的相關驗證等參數便可。
鑑於Spring Boot Actuator的端點所帶來的兩面性,除了能夠增長spring-boot-starter-security
來得到強度較弱的HTTP Basic認證外,咱們還能夠修改management.port
和management.context-path
來提升攻擊成本. 是的,我對每個服務都修改了以上兩個屬性,而且兼容了Eureka Server,Hystrix Dashboard,Spring Boot Admin,使這些監控服務仍能正確工做. 由於對以上兩個參數修改,咱們的監控路徑有所變化,以下表:
原文:Java架構筆記