貝殼金控趙文樂:基於 Spring Cloud 的服務治理實踐

weixin_34127717發表於2018-05-24

大家好,我是來自貝殼金控的趙文樂,目前主要從事架構方面的工作。今天我想跟大家分享《基於 Spring Cloud 的服務治理實踐》。我先簡單向大家介紹一下服務治理的概念,然後介紹實際案例中的實踐。

\\

服務治理的範圍及原因

\\

b8fc504f580207eb92c7756db65a42c3.jpeg

\\

上圖是我簡單製作的「服務治理實踐過程中遇到的問題和解決方法」,不是非常完全,但也可以代表服務治理的大致範圍。

\\

服務治理的範圍

\\

在服務治理方面,我們需要解決四個方面的問題:

\\
  1. 服務質量。包括:服務列表、服務效能KPI 、鏈路監控、依賴監控、故障管理與報警系統等;\\t
  2. 線上治理,包括服務發現(讓客戶端能夠發現這個服務)、服務排程(包括客戶端和服務端的負載均衡、服務路由、升降級熔斷和監控)和配置管理;\\t
  3. 線下治理,包括開發工具、上線審批、下線通知、服務文件;\\t
  4. 運維生態。如容器雲、使用者角色許可權管理、服務的流程審批。\

為什麼要進行服務治理?

\\

3246c0afb466d0f9d8fea521e6849223.jpeg

\\
  • 當服務越來越多時,過去簡單記錄服務的 end point就越來越複雜。所以註冊中心是我們需要做的第一步,在這之後,才是服務發現和客戶端定製;\\t
  • 當服務開始越來越複雜,我們就要依賴於管理服務。如果架構師不瞭解系統裡所有服務之間的依賴關係,則需要藉助框架自動畫出依賴關係並予以管理;\\t
  • 當呼叫越來越多時,我們需要增加監控、容量規劃以及度量;\\t
  • 當依賴變得複雜時,除了瞭解服務的依賴關係,還要動態的察覺依賴;\\t
  • 一般情況下,下層服務如果反調上層服務,會造成迴圈依賴,需要SOA做到服務之間互相溝通,使管理更加容易;\\t
  • 如果想要防止文件變得混亂,就需要更集中化的文件管理,讓大家能夠搜到、看到所有的服務的文件;\\t
  • 如果大家都可以公開呼叫內部服務,那麼就會出現安全問題;\\t
  • 質量問題也會難以保障,需要有非常好的服務監控;\\t
  • 當呼叫多個服務時,需要做服務聚合。特別是當我們依賴於服務編排時,如果用框架來做會更方便。\

服務拆分和治理的原則

\\

服務拆分的原則

\\

c0660e46af75d313cf3e9df466cdffaf.jpeg

\\

當我們在說微服務時,我們是在說:到底微服務的顆粒度要做到多細或多粗。這就需要我們先定義服務的不同分類,可以按照不同的維度來做。如服務業務、服務流程或不同的業務域,這是第一種流程服務,即滿足最高層服務的流程。在流程服務下還會出現組合服務,會呼叫多個其他服務進行封裝組合。再下面還會有平臺服務 —— 在某業務域下的核心服務。最後是基礎服務,它通常沒有特別的業務含義,是比較通用的服務。

\\

同時,我們也可以根據服務的屬性來分類:

\\
  1. 穩定服務和不穩定/ 易變服務需要隔離;\\t
  2. 核心服務和非核心服務需要隔離;\\t
  3. 非功能服務和功能服務。非功能服務通常更容易複用,會把它放在最底層,由不同的服務來呼叫;\\t
  4. 高可用服務和容錯服務。有些服務能容忍一定錯誤率,這樣的服務不能和高可用服務部署在一起。\

63462e939f49670cb398f335c14db6de.jpeg

\\

所以,我們可以按照以上原則做系統分解:

\\
  • 不同的業務域劃分大的業務系統,每個業務呼叫資料量最大的需要拆分;\\t
  • 風險高、頻率高、經常更新的需要拆分的;\\t
  • 經常會被複用的底層服務需要拆分;\\t
  • 服務需要專業技能、專業團隊,特別是技術棧不統一時進行拆分。\

服務設計原則

\\

56ab9a7ef66f31ffdee27306168ff5a0.jpeg

\\

服務設計原因包括:

\\
  • 服務無狀態,冪等性。在設計微服務時,一般都會從領域模型。基於這些領域來驅動微服務REST API的設計;\\t
  • 服務業務隔離,領域驅動( Domain Driven Design );\\t
  • 服務契約驅動( Design by Contract )。先定義介面,再去做服務的實現;\\t
  • 服務資源隔離(資料庫,執行緒池等)。如果不隔離服務的資料庫,就很難知道有沒有其他服務在呼叫我們的資料庫,至少資料庫的使用者是需要隔離,不同使用者要有不同的許可權;\\t
  • 故障可隔離(熔斷機制)。Spring Cloud裡有Hystrix框架就可以很好的解決這個問題。\

