詳解Spring Cloud和Docker的微服務架構

HitTwice發表於2018-07-04


  Spring Cloud和Docker的微服務架構

  ====

  本文透過以Spring Boot,Spring Cloud和Docker構建的一個應用程式為例,幫助大家理解微服務架構模式。

  本文的程式碼儲存在 上,映象檔案儲存在 docker hub 上。可以透過一條命令啟動整個系統。

  這個應用程式提供了:處理個人財務,組織收入和支出,管理儲蓄,分析統計,並建立簡單的預測等功能。

  功能服務

  整體應用被分解成三個核心的微服務。這些微服務是圍繞某些業務功能進行組織,可獨立部署的應用程式。

服務間關係

  Account Service(賬戶服務)

  包含使用者的輸入邏輯和驗證:收入/支出,儲蓄和賬戶設定。

  Statistics Service(統計服務)

  對主要統計引數執行計算,並獲取每個帳戶的時間線。資料點包含標準化為基本貨幣和時間段的值。這些資料可用於追蹤賬戶一生中的現金流動態

  Notification Service(通知服務)

  儲存使用者聯絡資訊和訊息設定(比如提醒和備份頻率),定時器從其他伺服器上收集所需的資訊並透過 emial 傳送給訂閱者。

  注意

  ·每個微服務都有自己的資料庫,不能繞過微服務提供的 API 直接訪問微服務的持久化資料。

  ·這個例子中我採用 mongoDB 作為每個微服務的資料庫,使用者可以根據微服務的型別選擇合適的資料庫。

  ·微服務和微服務間的採用同步的 REST API 進行通訊,通常的做法是採用互動風格進行通訊,比如:透過同步的 GET 請求來檢索資料,透過Message Broker使用非同步方法來建立/更新操作,以便分離服務和緩衝區訊息,目標是實現最終一致性。

  Infrastructure Services(基礎設施服務)

  分散式系統中有許多共同的模式,可以幫助我們描述核心服務。提供了強大的工具以幫助 spring boot 應用實現這些模式,下面會做一些簡單的介紹:

