本文通過使用Spring Boot,Spring Cloud和Docker構(gòu)建的概念驗證應(yīng)用程序的示例,為了解常見的微服務(wù)架構(gòu)模式提供了一個起點廊遍。另外小編從事在線教育多年,將自己的資料整合建了一個QQ群曼氛,對于有興趣一起交流學(xué)習(xí)java的可以加群:732976516,里面有大神會給予解答令野,也會有許多的資源可以供大家學(xué)習(xí)分享舀患,歡迎大家前來一起學(xué)習(xí)進步!
該代碼可在Github上獲得气破,圖像可在Docker Hub上獲得聊浅。只需一個命令即可啟動整個系統(tǒng)。
作為這個系統(tǒng)的基礎(chǔ),我選擇了一個舊項目低匙,其后端曾經(jīng)是一個整體旷痕。該應(yīng)用程序提供了一種處理個人財務(wù),組織收入和支出顽冶,管理儲蓄欺抗,分析統(tǒng)計數(shù)據(jù)和創(chuàng)建簡單預(yù)測的方法。
功能服務(wù)
整體應(yīng)用程序被分解為三個核心微服務(wù)强重。所有這些都是可獨立部署的應(yīng)用程序佩迟,圍繞某些業(yè)務(wù)功能組織。
帳戶服務(wù)
包含一般用戶輸入邏輯和驗證:收入/費用項目竿屹,節(jié)省和帳戶設(shè)置。
方法路徑描述用戶通過身份驗證可從UI獲得得到/賬戶/ {帳戶}獲取指定的帳戶數(shù)據(jù)
得到/帳號/電流獲取當(dāng)前帳戶數(shù)據(jù)××得到/帳號/演示獲取模擬賬戶數(shù)據(jù)(預(yù)先填寫的收入/費用項目等)
×放/帳號/電流保存當(dāng)前帳戶數(shù)據(jù)××POST/帳號/注冊新帳戶
×
統(tǒng)計服務(wù)
對主要統(tǒng)計參數(shù)執(zhí)行計算并捕獲每個帳戶的時間序列灸姊。數(shù)據(jù)點包含標(biāo)準(zhǔn)化為基本貨幣和時間段的值拱燃。此數(shù)據(jù)可用于跟蹤帳戶生命周期中的現(xiàn)金流動態(tài)。
方法路徑描述用戶通過身份驗證可從UI獲得得到/統(tǒng)計/ {}帳戶獲取指定的帳戶統(tǒng)計信
得到/統(tǒng)計/電流獲取當(dāng)前帳戶統(tǒng)計信息××得到/統(tǒng)計/演示獲取模擬賬戶統(tǒng)計信息
×放/統(tǒng)計/ {}帳戶為指定的帳戶創(chuàng)建或更新時間序列數(shù)據(jù)點
通知服務(wù)
存儲用戶的聯(lián)系信息和通知設(shè)置(如提醒和備份頻率)力惯。計劃工作人員從其他服務(wù)收集所需信息碗誉,并向訂閱客戶發(fā)送電子郵件。
方法路徑描述用戶通過身份驗證可從UI獲得得到/通知/設(shè)置/電流獲取當(dāng)前帳戶通知設(shè)置××放/通知/設(shè)置/電流保存當(dāng)前帳戶通知設(shè)置××
筆記
每個微服務(wù)都有自己的數(shù)據(jù)庫父晶,因此無法繞過API并直接訪問持久性數(shù)據(jù)哮缺。
對于這個項目,我使用MongoDB作為每個服務(wù)的主數(shù)據(jù)庫甲喝。擁有多語言持久性體系結(jié)構(gòu)(以便選擇最適合服務(wù)要求的數(shù)據(jù)庫類型)也是有意義的尝苇。
服務(wù)到服務(wù)通信非常簡單:微服務(wù)僅使用同步REST API進行通信。現(xiàn)實世界系統(tǒng)中的常見做法是使用交互方式的組合埠胖。例如糠溜,執(zhí)行同步GET請求以檢索數(shù)據(jù)并通過Message代理使用異步方法進行創(chuàng)建/更新操作,以便解耦服務(wù)和緩沖消息直撤。然而非竿,這給我們帶來了? 最終的一致性? 世界。
基建服務(wù)
分布式系統(tǒng)中有許多常見模式谋竖,可以幫助我們使所描述的核心服務(wù)工作红柱。 Spring云? 提供了強大的工具,可以增強Spring Boot應(yīng)用程序的行為以實現(xiàn)這些模式蓖乘。我會簡要介紹一下锤悄。
配置服務(wù)
Spring Cloud Config? 是分布式系統(tǒng)的水平可擴展集中配置服務(wù)。它使用可插入的存儲庫層嘉抒,目前支持本地存儲铁蹈,Git和Subversion。
在這個項目中,我使用? native profile握牧,它只是從本地類路徑加載配置文件容诬。您可以shared在Config服務(wù)資源中查看? 目錄? 。現(xiàn)在沿腰,當(dāng)Notification-service請求它的配置時览徒,使用shared/notification-service.yml 和? 配置服務(wù)響應(yīng)? shared/application.yml (在所有客戶端應(yīng)用程序之間共享)。
客戶端使用
只需構(gòu)建具有spring-cloud-starter-config 依賴關(guān)系的Spring Boot應(yīng)用程序? 颂龙,自動配置將完成剩下的工作习蓬。
現(xiàn)在,您的應(yīng)用程序中不需要任何嵌入屬性措嵌。只需提供? bootstrap.yml 應(yīng)用程序名稱和配置服務(wù)URL:
spring:
? application:
? ? name: notification-service
? cloud:
? ? config:
? ? ? uri: http://config:8888
? ? ? fail-fast: true
使用Spring Cloud Config躲叼,您可以動態(tài)更改應(yīng)用程序配置
例如,? EmailService bean? 使用注釋? @RefreshScope企巢。這意味著您可以更改電子郵件文本和主題行枫慷,而無需重建和重新啟動Notification Service應(yīng)用程序。
首先浪规,在Config服務(wù)器中更改所需的屬性或听。然后,對Notification服務(wù)執(zhí)行刷新請求: curl -H "Authorization: Bearer #token#" -XPOST http://127.0.0.1:8000/notifications/refresh
您還可以使用? webhooks自動執(zhí)行此過程笋婿。
筆記
但動態(tài)刷新有一些限制誉裆。 @RefreshScope 不適用于? @Configuration 類,不能影響? @Scheduled 方法缸濒。
fail-fast property表示如果Spring Boot應(yīng)用程序無法連接到Config Service足丢,則會立即失敗啟動。當(dāng)你一起啟動所有應(yīng)用程序時庇配,這非常有用? 霎桅。
下面有重要的安全說明。
驗證服務(wù)
授權(quán)職責(zé)被完全提取到單獨的服務(wù)器讨永,該服務(wù)器 為后端資源服務(wù)授予? OAuth2令牌滔驶。Auth Server用于用戶授權(quán)以及周邊內(nèi)部的安全機器到機器通信。
在這個項目中卿闹,我使用? Password credentials 授權(quán)類型進行用戶授權(quán)(因為它僅由本機應(yīng)用程序UI使用)揭糕,并? Client Credentials 用作微服務(wù)授權(quán)的授權(quán)類型。
Spring Cloud Security提供方便的注釋和自動配置锻霎,使服務(wù)器和客戶端都能輕松實現(xiàn)著角。您可以在文檔中了解有關(guān)它的更多信息,? 并檢查Auth Server代碼中的配置詳細(xì)信息? 旋恼。
從客戶端來看吏口,一切都與傳統(tǒng)的基于會話的授權(quán)完全相同。您可以Principal 從請求中檢索? 對象,使用基于表達式的訪問控制和@PreAuthorize 注釋檢查用戶角色和其他內(nèi)容? 产徊。
PiggyMetrics中的每個客戶端(帳戶服務(wù)昂勒,統(tǒng)計服務(wù),通知服務(wù)和瀏覽器)都有一個范圍:? server用于后端服務(wù)舟铜,以及? ui - 用于瀏覽器戈盈。因此,我們還可以保護控制器免受外部訪問谆刨,例如:
@PreAuthorize("#oauth2.hasScope('server')")
@RequestMapping(value = "accounts/{name}", method = RequestMethod.GET)
public List<DataPoint> getStatisticsByAccountName(@PathVariable String name) {
? ? return statisticsService.findByAccountName(name);
}
API網(wǎng)關(guān)
如您所見塘娶,有三種核心服務(wù),它們向客戶端公開外部API痊夭。在現(xiàn)實世界的系統(tǒng)中刁岸,這個數(shù)字可以非常快速地增長以及整個系統(tǒng)的復(fù)雜性她我。實際上虹曙,渲染一個復(fù)雜的網(wǎng)頁可能涉及數(shù)百種服務(wù)。
理論上鸦难,客戶端可以直接向每個微服務(wù)發(fā)出請求。但顯然這個選項存在挑戰(zhàn)和局限员淫,例如必須知道所有端點地址合蔽,分別對每個信息的和平執(zhí)行http請求,在客戶端合并結(jié)果介返。另一個問題是非網(wǎng)絡(luò)友好協(xié)議拴事,可能會在后端使用。
通常圣蝎,更好的方法是使用API??網(wǎng)關(guān)刃宵。它是系統(tǒng)的單一入口點,用于通過將請求路由到適當(dāng)?shù)暮蠖朔?wù)或通過調(diào)用多個后端服務(wù)并聚合結(jié)果來處理請求? 徘公。此外牲证,它還可用于身份驗證,洞察关面,壓力和金絲雀測試坦袍,服務(wù)遷移,靜態(tài)響應(yīng)處理等太,主動流量管理捂齐。
Netflix開源了? 這樣的優(yōu)質(zhì)服務(wù),現(xiàn)在使用Spring Cloud缩抡,我們可以通過一個@EnableZuulProxy注釋啟用它? 奠宜。在這個項目中,我使用Zuul存儲靜態(tài)內(nèi)容(UI應(yīng)用程序)并將請求路由到適當(dāng)?shù)奈⒎?wù)。以下是Notification服務(wù)的簡單基于前綴的路由配置:
zuul:
? routes:
? ? notification-service:
? ? ? ? path: /notifications/**
? ? ? ? serviceId: notification-service
? ? ? ? stripPrefix: false
這意味著所有以請求開頭的請求? /notifications 都將路由到Notification服務(wù)压真。您可以看到娩嚼,沒有硬編碼的地址。Zuul使用? 服務(wù)發(fā)現(xiàn)? 機制來定位Notification服務(wù)實例以及? Circuit Breaker和Load Balancer榴都,如下所述待锈。
服務(wù)發(fā)現(xiàn)
另一種眾所周知的架構(gòu)模式是服務(wù)發(fā)現(xiàn)。它允許自動檢測服務(wù)實例的網(wǎng)絡(luò)位置嘴高,這些服務(wù)實例可能由于自動擴展竿音,故障和升級而動態(tài)分配地址。
服務(wù)發(fā)現(xiàn)的關(guān)鍵部分是注冊表拴驮。我在這個項目中使用了Netflix Eureka春瞬。當(dāng)客戶端負(fù)責(zé)確定可用服務(wù)實例的位置(使用注冊服務(wù)器)并在它們之間加載平衡請求時,Eureka是客戶端發(fā)現(xiàn)模式的一個很好的例子套啤。
使用Spring Boot宽气,您可以輕松地使用spring-cloud-starter-eureka-server 依賴項,? @EnableEurekaServer 注釋和簡單配置屬性構(gòu)建Eureka Registry? 潜沦。
通過@EnableDiscoveryClient 注釋和? bootstrap.yml 應(yīng)用程序名稱啟用客戶端支持? :
spring:
? application:
? ? name: notification-service
現(xiàn)在萄涯,在應(yīng)用程序啟動時,它將向Eureka Server注冊并提供元數(shù)據(jù)唆鸡,例如主機和端口涝影,運行狀況指示器URL,主頁等.Eureka從屬于服務(wù)的每個實例接收心跳消息争占。如果心跳故障超過可配置的時間表燃逻,則實例將從注冊表中刪除。
此外臂痕,Eureka提供了一個簡單的界面伯襟,您可以在其中跟蹤正在運行的服務(wù)和可用實例的數(shù)量: http://localhost:8761
負(fù)載均衡器,斷路器和Http客戶端
Netflix OSS提供了另一套很棒的工具握童。
帶
Ribbon是一個客戶端負(fù)載均衡器姆怪,可以讓您對HTTP和TCP客戶端的行為進行大量控制。與傳統(tǒng)的負(fù)載均衡器相比澡绩,每次線上調(diào)用都不需要額外的跳 - 您可以直接聯(lián)系所需的服務(wù)片效。
開箱即用,它本身與Spring Cloud和Service Discovery集成英古。 Eureka Client? 提供可用服務(wù)器的動態(tài)列表淀衣,因此Ribbon可以在它們之間取得平衡。
豪豬
Hystrix是Circuit Breaker模式的實現(xiàn)? 召调,它可以控制通過網(wǎng)絡(luò)訪問的依賴關(guān)系的延遲和故障膨桥。主要思想是在具有大量微服務(wù)的分布式環(huán)境中停止級聯(lián)故障蛮浑。這有助于快速失敗并盡快恢復(fù) - 自我修復(fù)的容錯系統(tǒng)的重要方面。
除了斷路器控制之外只嚣,您還可以使用Hystrix添加一個回退方法沮稚,以便在主命令失敗時獲取默認(rèn)值。
此外册舞,Hystrix會為每個命令生成執(zhí)行結(jié)果和延遲的指標(biāo)蕴掏,我們可以使用它來? 監(jiān)控系統(tǒng)行為。
假裝
Feign是一個聲明式HTTP客戶端调鲸,可與Ribbon和Hystrix無縫集成盛杰。實際上,通過一個? spring-cloud-starter-feign 依賴關(guān)系和? @EnableFeignClients 注釋藐石,您可以擁有一整套負(fù)載均衡器即供,斷路器和HTTP客戶端,并具有合理的即用型默認(rèn)配置于微。
以下是帳戶服務(wù)的示例:
@FeignClient(name = "statistics-service")
public interface StatisticsServiceClient {
? ? @RequestMapping(method = RequestMethod.PUT, value = "/statistics/{accountName}", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
? ? void updateStatistics(@PathVariable("accountName") String accountName, Account account);
}
你需要的一切只是一個界面
您可以@RequestMapping 在Spring MVC控制器和Feign方法之間共享
以上示例指定了所需的服務(wù)ID -? statistics-service感謝Eureka的自動發(fā)現(xiàn)(但顯然您可以訪問具有特定URL的任何資源)
監(jiān)控儀表板
在此項目配置中逗嫡,每個帶有Hystrix的微服務(wù)都會通過Spring Cloud Bus(使用AMQP代理)將指標(biāo)推送到Turbine。Monitoring項目只是一個帶有Turbine? 和? Hystrix Dashboard的小型Spring啟動應(yīng)用程序? 株依。
讓我們看看我們在負(fù)載下的系統(tǒng)行為:帳戶服務(wù)調(diào)用統(tǒng)計服務(wù)驱证,它響應(yīng)模擬延遲變化。響應(yīng)超時閾值設(shè)置為1秒恋腕。
0 ms delay500 ms delay800 ms delay1100 ms delay表現(xiàn)良好的系統(tǒng)抹锄。吞吐量約為22個請求/秒。統(tǒng)計服務(wù)中的活動線程數(shù)量很少吗坚。中位服務(wù)時間約為50毫秒祈远。
活動線程數(shù)正在增長呆万。我們可以看到紫色線程池拒絕的數(shù)量商源,因此大約有30-40%的錯誤,但電路仍然關(guān)閉谋减。
半開狀態(tài):失敗命令的比例超過50%牡彻,斷路器啟動。睡眠窗口的時間量后出爹,下一個請求通過庄吼。
100%的請求失敗。電路現(xiàn)在永久開放严就。睡眠時間后重試不會再次關(guān)閉電路总寻,因為單個請求太慢。
日志分析
在嘗試識別分布式環(huán)境中的問題時梢为,集中日志記錄非常有用渐行。Elasticsearch轰坊,Logstash和Kibana堆棧使您可以輕松搜索和分析日志,利用率和網(wǎng)絡(luò)活動數(shù)據(jù)祟印。我的其他項目中描述了隨時可用的Docker配置? 肴沫。
安全
高級安全配置超出了此概念驗證項目的范圍。要更真實地模擬真實系統(tǒng)蕴忆,請考慮使用https和JCE密鑰庫來加密微服務(wù)密碼和配置服務(wù)器屬性內(nèi)容( 有關(guān)詳細(xì)信息颤芬,請參閱? 文檔)。
基建自動化
與部署整體應(yīng)用程序相比套鹅,部署微服務(wù)具有相互依賴性站蝠,這是一個復(fù)雜得多的過程。擁有完全自動化的基礎(chǔ)架構(gòu)非常重要芋哭。我們可以通過持續(xù)交付方法獲得以下好處:
隨時發(fā)布軟件的能力沉衣。
任何構(gòu)建都可能最終成為一個版本。
構(gòu)建工件一次减牺,根據(jù)需要進行部署豌习。
這是一個簡單的Continuous Delivery工作流程,在此項目中實施:
在此? 配置中拔疚,Travis CI為每個成功的Git推送構(gòu)建標(biāo)記圖像肥隆。因此latest ,Docker Hub上的每個微服務(wù)始終都有一個? 映像? 稚失,舊映像使用Git commit hash進行標(biāo)記栋艳。如果需要,可以輕松部署其中任何一個并快速回滾句各。
如何運行所有的東西吸占?
這真的很容易,我建議你試試凿宾。請記住矾屯,您將啟動8個Spring Boot應(yīng)用程序,4個MongoDB實例和RabbitMq初厚。確保您4 Gb 的計算機上有? 可用的RAM件蚕。您始終可以通過網(wǎng)關(guān),注冊表产禾,配置排作,身份驗證服務(wù)和帳戶服務(wù)運行重要服務(wù)。
在你開始之前
安裝Docker和Docker Compose亚情。
出口環(huán)境變量:? CONFIG_SERVICE_PASSWORD妄痪,? NOTIFICATION_SERVICE_PASSWORD,? STATISTICS_SERVICE_PASSWORD楞件,? ACCOUNT_SERVICE_PASSWORD衫生, MONGODB_PASSWORD
生產(chǎn)模式
在此模式下僧著,所有最新圖像都將從Docker Hub中提取。只需復(fù)制? docker-compose.yml 并點擊即可? docker-compose up -d障簿。
發(fā)展模式
如果您想自己構(gòu)建映像(例如盹愚,代碼中有一些更改),則必須使用Maven克隆所有存儲庫并構(gòu)建工件站故。然后皆怕,跑 docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
docker-compose.dev.yml 繼承? docker-compose.yml 了在本地構(gòu)建映像的額外可能性,并公開所有容器端口以便于開發(fā)西篓。
重要的終點
localhost:80 - 網(wǎng)關(guān)
localhost:8761 - Eureka Dashboard
localhost:9000 - Hystrix儀表板
localhost:8989 - 渦輪流(Hystrix儀表板的來源)
localhost:15672 - RabbitMq管理
筆記
所有Spring Boot應(yīng)用程序都需要運行? Config Server? 才能啟動愈腾。但是我們可以同時啟動所有容器,因為? fail-fast Spring Boot屬性和? restart: always docker-compose選項岂津。這意味著所有相關(guān)容器都將嘗試重新啟動虱黄,直到Config Server啟動并運行。
此外吮成,Service Discovery機制在所有應(yīng)用程序啟動后需要一些時間橱乱。在實例,Eureka服務(wù)器和客戶端在其本地緩存中都具有相同的元數(shù)據(jù)之前粱甫,客戶端無法發(fā)現(xiàn)任何服務(wù)泳叠,因此可能需要3次聽覺。默認(rèn)聽覺時間為30秒茶宵。
另外本人從事在線教育多年危纫,將自己的資料整合建了一個公眾號,對于有興趣一起交流學(xué)習(xí)java的初學(xué)者可以搜索:程序員文明乌庶,里面有大神會給予解答种蝶,也會有許多的資源可以供大家學(xué)習(xí)分享,歡迎大家前來一起學(xué)習(xí)進步瞒大!