歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~html
本文經過使用Spring Boot,Spring Cloud和Docker構建的概念驗證應用程序的示例,爲了解常見的微服務架構模式提供了一個起點。git
該代碼在Github上可用,而且能夠在Docker Hub上得到圖像。只需一個命令便可啓動整個系統。github
做爲這個系統的基礎,我選擇了一箇舊項目,其後端曾經是一個總體。該應用程序提供了一種處理我的財務,組織收入和支出,管理儲蓄,分析統計數據和建立簡單預測的方法。web
總體應用程序被分解爲三個核心微服務。全部這些都是可獨立部署的應用程序,圍繞某些業務功能組織。spring
包含通常用戶輸入邏輯和驗證:收入/費用項目,節省和賬戶設置。docker
METHOD | PATH | DESCRIPTION | USER AUTHENTICATED | AVAILABLE FROM UI |
---|---|---|---|---|
GET | /accounts/{account} | Get specified account data | ||
GET | /accounts/current | Get current account data | × | × |
GET | /accounts/demo | Get demo account data (pre-filled incomes/expenses items, etc) | × | |
PUT | /accounts/current | Save current account data | × | × |
POST | /accounts/ | Register new account |
對主要統計參數執行計算並捕獲每一個賬戶的時間序列。數據點包含標準化爲基本貨幣和時間段的值。此數據可用於跟蹤賬戶生命週期中的現金流動態。數據庫
METHOD | PATH | DESCRIPTION | USER AUTHENTICATED | AVAILABLE FROM UI |
---|---|---|---|---|
GET | /statistics/{account} | Get specified account statistics | ||
GET | /statistics/current | Get current account statistics | × | × |
GET | /statistics/demo | Get demo account statistics | × | |
PUT | /statistics/{account} | Create or update time series datapoint for specified account |
存儲用戶的聯繫信息和通知設置(如提醒和備份頻率)。計劃工做人員從其餘服務收集所需信息,並向訂閱客戶發送電子郵件。bootstrap
METHOD | PATH | DESCRIPTION | USER AUTHENTICATED | AVAILABLE FROM UI |
---|---|---|---|---|
GET | /notifications/settings/current | Get current account notification settings | × | × |
PUT | /notifications/settings/current | Save current account notification settings | × | × |
分佈式系統中有許多常見模式,能夠幫助咱們使所描述的核心服務工做。Spring cloud 提供了強大的工具,能夠加強Spring Boot應用程序的行爲以實現這些模式。我簡要介紹一下:後端
Spring Cloud Config 是分佈式系統的水平可擴展集中配置服務。它使用可插入的存儲庫層,目前支持本地存儲,Git和Subversion。
在這個項目中,我使用 native profile
,它只是從本地類路徑加載配置文件。你能夠在Config服務資源中查看 share 目錄 。如今,當Notification-service請求它的配置時,使用shared/notification-service.yml
和 配置服務響應 shared/application.yml
(在全部客戶端應用程序之間共享)。
只需構建具備spring-cloud-starter-config
依賴性的Spring Boot應用程序 ,自動配置將完成剩下的工做。
如今,你的應用程序中不須要任何嵌入屬性。只需提供 bootstrap.yml
應用程序名稱和配置服務URL:
spring: application: name: notification-service cloud: config: uri: http://config:8888 fail-fast: true
例如, EmailService bean 使用註釋 @RefreshScope
。這意味着你能夠更改電子郵件文本和主題行,而無需重建和從新啓動Notification Service應用程序。
首先,在Config服務器中更改所需的屬性。而後,對Notification服務執行刷新請求: curl -H "Authorization: Bearer #token#" -XPOST http://127.0.0.1:8000/notifications/refresh
你還可使用 webhooks自動執行此過程。
@RefreshScope
不適用於 @Configuration
類,不能影響 @Scheduled
方法。fail-fast
property表示若是Spring Boot應用程序沒法鏈接到Config Service,則會當即失敗啓動。當你同時啓動全部應用程序時,這很是有用 。受權職責徹底提取到單獨的服務器,該服務器 爲後端資源服務授予 OAuth2令牌。Auth Server用於用戶受權以及周邊內部的安全機器到機器通訊。
在這個項目中,我使用 Password credentials
受權類型進行用戶受權(由於它僅由本機應用程序UI使用),而且 Client Credentials
用做微服務受權的受權類型。
Spring Cloud Security提供方便的註釋和自動配置,使服務器和客戶端都能輕鬆實現。你能夠在文檔中瞭解有關它的更多信息, 並檢查Auth Server代碼中的配置詳細信息 。
從客戶端來看,一切都與傳統的基於會話的受權徹底相同。你能夠從Principal
請求中檢索 對象,使用基於表達式的訪問控制和@PreAuthorize
註釋檢查用戶角色和其餘內容 。
PiggyMetrics中的每一個客戶端(賬戶服務,統計服務,通知服務和瀏覽器)都有一個範圍: server
用於後端服務, ui
- 用於瀏覽器。所以,咱們還能夠保護控制器免受外部訪問,例如:
@PreAuthorize("#oauth2.hasScope('server')")
@RequestMapping(value = "accounts/{name}", method = RequestMethod.GET)
public List<DataPoint> getStatisticsByAccountName(@PathVariable String name) {
return statisticsService.findByAccountName(name);
}
如你所見,有三種核心服務,它們將外部API暴露給客戶端。在現實世界的系統中,這個數字能夠很是快速地增加,而且整個系統的複雜性也會增長。實際上,渲染一個複雜的網頁可能涉及數百種服務。
理論上,客戶端能夠直接向每一個微服務發出請求。但顯然這個選項存在挑戰和侷限,例如必須知道全部端點地址,分別對每一個信息和平執行http請求,在客戶端合併結果。另外一個問題是非網絡友好協議,可能在後端使用。
一般,更好的方法是使用API網關。它是進入系統的單一入口點,用於經過將請求路由到適當的後端服務或經過調用多個後端服務並聚合結果來處理請求 。此外,它還可用於身份驗證,壓力測試,服務遷移,靜態響應處理,主動流量管理。
Netflix開源了 這樣的優質服務,如今有了Spring Cloud,咱們能夠經過一個@EnableZuulProxy
註釋啓用它 。在這個項目中,我使用Zuul存儲靜態內容(UI應用程序)並將請求路由到適當的微服務。如下是Notification服務的簡單基於前綴的路由配置:
zuul:
routes:
notification-service:
path: /notifications/**
serviceId: notification-service
stripPrefix: false
這意味着全部以請求開頭的請求 /notifications
都將路由到Notification服務。能夠看到,沒有硬編碼的地址。Zuul使用 服務發現 機制來定位Notification服務實例以及 Circuit Breaker和Load Balancer。
另外一種衆所周知的架構模式是Service Discovery。它容許自動檢測服務實例的網絡位置,這些服務實例可能因爲自動擴展,故障和升級而動態分配地址。
服務發現的關鍵部分是註冊表。我在這個項目中使用了Netflix Eureka。當客戶端負責肯定可用服務實例的位置(使用註冊服務器)並在它們之間加載平衡請求時,Eureka是客戶端發現模式的一個很好的例子。
使用Spring Boot,你能夠輕鬆地使用spring-cloud-starter-eureka-server
依賴項, @EnableEurekaServer
註釋和簡單配置屬性構建Eureka Registry 。
經過@EnableDiscoveryClient
註釋和 bootstrap.yml
應用程序名稱啓用客戶端支持 :
spring: application: name: notification-service
如今,在應用程序啓動時,它將向Eureka Server註冊並提供元數據,例如主機和端口,運行情況指示器URL,主頁等.Eureka從屬於服務的每一個實例接收消息。若是故障超過可配置的時間表,則實例將從註冊表中刪除。
此外,Eureka提供了一個簡單的界面,你能夠在其中跟蹤正在運行的服務和可用實例的數量: http://localhost:8761
Netflix OSS提供了另外一套很棒的工具。
Ribbon是一個客戶端負載均衡器,可讓你對HTTP和TCP客戶端的行爲進行大量控制。與傳統的負載均衡器相比,每次線上調用都不須要額外的跳過 - 你能夠直接聯繫所需的服務。
開箱即用,它自己與Spring Cloud和Service Discovery集成。 Eureka Client 提供可用服務器的動態列表,所以Ribbon能夠在它們之間取得平衡。
Hystrix是Circuit Breaker模式的實現 ,它能夠控制經過網絡訪問的依賴關係的延遲和故障。主要思想是在具備大量微服務的分佈式環境中中止級聯故障。這有助於快速失敗並儘快恢復 - 自我修復的容錯系統的重要方面。
除了斷路器控制以外,使用Hystrix還能夠添加一個回退方法,以便在主命令失敗時獲取默認值。
此外,Hystrix會爲每一個命令生成執行結果和延遲的指標,咱們可使用它來 監控系統行爲。
Feign是一個聲明式HTTP客戶端,可與Ribbon和Hystrix無縫集成。實際上,經過一個 spring-cloud-starter-feign
依賴關係和 @EnableFeignClients
註釋,你能夠擁有一整套負載均衡器,斷路器和HTTP客戶端,並具備合理的即用型默認配置。
如下是賬戶服務的示例:
@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
statistics-service
感謝Eureka的自動發現(但顯然你能夠訪問具備特定URL的任何資源)在此項目配置中,每一個帶有Hystrix的微服務都經過Spring Cloud Bus(使用AMQP代理)將指標推送到Turbine。Monitoring項目只是一個帶有Turbine 和 Hystrix Dashboard的小型Spring啓動應用程序 。
讓咱們看看咱們在負載下的系統行爲:賬戶服務調用統計服務,它響應模仿延遲。響應超時閾值設置爲1秒。
0 ms delay | 500 ms delay | 800 ms delay | 1100 ms delay |
表現良好的系統。吞吐量約爲22個請求/秒。統計服務中的活動線程數量不多。中位服務時間約爲50毫秒。 | 活動線程的數量正在增加。咱們能夠看到紫色線程池拒絕的數量,所以大約有30-40%的錯誤,但電路仍然關閉。 | 半開狀態:失敗命令的比例超過50%,斷路器啓動。睡眠窗口的時間量後,下一個請求經過。 | 100%的請求失敗。電路如今永久開放。睡眠時間後重試不會再次關閉電路,由於單個請求太慢。 |
在嘗試識別分佈式環境中的問題時,集中日誌記錄很是有用。Elasticsearch,Logstash和Kibana堆棧使你能夠輕鬆搜索和分析日誌,利用率和網絡活動數據。個人其餘項目中描述隨時可用的Docker配置 。
高級安全配置超出了此概念驗證項目的範圍。要更真實地模擬真實系統,請考慮使用https和JCE密鑰庫來加密微服務密碼和配置服務器屬性內容( 有關詳細信息,請參閱 文檔)。
與部署總體應用程序相比,部署微服務具備相互依賴性,這是一個複雜得多的過程。擁有一個徹底自動化的基礎設施很是重要。咱們能夠經過持續交付方法得到如下好處:
這是一個簡單的Continuous Delivery工做流程,在此項目中實現:
在此 配置中,Travis CI爲每一個成功的Git推送構建標記圖像。所以latest
,Docker Hub上的每一個微服務始終都有一個 映像,舊的映像使用Git commit hash進行標記。若是須要,能夠輕鬆部署其中任何一個並快速回滾。
這真的很容易,我建議你試試。請記住,你要啓動8個Spring Boot應用程序,4個MongoDB實例和RabbitMq。確保4 Gb
的計算機上有 RAM。你始終能夠經過網關,註冊表,配置,身份驗證服務和賬戶服務運行重要服務。
CONFIG_SERVICE_PASSWORD
, NOTIFICATION_SERVICE_PASSWORD
, STATISTICS_SERVICE_PASSWORD
, ACCOUNT_SERVICE_PASSWORD
, MONGODB_PASSWORD
在此模式下,全部最新圖像都將從Docker Hub中提取。只需複製 docker-compose.yml
並點擊便可 docker-compose up -d
。
若是你想本身構建映像(例如,在代碼中進行一些更改),則必須使用Maven克隆全部存儲庫並構建工件。而後,運行docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d
docker-compose.dev.yml
繼承 docker-compose.yml
在本地構建映像的額外可能性,並公開全部容器端口以便於開發。
全部Spring Boot應用程序都須要運行 Config Server 才能啓動。可是咱們能夠同時啓動全部容器,由於 fail-fast
Spring Boot屬性和 restart: always
docker-compose選項。這意味着全部相關容器將嘗試從新啓動,直到Config Server啓動並運行。
此外,Service Discovery機制在全部應用程序啓動後須要一些時間。在實例,Eureka服務器和客戶端在其本地緩存中都具備相同的元數據以前,客戶端沒法發現任何服務,所以可能須要3次偵聽。默認偵聽時間爲30秒。
原文標題《Microservice Architectures With Spring Cloud and Docker》
做者:Alexander Lukyanchikov
譯者:我就靜靜地看
不表明雲加社區觀點,更多詳情請查看原文連接
問答
微服務架構的優點與不足?
相關閱讀
Web應用程序開發指南
深度學習和神經網絡的六大趨勢
如何編寫本身的jQuery插件?
【每日課程推薦】機器學習實戰!快速入門在線廣告業務及CTR相應知識
此文已由做者受權騰訊雲+社區發佈,更多原文請點擊
搜索關注公衆號「雲加社區」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!