簡介
這是一款概念性的應用程式,基於Spring Boot,Spring Cloud和Docker 簡單演示了微服務的架構模式,順便說一句,它還有一個非常漂亮整潔的使用者介面。下面是它的介面演示:
功能服務
PiggyMetrics被分解為三個核心微服務。這些服務都是圍繞某些業務能力組織的可獨立部署的應用程式。
賬戶服務
包含一般使用者輸入邏輯和驗證:收入/費用專案,儲蓄和帳戶設定。
MethodPathDescriptionUser authenticatedAvailable from UI
GET/accounts/{account}獲取指定的帳戶資料
GET/accounts/current獲取當前帳戶資料××
GET/accounts/demo獲取模擬賬戶資料(預填收入/費用專案等) ×
PUT/accounts/current儲存當前帳戶資料××
POST/accounts/註冊新帳號 ×
統計服務
對主要統計引數執行計算,併為每個帳戶的時間序列。資料點包含基準貨幣和時間段的值。此資料用於跟蹤帳戶生命週期中的現金流動動態(尚未在UI中實現的花式圖表)。
MethodPathDescriptionUser authenticatedAvailable from UI
GET/statistics/{account}獲取指定的帳戶統計資訊
GET/statistics/current獲取當前帳戶統計資訊××
GET/statistics/demo獲取模擬帳戶統計資訊 ×
PUT/statistics/{account}建立或更新指定帳戶的時間序列資料點
通知服務
儲存使用者聯絡資訊和通知設定(如提醒和備份頻率)。計劃工作人員從其他服務收集所需的資訊,並向訂閱的客戶傳送電子郵件。
MethodPathDescriptionUser authenticatedAvailable from UI
GET/notifications/settings/current獲取當前的帳戶通知設定××
PUT/notifications/settings/current儲存當前帳戶通知設定××
小結:
每個微服務都有自己的資料庫,因此沒有辦法繞過API和直接訪問資料庫。
在這個專案中,使用MongoDB作為每個服務的主資料庫。它是支援多種程式語言永續性架構(包括最適合服務需求的資料庫型別)。
Service-to-service的通訊是相當簡單的:各個微服務之間的通訊只使用同步的REST API。在現實世界中通常的做法是使用互動風格的組合。例如,執行同步GET請求以檢索資料,並通過訊息代理使用非同步方法進行建立/更新操作,以便分離服務和緩衝訊息,這為我們帶來了一致性。
基礎服務設施
在分散式系統中有一些常見的架構,這可以幫助我們理解核心服務的工作原理。Spring Cloud提供了強大的工具來增強基於Spring Boot的應用程式,以此來實現這些架構。
Config service
Spring Cloud Config是用於分散式系統的水平可擴充套件的集中式配置服務。支援本地儲存、Git和Subversion。
在這個專案中,使用native profile,它從本地類路徑載入配置檔案。可以檢視shared在Config服務資源中的目錄。現在,當通知服務請求其配置時,配置服務以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
1
2
3
4
5
6
7
使用Spring Cloud Config,可以動態地更新配置。
例如,EmailService bean已註釋@RefreshScope。這意味著,可以更改電子郵件文字和主題,而不需要重新部署啟動通知服務。
首先,在Config伺服器中更改所需的屬性。然後,對Notification服務執行重新整理請求:curl -H "Authorization: Bearer #token#" -XPOST
此外,也可以使用Repository webhooks自動執行此過程
小結:
動態更新有一些限制。@RefreshScope不與@Configuration類一起使用,並且不影響@Scheduled方法
fail-fast屬性意味著Spring Boot如果它無法連線到Config
Service就將啟動失敗,這在批量啟動時非常有用。
安全注意事項請往下看
Auth service
授權的責任完全抽取到單獨的伺服器,它為後端資源服務授予OAuth2令牌。Auth伺服器用於使用者授權以及在外圍內的安全的機器對機器通訊。
在這個專案中,我使用Password credentials授權型別的使用者授權(因為它只由本地PiggyMetrics UI使用)和Client Credentials授予微服務許可權。
Spring雲安全提供了方便的註釋和自動配置,使得從伺服器端和客戶端端都很容易實現。您可以在文件中瞭解更多資訊,並在Auth Server程式碼中檢查配置詳細資訊。
從客戶端,一切工作與傳統的基於會話的授權完全相同。您可以Principal從請求中檢索物件,檢查使用者的角色和其他使用基於表示式的訪問控制和@PreAuthorize註釋的東西。
PiggyMetrics(帳戶服務,統計服務,通知服務和瀏覽器)中的每個客戶端都有一個範圍:server用於後端服務,以及ui- 用於瀏覽器。因此,我們還可以保護控制器免受外部訪問,例如:
@PreAuthorize("#oauth2.hasScope('server')")@RequestMapping(value ="accounts/{name}", method = RequestMethod.GET)public List getStatisticsByAccountName(@PathVariableString name) { return statisticsService.findByAccountName(name);}
1
2
3
4
5
API Gateway
可以看到,有三個核心服務,它們向客戶端公開外部API。在現實世界的系統中,這個數字可以快速增長以及整個系統的複雜性。實際上,上百個服務可能涉及到渲染一個複雜的網頁。
在理論上,客戶端可以直接向每個微伺服器發出請求。但是顯然,這個選項有挑戰和限制,如需要知道所有端點地址,分別執行每個資訊的http請求,在客戶端合併結果。另一個問題是非web友好的協議,可能在後端使用。
通常一個更好的方法是使用API閘道器。它是進入系統的單個入口點,用於通過將它們路由到適當的後端服務來處理請求,或者通過呼叫多個後端服務並聚合結果。此外,它可以用於身份驗證,洞察,壓力和金絲雀測試,服務遷移,靜態響應處理,主動流量管理。
Netflix開啟了這樣一個邊緣服務,現在使用Spring Cloud,我們可以使用一個@EnableZuulProxy註釋啟用它。在這個專案中,我使用Zuul來儲存靜態內容(ui應用程式),並將請求路由到適當的微服務。這是一個簡單的基於字首的路由配置Notification服務:
zuul: routes: notification-service: path:/ notifications /** serviceId:notification-service stripPrefix:false
1
2
3
4
5
6
這意味著所有開始的請求/notifications都將路由到Notification服務。沒有硬編碼的地址,你可以看到。Zuul使用服務發現機制來定位通知服務例項,以及斷路器和負載平衡器,如下所述。
Service discovery
另一個公知的架構模式是服務發現。它允許自動檢測服務例項的網路位置,由於自動擴充套件,故障和升級,可能會動態分配地址。
服務發現的關鍵部分是登錄檔。我在這個專案中使用Netflix Eureka。當客戶端負責確定可用服務例項(使用登錄檔伺服器)和負載平衡請求的位置時,Eureka是客戶端發現模式的一個很好的例子。
使用Spring Boot,您可以輕鬆地使用spring-cloud-starter-eureka-server依賴關係,@EnableEurekaServer註釋和簡單配置屬性來構建Eureka登錄檔。
支援@EnableDiscoveryClient註釋的客戶端支援bootstrap.yml應用程式名稱:
spring:
application:
name:notification-service
1
2
3
現在,在應用程式啟動時,它將註冊到Eureka伺服器並提供後設資料,如主機和埠,執行狀況指示器URL,主頁等。Eureka從屬於一個服務的每個例項接收心跳訊息。如果心跳故障切換到可配置的時間表,則例項將從登錄檔中刪除。
負載均衡器,斷路器和Http客戶端
Netflix OSS提供了另一個偉大的工具集。
Ribbon
Ribbon是一個客戶端負載均衡器,它為您提供了對HTTP和TCP客戶端行為的大量控制。與傳統的負載均衡器相比,每個線上呼叫不需要額外的跳躍 - 您可以直接聯絡所需的服務。
開箱即用,它與Spring Cloud和服務發現本身整合。Eureka Client提供了可用伺服器的動態列表,以便Ribbon可以在它們之間進行平衡。
Hystrix
Hystrix是斷路器模式的實現,它提供了對通過網路訪問的依賴性的延遲和故障的控制。主要思想是在具有大量微服務的分散式環境中停止級聯故障。這有助於快速失敗,並儘快恢復 - 自愈的容錯系統的重要方面。
除了斷路器控制,使用Hystrix,您可以新增一個後備方法,在主命令失敗的情況下呼叫該方法以獲取預設值。
此外,Hystrix生成每個命令的執行結果和延遲的指標,我們可以用它來監視系統行為。
Feign
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);}
1
2
3
4
5
6
7
你需要的只是一個介面
你可以用@RequestMapping在Spring MVC控制器和Feign方法之間共享部分
上面的示例指定只需要的服務id -
statistics-service,由於通過Eureka自動發現(但顯然,您可以訪問任何資源與特定的網址)
監視儀表板
在這個專案配置中,Hystrix的每個微服務通過Spring Cloud Bus(使用AMQP代理)將指標推送到Turbine。監控專案只是一個小的Spring啟動應用程式與渦輪和Hystrix儀表板。
看下面如何讓它執行。
讓我們看看我們的系統在負載下的行為:帳戶服務呼叫統計服務,它的響應具有不同的模仿延遲。響應超時閾值設定為1秒。
0 ms delay500 ms delay800 ms delay1100 ms delay
表現良好的系統。吞吐量約為22請求/秒。統計服務中的活動執行緒數較少。中位服務時間約為50 ms。活動執行緒的數量在增加。我們可以看到紫色執行緒池拒絕的數量,因此約30-40%的錯誤,但電路仍然關閉。半開狀態:故障命令的比率大於50%,斷路器啟動。在睡眠視窗的時間後,下一個請求被允許通過。100%的請求失敗。電路現在永久開啟。在睡眠時間後重試不會再次閉合電路,因為單個請求太慢。
日誌分析
當嘗試在分散式環境中識別問題時,集中式日誌記錄可能非常有用。Elasticsearch,Logstash和Kibana堆疊使您可以輕鬆搜尋和分析您的日誌,利用率和網路活動資料。我的其他專案中描述的即開即用 Docker配置。
安全
高階安全配置超出了此概念驗證專案的範圍。對於真實系統的更真實的模擬,考慮使用https,JCE金鑰庫加密微服務密碼和配置伺服器屬性內容(有關詳細資訊,請參閱文件)。
基建自動化
部署微服務及其相互依賴性,比部署單片應用程式要複雜得多。擁有完全自動化的基礎設施非常重要。我們可以通過持續交付方法實現以下優勢:
隨時釋放軟體的能力
任何構建可能最終都是釋出
構建工件一次 - 根據需要部署
這裡是一個簡單的連續交付工作流,在這個專案中實現:
在此配置中,Travis CI為每個成功的git push建立標記的映像。因此,latest對於Docker Hub上的每個微服務總有影象,並且用git提交雜湊標記的舊影象。它很容易部署任何一個,並快速回滾,如果需要。
如何執行所有的東西?
記住,你要啟動8個Spring Boot應用程式,4個MongoDB例項和RabbitMq。確保您4 Gb的計算機上有可用的RAM。您可以始終執行重要的服務,雖然:閘道器,登錄檔,配置,Auth服務和帳戶服務。
在你開始之前
-
安裝Docker和Docker Compose。
-
出口環境變數: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具有在本地構建映像的額外可能性,並公開所有容器埠以方便開發。
重要埠
http://DOCKER-HOST:80 - Gatewayhttp://DOCKER-HOST:8761 - Eureka Dashboardhttp://DOCKER-HOST:9000/hystrix - Hystrix Dashboardhttp://DOCKER-HOST:8989 - Turbine stream (source for the Hystrix Dashboard)http://DOCKER-HOST:15672 - RabbitMq management (default login/password: guest/guest)
1
2
3
4
5
小結
所有Spring Boot應用程式都需要執行Config Server進行啟動。但是我們可以同時啟動所有容器,因為fail-fastSpring Boot屬性和docker restart: always-compose選項。這意味著所有依賴的容器將嘗試重新啟動,直到Config Server啟動並執行。
此外,在所有應用程式啟動後,服務發現機制需要一些時間。任何服務都不可用於客戶端發現,直到例項,Eureka伺服器和客戶端都在其本地快取中具有相同的後設資料,因此可能需要3個心跳。預設心跳週期為30秒。