系統架構

  Config Service(配置服務)

  是分散式系統中的集中式配置服務。

  在這個專案中,我使用 native profile 從本地的 classpath 上載入配置檔案,你可以在 shared 目錄下面檢視 config service resources。比如:當Notification-service請求它的配置資訊,配置服務會返回如下來兩個檔案:shared/notification-service.yml 和 shared/application.yml(這個檔案會被所有的應用共享).

  Client-side Usage(客戶端使用)

  只要用spring-cloud-starter-config依賴構建Spring Boot應用程式,其餘部分將自動配置

  應用中不需要其他任何內建的properties,只需要提供一個bootstrap.yml檔案,這個檔案中需要包含當前應用的名字和Config service 的url

  spring:

    application:

      name: notification-service

    cloud:

      config:

        uri:

        fail-fast: true

  spring cloud config支援動態修改 App 的配置資訊,比如: 在EmailService bean上新增@RefreshScope註解,這就意味著你可以修改 email 的正文和標題而不用重新編譯或者重啟Notification service。具體操作如下:

  1、修改config server 上相關的屬性

  2、對Notification service執行重新整理請求:

  curl -H "Authorization: Bearer #token#" -XPOST

  也可以採用自動執行這個流程

  注意

  1、動態重新整理有如下限制:@RefreshScope 註解無法在@Configuration 類和 @Scheduled 方法上生效。

  2、fail-fast屬性意味著如果服務無法連線上 config service,則服務會在啟動期間立即失敗。這在一起啟動所有服務的時候十分有用。

  Auth Service(鑑權服務)

  授權職責完全提取到單獨的伺服器,後者為後端資源服務授予OAuth2令牌。 身份驗證伺服器用於使用者授權以及在外圍進行安全的機器對機器通訊。

  在這個專案中,我使用密碼憑證作為使用者授權的授權型別(因為它只被本機應用程式UI使用),而客戶端憑證作為微服務授權的授權型別。

  Spring Cloud Security提供了便利的註釋和自動配置,使得從伺服器和客戶端都可以輕鬆實現。 您可以在文件中瞭解更多資訊,並檢視程式碼中的配置詳細資訊。

  客戶端與傳統的基於 session 的許可權驗證類似,你可以從 request 中獲取Principal物件資訊,校驗使用者的角色,使用@PreAuthorize註解進行基於正則的訪問控制。

  每個 client (account-service, statistics-service, notification-service 和 browser)都有一個 scope屬性: server :後臺服務, ui: 瀏覽器,透過scope 能防止 controller 被外部訪問:

  @PreAuthorize("#oauth2.hasScope('server')")

  @RequestMapping(value = "accounts/{name}", method = RequestMethod.GET)

  public List getStatisticsByAccountName(@PathVariable String name) {

      return statisticsService.findByAccountName(name);

  }

  API Gateway

  在這個例子中,存在三個核心服務,將外部API 暴露給客戶端,但是在現實世界中,隨著系統複雜度的增加,核心服務數也會急劇增長。可能存在一個複雜頁面,渲染這個頁面需要呼叫上百個服務。

  理論上,客戶端應該直接請求每一個微服務,但是這種方式存在很多挑戰和侷限性,比如:客戶端需要了解所有微服務的地址,為每一個資訊獨立地執行 http 呼叫,然後在客戶端 merger 這些資訊。Another problem is non-web-friendly protocols, which might be used on the backend.

  通常一個更好的實現方式是使用 API Gateway,它是一個進入系統的單入口,目的是將請求路由到合適的後臺服務或者呼叫多個後臺服務並將結果聚合返回給客戶端。API Gateway也會被用來做許可權驗證,監控,壓力測試,服務遷移,靜態響應處理和主動流量管理

  在 Spring cloud 專案中可以透過@EnableZuulProxyannotation註解使用Netflix開源的專案edge service

  在這個例子中我們使用Zuul儲存靜態內容(UI application),路由請求到合適的微服務上,下面是Notification service的路由配置:

  zuul:

      routes:

          notification-service:

              path: /notifications/**

              serviceId: notification-service

              stripPrefix: false

  這個配置意味著所有以 /notifications開頭的請求都會被路由到Notification service,Notification service 地址並沒有硬編碼,Zuul使用服務發現機制定位Notification service 例項並實現訪問的負載均衡。

  Service Discovery(服務發現)

  透過服務發現能夠自動地確定服務例項的網路位置(由於例項數擴充套件,例項失敗/更新,會導致服務例項的網路地址發生變化)

  服務發現的關鍵部分是服務註冊,在這個例子中我們使用Netflix Eureka 實現這個功能,Eureka是基於客戶端服務發現模式的一個好的例子,客戶端負責確定可用服務例項(使用註冊伺服器)的位置和負載均衡請求。

  在Spring Boot中,您可以使用spring-cloud-starter-eureka-server依賴項,透過@EnableEurekaServer註釋和簡單的配置屬性來構建Eureka Registry。

  客戶端支援需要使用@EnableDiscoveryClient註解和新增包含應用名稱的bootstrap.yml檔案

  spring:

      application:

          name: notification-service

  在應用啟動的時候,它會在Eureka Serve中註冊,並提供相關的meta-data資訊(比如:host,port,健康檢查頁,主頁等)。Eureka從微服務的每個例項接收心跳資訊,如果在約定的時間內(可配置)沒有接受到心跳資訊,這個例項就會被註冊中心移除。

  Eureka提供了一個簡單的頁面,在這個頁面上你可以檢視執行的微服務以及這些服務對應的例項

Eureka

  Load Balancer, Circuit Breaker, and Http Client(負載均衡,斷路器以及 http Client)

  Netflix OSS 提供了另外一套優秀的工具集

  Ribbon

  Ribbon是一個客戶端的負載均衡器,可以透過它控制 HTTP 和 TCP client 請求,與傳統的負載均衡器相比,每個線上呼叫不需要額外的跳躍,你可以直接聯絡所需的服務。

  Eureka本身與Spring Cloud 和 Service Discovery整合在一起,開箱即用,Eureka Client提供了一個可用服務的動態列表,Ribbon可以透過這個列表來實現負載均衡。

  Hystrix

  Hystrix是熔斷器模式的實現,透過網路訪問依賴關係來控制延遲和失敗。核心思想是在大量微服務的分散式環境中停止級聯失敗,這有助於系統儘快恢復 。

  除了提供熔斷器,Hystrix還可以新增一個fallback方法,在主命令失敗的情況下返回預設值。

  而且,Hystrix為每個命令生成執行結果和延遲的度量標準,我們可以用它來。

  Feign

  Feign是一個宣告式HTTP客戶端,與Ribbon和Hystrix無縫整合。 實際上,透過一個Spring-Cloud-Starter-Feign依賴和@EnableFeignClients批註,您可以擁有一整套負載均衡器,斷路器和HTTP客戶端,並具有合理的隨時可用的預設配置。

  下面是Account Service的一個列子:

  @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);

  }

  上面的例子指定了所需的服務id - statistics-service,依靠Eureka的自動發現

  Monitor Dashboard

  在這個專案配置中,搭載Hystrix的每個微服務都透過Spring Cloud Bus(使用AMQP代理)向Turbine推送指標。Monitoring project只是一個小型的包含和儀表板的Spring boot應用程式。

  讓我們看看不同負載下的系統行為:Account service呼叫Statistics service ,Statistics service 響應模擬不同的延遲。響應超時閾值設定為1秒。

Monitor Dashboard

  Log Analysis

  集中式日誌在分析分散式系統中存在的問題時十分有效。Elasticsearch, Logstash, 和 Kibana的技術棧讓你輕鬆搜尋和分析你的日誌,系統利用率和網路活動資料。在中可以找到相關的描述。

  Security

  高階安全配置超出了這個概念驗證專案的範圍。 要更真實地模擬真實系統,請考慮使用https和JCE金鑰庫來加密微服務密碼和配置伺服器屬性內容(請參閱文件以瞭解詳細資訊)。

  Infrastructure Automation(基礎設定自動化)

  部署相互依賴的微服務,比部署整體應用程式要複雜得多。 擁有完全自動化的基礎設施非常重要。 採用持續交付方式,我們可以獲得以下好處:

  ·隨時釋出軟體的能力。

  ·任何構建可能最終成為一個release。

  ·一次構建工件,根據需要進行部署

  這是在這個專案中實現一個簡單的持續交付工作流程:

持續交付流程

  在這個配置中,Travis CI為每個成功的Git推送建立標記的影像。 因此,Docker Hub上的每個微服務總是有最新的映象,而舊映象使用Git commit hash進行標記。 如果需要的話,部署它們很容易並且快速回滾。

  How to Run All the Things?

  你將啟動8個Spring Boot應用程式,4個MongoDB例項和RabbitMq。 確保您的機器上有4 Gb RAM。 透過Gateway,Registry,Config,Auth Service和Account Service,您始終可以執行重要的服務。

  開始之前

  ·安裝Docker和Docker Compose。

  ·匯出環境變數: CONFIG_SERVICE_PASSWORD, NOTIFICATION_SERVICE_PASSWORD, STATISTICS_SERVICE_PASSWORD, ACCOUNT_SERVICE_PASSWORD, MONGODB_PASSWORD

  Production Mode

  在這種模式下,會從 docker hub 下抓取最新的 images,只需複製docker-compose.yml並點選docker-compose up -d

  Development Mode

  如果您想自己構建映象(例如,在程式碼中進行了一些更改),則必須克隆所有repository並使用Maven構建。 然後執行

  docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

  docker-compose.dev.yml繼承了docker-compose.yml,可以在本地構建映象並公開所有容器埠以方便開發。

  ·Important Endpoints

  ·Ilocalhost:80 - Gateway

  ·Ilocalhost:8761 - Eureka Dashboard

  ·Ilocalhost:9000 - Hystrix Dashboard

  ·Ilocalhost:8989 - Turbine stream (source for Hystrix Dashboard)

  ·Ilocalhost:15672 - RabbitMq management

  注意

  所有Spring Boot應用程式都需要依賴執行中的Config Server才能啟動。 但是,我們可以同時啟動所有的容器,因為docker-compose選項始終存在Spring Boot的fail-fast和restart屬性。 這意味著所有從屬容器將嘗試重新啟動,直到配置伺服器啟動並執行。

  此外,在所有應用程式啟動之後,服務發現機制還需要一些時間,服務都不會立馬被客戶端的發現,直到例項,Eureka伺服器和客戶端在其本地快取中都具有相同的後設資料,因此可能需要3個心跳。 預設心跳週期是30秒。

  作者:韋三笑

  連結:

  來源:簡書


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31473948/viewspace-2157294/,如需轉載,請註明出處,否則將追究法律責任。

相關文章