基於Spring Boot、Spring Cloud、Docker的微服務系統架構實踐

因爲最近公司業務須要,須要搭建基於Spring Cloud的微服務系統。遍訪各大搜索引擎,發現國內資料少之又少,也難怪,國內Dubbo正統治着天下。可是,一個技術總有它的瓶頸,Dubbo也有它捉襟見肘的地方。所幸霸主Spring也推出了一整套微服務解決方案,各個子項目也巧妙地解決了分佈式系統開發過程當中的各類各樣的問題。看了不少國內的資料,最先的幾份文檔也是互相借用,恐怕到底是什麼都說不清楚了。擼主在github上面發現幾個很好的相關項目,就想翻譯來看看。這篇實際上是項目說明,可是裏面不少知識點是百度找不到的,下面就來看看吧,想要部署來看看的能夠去下載:

這個項目的名字叫:Piggy Metrics,一個供我的處理財務的解決方案。git

簡介 github

這是一款概念性的應用程序,基於Spring Boot,Spring Cloud和Docker 簡單演示了微服務的架構模式,順便說一句,它還有一個很是漂亮整潔的用戶界面。下面是它的界面演示: web

功能服務

PiggyMetrics被分解爲三個核心微服務。這些服務都是圍繞某些業務能力組織的可獨立部署的應用程序。spring

帳戶服務 docker

包含通常用戶輸入邏輯和驗證:收入/費用項目,儲蓄和賬戶設置。數據庫

統計服務 編程

對主要統計參數執行計算,併爲每一個賬戶的時間序列。數據點包含基準貨幣和時間段的值。此數據用於跟蹤賬戶生命週期中的現金流動動態(還沒有在UI中實現的花式圖表)。bootstrap

通知服務 後端

存儲用戶聯繫信息和通知設置(如提醒和備份頻率)。計劃工做人員從其餘服務收集所需的信息,並向訂閱的客戶發送電子郵件。瀏覽器

小結:

  • 每一個微服務都有本身的數據庫,所以沒有辦法繞過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
複製代碼

使用Spring Cloud Config,能夠動態地更新配置。

例如,EmailService bean已註釋@RefreshScope。這意味着,能夠更改電子郵件文本和主題,而不須要從新部署啓動通知服務。

首先,在Config服務器中更改所需的屬性。而後,對Notification服務執行刷新請求:

curl -H "Authorization: Bearer #token#" -XPOST http://127.0.0.1:8000/notifications/refresh

此外,也可使用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<DataPoint> getStatisticsByAccountName(@PathVariable String name) {
    return statisticsService.findByAccountName(name);
}
複製代碼

API Gateway

能夠看到,有三個核心服務,它們向客戶端公開外部API。在現實世界的系統中,這個數字能夠快速增加以及整個系統的複雜性。實際上,上百個服務可能涉及到渲染一個複雜的網頁。

在理論上,客戶端能夠直接向每一個微服務器發出請求。可是顯然,這個選項有挑戰和限制,如須要知道全部端點地址,分別執行每一個信息的http請求,在客戶端合併結果。另外一個問題是非web友好的協議,可能在後端使用。

一般一個更好的方法是使用API​​網關。它是進入系統的單個入口點,用於經過將它們路由到適當的後端服務來處理請求,或者經過調用多個後端服務並聚合結果。此外,它能夠用於身份驗證,洞察,壓力和金絲雀測試,服務遷移,靜態響應處理,主動流量管理。

Netflix打開了這樣一個邊緣服務,如今使用Spring Cloud,咱們可使用一個@EnableZuulProxy註釋啓用它。在這個項目中,我使用Zuul來存儲靜態內容(ui應用程序),並將請求路由到適當的微服務。這是一個簡單的基於前綴的路由配置Notification服務:

zuul:
   routes:
     notification-service:
         path:/ notifications / ** 
        serviceId:notification-service 
        stripPrefix:false
複製代碼

這意味着全部開始的請求/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
複製代碼

如今,在應用程序啓動時,它將註冊到Eureka服務器並提供元數據,如主機和端口,運行情況指示器URL,主頁等。Eureka從屬於一個服務的每一個實例接收心跳消息。若是心跳故障切換到可配置的時間表,則實例將從註冊表中刪除。

此外,Eureka提供了一個簡單的界面,您能夠跟蹤運行的服務和可用實例數: http://localhost:8761

負載均衡器,斷路器和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);
}
複製代碼
  • 你須要的只是一個接口
  • 你能夠用@RequestMapping在Spring MVC控制器和Feign方法之間共享部分
  • 上面的示例指定只須要的服務id -
  • statistics-service,因爲經過Eureka自動發現(但顯然,您能夠訪問任何資源與特定的網址)

監視儀表板

在這個項目配置中,Hystrix的每一個微服務經過Spring Cloud Bus(使用AMQP代理)將指標推送到Turbine。監控項目只是一個小的Spring啓動應用程序與渦輪和Hystrix儀表板。

看下面如何讓它運行。

讓咱們看看咱們的系統在負載下的行爲:賬戶服務調用統計服務,它的響應具備不一樣的模仿延遲。響應超時閾值設置爲1秒。

表現良好的系統。吞吐量約爲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 - Gateway
http://DOCKER-HOST:8761 - Eureka Dashboard
http://DOCKER-HOST:9000/hystrix - Hystrix Dashboard
http://DOCKER-HOST:8989 - Turbine stream (source for the Hystrix Dashboard)
http://DOCKER-HOST:15672 - RabbitMq management (default login/password: guest/guest)
複製代碼

小結

全部Spring Boot應用程序都須要運行Config Server進行啓動。可是咱們能夠同時啓動全部容器,由於fail-fastSpring Boot屬性和docker restart: always-compose選項。這意味着全部依賴的容器將嘗試從新啓動,直到Config Server啓動並運行。

此外,在全部應用程序啓動後,服務發現機制須要一些時間。任何服務都不可用於客戶端發現,直到實例,Eureka服務器和客戶端都在其本地緩存中具備相同的元數據,所以可能須要3個心跳。默認心跳週期爲30秒。

相關文章
相關標籤/搜索