服務治理原則包括:

\\
  • 服務SLA;\\t
  • 服務需自治;\\t
  • 服務可開關,降級,限流,動態調整負載路由;\\t
  • 服務可監控,可統計,提供Metrics和Health Check( Metrics Driven Design );\\t
  • 服務文件和版本管理;\\t
  • 服務許可權控制;\\t
  • 服務呼叫鏈可監控。\

Spring Cloud的服務治理

\\

027b05d40f72289b60565f374b399128.jpeg

\\

Spring Cloud 元件

\\

上圖中比較核心的組建包括:

\\
  • 服務註冊提供很多選型。預設是Eureka,還支援Consul和Zookeeper服務註冊;\\t
  • 服務呼叫,REST API通常用Feign Client做服務呼叫,整合客戶端的負載均衡,所以Feign Client在服務治理中非常重要;\\t
  • 服務路由和服務過濾,在Spring Cloud提供的route API、gateway之類的工具;\

其他還包括:

\\
  • 服務監控,在 Spring Cloud環境下用的較多的是Hystrix —— 監控控制檯,整合的Turbine可以做跨叢集的監控;\\t
  • 配置中心,Spring Cloud預設提供的配置管理是通過地址檔案進行管理,也支援諸如Zookeeper之類配置中心;\\t
  • 安全控制整合SpringSecurity,它本身不是屬於Spring Cloud的範疇,但會提供SpringSecurity Starter,幫助我們快速的建立許可權管理;\\t
  • 用 Spring Cloud Sleuth做分散式的鏈路監控,整合Zipkin之類的框架。\

Spring Cloud 存在的問題和痛點

\\

66e5c531ffda1918009a4320834acd27.jpeg

\\
  1. 配置管理。Spring Cloud的配置管理比較簡陋,沒有特別好的配置管理中心,也沒有共享配置。另外,Spring Cloud 配置不支援灰度;\\t
  2. 閘道器(API Gateway)。閘道器需要做很多二次開發,沒有動態路由;同時,Zuul做不了服務編排,而在市場上也沒有一個很好的服務編排的框架;\\t
  3. 服務跟蹤。Sleuth框架不成熟。如果跟一些比較成熟的APM框架相比,它是非常欠缺的;\\t
  4. UI。spring cloud 的UI介面非常分散,像Hystrix、eureka、tubine、zipkin都有自己的介面。但這些缺乏集中的管理,使用者體也普遍比較差、感覺比較簡單,跟商業級的服務治理平臺無法相比。\

如何改善

\\

更換配置中心。攜程的Apollo是一個更好的選擇。它裡面的很多功能都是原生Spring Cloud配置中心不支援的。所以建議大家嘗試一下比較成熟的配置中心。

\\

e097a0575fe1b2e0151283a57ff6e5db.jpeg

\\

因為 API Gateway在Spring Cloud中沒有操作介面,所以我們就為之定製了專屬介面,讓它能夠管理不同的路由規則。我們還開發了一系列Filter,可以在API Gateway裡做簽名檢查和解密。同時,我們還整合了自己的賬戶系統和單點登入,支援不同的登入方式。

\\

除此之外,我們整合了使用者中心( Accountservice )。因為當 API Gateway開放給渠道使用者或合作伙伴使用者時,通常沒有互動,所以我們就需要通過引數的自動抓取匹配使用者,據此判斷這個使用者是否已經註冊。如果還未註冊,我們就會自動註冊。同時,當一個潛在使用者使用我們系統、呼叫API時,我們就可以通過這種方式把硬體指紋記錄下來,後臺會給這些使用者打標籤,我們就可以針對這些使用者做push等營銷手段。

\\

最後,還有一些前置Filter用於抽取資料。當API請求時,會非同步通過日誌抽取報文做資料清洗,通過ETL寫到資料倉儲裡。

\\

API gateway的動態路由

\\

0973a49c5aead99ff09064bb9719400c.jpeg

\\

舉個例子,比如我們把年齡小於30歲的男性路由到一個不同的endpoint ,我們在這過程中會在請求頭、請求引數或請求頭中通過Json Parse抽取引數和資料轉換。我們可以從body裡第一個customer物件的ID得到uid,之後儲存到上下文中,輸出到output,當我們指定endpoint為另外一個URL時把UID這個引數傳過去。

\\

