想要設計自己的微服務?看這篇文章就對了

歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~

本文由我就靜靜地看 發表於雲+社區專欄

本文通過使用Spring Boot,Spring Cloud和Docker構建的概念驗證應用程序的示例,爲了解常見的微服務架構模式提供了一個起點。

該代碼在Github上可用,並且可以在Docker Hub上獲得圖像。只需一個命令即可啓動整個系統。

作爲這個系統的基礎,我選擇了一箇舊項目,其後端曾經是一個整體。該應用程序提供了一種處理個人財務,組織收入和支出,管理儲蓄,分析統計數據和創建簡單預測的方法。

功能服務

整體應用程序被分解爲三個核心微服務。所有這些都是可獨立部署的應用程序,圍繞某些業務功能組織。

img

帳戶服務

包含一般用戶輸入邏輯和驗證:收入/費用項目,節省和帳戶設置。

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

通知服務

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

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 × ×

注意

  • 每個微服務都有自己的數據庫,因此無法繞過API並直接訪問持久性數據。
  • 對於這個項目,我使用MongoDB作爲每個服務的主數據庫。擁有多語言持久性體系結構(以便選擇最適合服務要求的數據庫類型)也是有意義的。
  • 服務到服務通信非常簡單:微服務僅使用同步REST API進行通信。現實世界系統中的常見做法是使用交互方式的組合。例如,執行同步GET請求以檢索數據並通過Message broker使用異步方法進行創建/更新操作,以便解耦服務和緩衝消息。這帶給我們 一致性

基建服務

分佈式系統中有許多常見模式,可以幫助我們使所描述的核心服務工作。Spring cloud 提供了強大的工具,可以增強Spring Boot應用程序的行爲以實現這些模式。我簡要介紹一下:

img

配置服務

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

使用Spring Cloud Config,可以動態更改應用程序配置

例如, 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網關

如你所見,有三種核心服務,它們將外部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

另一種衆所周知的架構模式是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

img

負載均衡器,斷路器和Http客戶端

Netflix OSS提供了另一套很棒的工具。

Ribbon

Ribbon是一個客戶端負載均衡器,可以讓你對HTTP和TCP客戶端的行爲進行大量控制。與傳統的負載均衡器相比,每次線上調用都不需要額外的跳過 - 你可以直接聯繫所需的服務。

開箱即用,它本身與Spring Cloud和Service Discovery集成。 Eureka Client 提供可用服務器的動態列表,因此Ribbon可以在它們之間取得平衡。

Hystrix

Hystrix是Circuit Breaker模式的實現 ,它可以控制通過網絡訪問的依賴關係的延遲和故障。主要思想是在具有大量微服務的分佈式環境中停止級聯故障。這有助於快速失敗並儘快恢復 - 自我修復的容錯系統的重要方面。

除了斷路器控制之外,使用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);
}
  • 你需要的只是一個界面
  • 你可以在Spring MVC控制器和Feign方法之間共享 @RequestMapping
  • 以上示例指定了所需的服務ID - statistics-service感謝Eureka的自動發現(但顯然你可以訪問具有特定URL的任何資源)

監控儀表板

在此項目配置中,每個帶有Hystrix的微服務都通過Spring Cloud Bus(使用AMQP代理)將指標推送到Turbine。Monitoring項目只是一個帶有TurbineHystrix Dashboard的小型Spring啓動應用程序 。

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

img

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工作流程,在此項目中實現:

img

在此 配置中,Travis CI爲每個成功的Git推送構建標記圖像。因此latestDocker Hub上的每個微服務始終都有一個 映像,舊的映像使用Git commit hash進行標記。如果需要,可以輕鬆部署其中任何一個並快速回滾。

如何運行所有的東西?

這真的很容易,我建議你試試。請記住,你要啓動8個Spring Boot應用程序,4個MongoDB實例和RabbitMq。確保4 Gb 的計算機上有 RAM。你始終可以通過網關,註冊表,配置,身份驗證服務和帳戶服務運行重要服務。

在你開始之前

  • 安裝Docker和Docker Compose。
  • 出口環境變量: CONFIG_SERVICE_PASSWORDNOTIFICATION_SERVICE_PASSWORDSTATISTICS_SERVICE_PASSWORDACCOUNT_SERVICE_PASSWORDMONGODB_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 在本地構建映像的額外可能性,並公開所有容器端口以便於開發。

重要的終點

  • localhost:80 - 網關
  • localhost:8761 - Eureka Dashboard
  • localhost:9000 - Hystrix儀表板
  • localhost:8989 - Hystrix儀表板源
  • localhost:15672 - RabbitMq管理

注意

所有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 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社區

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章