還有一種是報文的轉換,即Payload Transformation。這個技術其實在很久以前就已經存在了,在ESB、SOAP時代,我們通常會利用XML來做報文的轉換。所以現在通常用來做報文轉換的工具是Json、Json Paser、Velocity Template、FreeMarker等。還有一些協議的轉換,我們內部有很多API都是基於dubbo或者是其他的一些RPC協議。所以當收到外部REST API請求時,我們會做一個協議、格式的轉換。

\\

f60befa1c054dd77338db925bb46eb50.jpg

\\

在上圖中,入參是比較複雜的Json,我們通過Input Mapping模板上邏輯輸出變數,嵌入到另外的Json物件中。如果我們在內部有一套比較標準的API,可以通過這種方式適配到外部不同的API。這樣便整合了規則引擎,可以做一些比較基本的服務編排。

\\

一體化的服務監控和跟蹤

\\

cb92b409973d79865377e2a3ffea279e.jpg

\\

在Spring Cloud裡提供了很多不同的服務監控工具,利用這些工具可以做服務的業務監控和埋點,來收集各種Metrics。當我們傳送訊息時,我們會在適當的地方做埋點,收集資料,最後再把這些整合起來,做報表展示和告警。所以整個這套服務監控和跟蹤都是一體化的。

\\

875682e2cba1e4a01992a708eb42308d.jpg

\\

我們在做中介軟體埋點時,可以有許多的選擇,比如JDK proxy、http client、Servlet filters、Spring MVC handler都可以新增埋點,但我們更多會在Feign Client提供一些攔截器,當服務呼叫時,會有一些不同的event。

\\

在DB裡,我們用的比較多的是Druid datasource filter,它提供了很多擴充套件,我們可以在這裡邊做SQL查詢的埋點,記錄每條SQL的響應時間和呼叫頻次。同時,Mybatis也可以做埋點,定製一些外掛。

\\

服務監控的整體架構

\\

64fe1c8ee9be478b056ffc2d06181716.jpg

\\

過去我們使用日誌做服務監控的資料收集,大家都知道也有不少的服務監控都是基於上報的API。但我們通過日誌的方式收集資料對應用的效能比較友好,不會因為我們埋點影響到業務。同時,耦合度也比較低,只是分析度量資料。通過不同的Instruments寫到日誌裡。最後通過Logstash到Kafka進入ElasticSearch,基於這些查詢可以快速生成簡單的報表。

\\

7441fb02c5d1b5e7c9971cded41f283f.jpeg

\\

以上所說的內容,如果都只是停留在框架級別,使用者和程式設計師根本看不到服務治理的概念。所以我們做了一套服務治理平臺,可以看到所有服務治理內容。同時,我們還把配置中心嵌到了服務治理平臺中,將服務閘道器管理、Rabbit MQ訊息佇列管理、通過訊息佇列業務ID查詢訊息軌跡以及一些專案管理相關的離線服務治理等功能整合在一起。

\\

Q \u0026amp; A

\\

問:下層服務和上層服務指的是什麼?

\\
\

答:所謂的下層服務,就是底下平臺級的服務。比如你有一個發簡訊的服務,如果這個服務跟你的賬戶體系耦合在一起,它就是反向呼叫,如果在簡訊服務裡需要到會員中心獲取手機號,這就是不合理的設計,就是下層服務調上層服務的例子。

\
\\

問:服務呼叫是每個服務各自寫一個FeignClient,還是由服務方提供統一的jar包?

\\
\

答:我們現在做法是:在定義服務介面時,這個服務介面就是FeignClient,然後把服務介面和它領域的物件封裝成統一的jar包,作為服務方提供。之後,客戶端用它來呼叫就可以了。在呼叫過程中,框架裡的攔截器會做埋點、注入及監控的工作。

\
\\

問:老的服務如何呼叫FeignClient?

\\
\

答:用延伸註解來實現。FeignClient在Spring Cloud用的是比較新的OpenFeign註解,支援一些特殊功能。比如插入自己的http client和做很多攔截器,老的FeignClient不是很友好,而且它跟Spring mvc的註解也不一致,但是作為一個很老的服務,如果要呼叫FeignClient的話,我們通常會把所有FeignClient用到的class打成一個大的jar包,為這些老的服務實現呼叫。

\
\\

問:如果有機會是不是直接選擇自研好一點?

\\
\

答:作為開發人員或架構師,每個人都想自研,確實也有很多團隊自己做自研框架。但自研的問題是從入門到融會貫通的時間。雖然Spring Cloud現在十分簡陋,但上手就可以用。如果在整個團隊裡都用Spring Cloud,可以很快地做一些簡單的服務治理,然後再慢慢的優化這個過程。還有一個原因,Spring Cloud在行業裡的接受度比較高,大家的學習曲線比較短,通常自研的框架很多工程師可能不太接受或不太信任。

\

相關文章