javascript
基于 Spring Cloud 的服务治理实践
http://www.infoq.com/cn/articles/spring-cloud-based-service-governance
大家好,我是來自貝殼金控的趙文樂,目前主要從事架構(gòu)方面的工作。今天我想跟大家分享《基于 Spring Cloud 的服務(wù)治理實(shí)踐》。我先簡(jiǎn)單向大家介紹一下服務(wù)治理的概念,然后介紹實(shí)際案例中的實(shí)踐。
服務(wù)治理的范圍及原因
上圖是我簡(jiǎn)單制作的「服務(wù)治理實(shí)踐過程中遇到的問題和解決方法」,不是非常完全,但也可以代表服務(wù)治理的大致范圍。
服務(wù)治理的范圍
在服務(wù)治理方面,我們需要解決四個(gè)方面的問題:
為什么要進(jìn)行服務(wù)治理?
- 當(dāng)服務(wù)越來越多時(shí),過去簡(jiǎn)單記錄服務(wù)的?end point就越來越復(fù)雜。所以注冊(cè)中心是我們需要做的第一步,在這之后,才是服務(wù)發(fā)現(xiàn)和客戶端定制;
- 當(dāng)服務(wù)開始越來越復(fù)雜,我們就要依賴于管理服務(wù)。如果架構(gòu)師不了解系統(tǒng)里所有服務(wù)之間的依賴關(guān)系,則需要借助框架自動(dòng)畫出依賴關(guān)系并予以管理;
- 當(dāng)調(diào)用越來越多時(shí),我們需要增加監(jiān)控、容量規(guī)劃以及度量;
- 當(dāng)依賴變得復(fù)雜時(shí),除了了解服務(wù)的依賴關(guān)系,還要?jiǎng)討B(tài)的察覺依賴;
- 一般情況下,下層服務(wù)如果反調(diào)上層服務(wù),會(huì)造成循環(huán)依賴,需要SOA做到服務(wù)之間互相溝通,使管理更加容易;
- 如果想要防止文檔變得混亂,就需要更集中化的文檔管理,讓大家能夠搜到、看到所有的服務(wù)的文檔;
- 如果大家都可以公開調(diào)用內(nèi)部服務(wù),那么就會(huì)出現(xiàn)安全問題;
- 質(zhì)量問題也會(huì)難以保障,需要有非常好的服務(wù)監(jiān)控;
- 當(dāng)調(diào)用多個(gè)服務(wù)時(shí),需要做服務(wù)聚合。特別是當(dāng)我們依賴于服務(wù)編排時(shí),如果用框架來做會(huì)更方便。
服務(wù)拆分和治理的原則
服務(wù)拆分的原則
當(dāng)我們?cè)谡f微服務(wù)時(shí),我們是在說:到底微服務(wù)的顆粒度要做到多細(xì)或多粗。這就需要我們先定義服務(wù)的不同分類,可以按照不同的維度來做。如服務(wù)業(yè)務(wù)、服務(wù)流程或不同的業(yè)務(wù)域,這是第一種流程服務(wù),即滿足最高層服務(wù)的流程。在流程服務(wù)下還會(huì)出現(xiàn)組合服務(wù),會(huì)調(diào)用多個(gè)其他服務(wù)進(jìn)行封裝組合。再下面還會(huì)有平臺(tái)服務(wù) —— 在某業(yè)務(wù)域下的核心服務(wù)。最后是基礎(chǔ)服務(wù),它通常沒有特別的業(yè)務(wù)含義,是比較通用的服務(wù)。
同時(shí),我們也可以根據(jù)服務(wù)的屬性來分類:
所以,我們可以按照以上原則做系統(tǒng)分解:
- 不同的業(yè)務(wù)域劃分大的業(yè)務(wù)系統(tǒng),每個(gè)業(yè)務(wù)調(diào)用數(shù)據(jù)量最大的需要拆分;
- 風(fēng)險(xiǎn)高、頻率高、經(jīng)常更新的需要拆分的;
- 經(jīng)常會(huì)被復(fù)用的底層服務(wù)需要拆分;
- 服務(wù)需要專業(yè)技能、專業(yè)團(tuán)隊(duì),特別是技術(shù)棧不統(tǒng)一時(shí)進(jìn)行拆分。
服務(wù)設(shè)計(jì)原則
服務(wù)設(shè)計(jì)原因包括:
- 服務(wù)無狀態(tài),冪等性。在設(shè)計(jì)微服務(wù)時(shí),一般都會(huì)從領(lǐng)域模型?;谶@些領(lǐng)域來驅(qū)動(dòng)微服務(wù)REST API的設(shè)計(jì);
- 服務(wù)業(yè)務(wù)隔離,領(lǐng)域驅(qū)動(dòng)( Domain Driven Design );
- 服務(wù)契約驅(qū)動(dòng)( Design by Contract )。先定義接口,再去做服務(wù)的實(shí)現(xiàn);
- 服務(wù)資源隔離(數(shù)據(jù)庫,線程池等)。如果不隔離服務(wù)的數(shù)據(jù)庫,就很難知道有沒有其他服務(wù)在調(diào)用我們的數(shù)據(jù)庫,至少數(shù)據(jù)庫的用戶是需要隔離,不同用戶要有不同的權(quán)限;
- 故障可隔離(熔斷機(jī)制)。Spring Cloud里有Hystrix框架就可以很好的解決這個(gè)問題。
服務(wù)治理原則包括:
- 服務(wù)SLA;
- 服務(wù)需自治;
- 服務(wù)可開關(guān),降級(jí),限流,動(dòng)態(tài)調(diào)整負(fù)載路由;
- 服務(wù)可監(jiān)控,可統(tǒng)計(jì),提供Metrics和Health Check( Metrics Driven Design );
- 服務(wù)文檔和版本管理;
- 服務(wù)權(quán)限控制;
- 服務(wù)調(diào)用鏈可監(jiān)控。
Spring Cloud的服務(wù)治理
Spring Cloud 組件
上圖中比較核心的組建包括:
- 服務(wù)注冊(cè)提供很多選型。默認(rèn)是Eureka,還支持Consul和Zookeeper服務(wù)注冊(cè);
- 服務(wù)調(diào)用,REST API通常用Feign Client做服務(wù)調(diào)用,集成客戶端的負(fù)載均衡,所以Feign Client在服務(wù)治理中非常重要;
- 服務(wù)路由和服務(wù)過濾,在Spring Cloud提供的route API、gateway之類的工具;
其他還包括:
- 服務(wù)監(jiān)控,在?Spring Cloud環(huán)境下用的較多的是Hystrix —— 監(jiān)控控制臺(tái),集成的Turbine可以做跨集群的監(jiān)控;
- 配置中心,Spring Cloud默認(rèn)提供的配置管理是通過地址文件進(jìn)行管理,也支持諸如Zookeeper之類配置中心;
- 安全控制集成SpringSecurity,它本身不是屬于Spring Cloud的范疇,但會(huì)提供SpringSecurity Starter,幫助我們快速的建立權(quán)限管理;
- 用?Spring Cloud Sleuth做分布式的鏈路監(jiān)控,集成Zipkin之類的框架。
Spring Cloud 存在的問題和痛點(diǎn)
如何改善
更換配置中心。攜程的Apollo是一個(gè)更好的選擇。它里面的很多功能都是原生Spring Cloud配置中心不支持的。所以建議大家嘗試一下比較成熟的配置中心。
因?yàn)?API Gateway在Spring Cloud中沒有操作界面,所以我們就為之定制了專屬界面,讓它能夠管理不同的路由規(guī)則。我們還開發(fā)了一系列Filter,可以在API Gateway里做簽名檢查和解密。同時(shí),我們還集成了自己的賬戶系統(tǒng)和單點(diǎn)登錄,支持不同的登錄方式。
除此之外,我們集成了用戶中心( Accountservice )。因?yàn)楫?dāng)?API Gateway開放給渠道用戶或合作伙伴用戶時(shí),通常沒有交互,所以我們就需要通過參數(shù)的自動(dòng)抓取匹配用戶,據(jù)此判斷這個(gè)用戶是否已經(jīng)注冊(cè)。如果還未注冊(cè),我們就會(huì)自動(dòng)注冊(cè)。同時(shí),當(dāng)一個(gè)潛在用戶使用我們系統(tǒng)、調(diào)用API時(shí),我們就可以通過這種方式把硬件指紋記錄下來,后臺(tái)會(huì)給這些用戶打標(biāo)簽,我們就可以針對(duì)這些用戶做push等營(yíng)銷手段。
最后,還有一些前置Filter用于抽取數(shù)據(jù)。當(dāng)API請(qǐng)求時(shí),會(huì)異步通過日志抽取報(bào)文做數(shù)據(jù)清洗,通過ETL寫到數(shù)據(jù)倉庫里。
API gateway的動(dòng)態(tài)路由
舉個(gè)例子,比如我們把年齡小于30歲的男性路由到一個(gè)不同的endpoint ,我們?cè)谶@過程中會(huì)在請(qǐng)求頭、請(qǐng)求參數(shù)或請(qǐng)求頭中通過Json Parse抽取參數(shù)和數(shù)據(jù)轉(zhuǎn)換。我們可以從body里第一個(gè)customer對(duì)象的ID得到uid,之后保存到上下文中,輸出到output,當(dāng)我們指定endpoint為另外一個(gè)URL時(shí)把UID這個(gè)參數(shù)傳過去。
還有一種是報(bào)文的轉(zhuǎn)換,即Payload Transformation。這個(gè)技術(shù)其實(shí)在很久以前就已經(jīng)存在了,在ESB、SOAP時(shí)代,我們通常會(huì)利用XML來做報(bào)文的轉(zhuǎn)換。所以現(xiàn)在通常用來做報(bào)文轉(zhuǎn)換的工具是Json、Json Paser、Velocity Template、FreeMarker等。還有一些協(xié)議的轉(zhuǎn)換,我們內(nèi)部有很多API都是基于dubbo或者是其他的一些RPC協(xié)議。所以當(dāng)收到外部REST API請(qǐng)求時(shí),我們會(huì)做一個(gè)協(xié)議、格式的轉(zhuǎn)換。
在上圖中,入?yún)⑹潜容^復(fù)雜的Json,我們通過Input Mapping模板上邏輯輸出變量,嵌入到另外的Json對(duì)象中。如果我們?cè)趦?nèi)部有一套比較標(biāo)準(zhǔn)的API,可以通過這種方式適配到外部不同的API。這樣便集成了規(guī)則引擎,可以做一些比較基本的服務(wù)編排。
一體化的服務(wù)監(jiān)控和跟蹤
在Spring Cloud里提供了很多不同的服務(wù)監(jiān)控工具,利用這些工具可以做服務(wù)的業(yè)務(wù)監(jiān)控和埋點(diǎn),來收集各種Metrics。當(dāng)我們發(fā)送消息時(shí),我們會(huì)在適當(dāng)?shù)牡胤阶雎顸c(diǎn),收集數(shù)據(jù),最后再把這些集成起來,做報(bào)表展示和告警。所以整個(gè)這套服務(wù)監(jiān)控和跟蹤都是一體化的。
我們?cè)谧鲋虚g件埋點(diǎn)時(shí),可以有許多的選擇,比如JDK proxy、http client、Servlet filters、Spring MVC handler都可以添加埋點(diǎn),但我們更多會(huì)在Feign Client提供一些攔截器,當(dāng)服務(wù)調(diào)用時(shí),會(huì)有一些不同的event。
在DB里,我們用的比較多的是Druid datasource filter,它提供了很多擴(kuò)展,我們可以在這里邊做SQL查詢的埋點(diǎn),記錄每條SQL的響應(yīng)時(shí)間和調(diào)用頻次。同時(shí),Mybatis也可以做埋點(diǎn),定制一些插件。
服務(wù)監(jiān)控的整體架構(gòu)
過去我們使用日志做服務(wù)監(jiān)控的數(shù)據(jù)收集,大家都知道也有不少的服務(wù)監(jiān)控都是基于上報(bào)的API。但我們通過日志的方式收集數(shù)據(jù)對(duì)應(yīng)用的性能比較友好,不會(huì)因?yàn)槲覀兟顸c(diǎn)影響到業(yè)務(wù)。同時(shí),耦合度也比較低,只是分析度量數(shù)據(jù)。通過不同的Instruments寫到日志里。最后通過Logstash到Kafka進(jìn)入ElasticSearch,基于這些查詢可以快速生成簡(jiǎn)單的報(bào)表。
以上所說的內(nèi)容,如果都只是停留在框架級(jí)別,用戶和程序員根本看不到服務(wù)治理的概念。所以我們做了一套服務(wù)治理平臺(tái),可以看到所有服務(wù)治理內(nèi)容。同時(shí),我們還把配置中心嵌到了服務(wù)治理平臺(tái)中,將服務(wù)網(wǎng)關(guān)管理、Rabbit MQ消息隊(duì)列管理、通過消息隊(duì)列業(yè)務(wù)ID查詢消息軌跡以及一些項(xiàng)目管理相關(guān)的離線服務(wù)治理等功能集成在一起。
Q & A
問:下層服務(wù)和上層服務(wù)指的是什么?
答:所謂的下層服務(wù),就是底下平臺(tái)級(jí)的服務(wù)。比如你有一個(gè)發(fā)短信的服務(wù),如果這個(gè)服務(wù)跟你的賬戶體系耦合在一起,它就是反向調(diào)用,如果在短信服務(wù)里需要到會(huì)員中心獲取手機(jī)號(hào),這就是不合理的設(shè)計(jì),就是下層服務(wù)調(diào)上層服務(wù)的例子。
問:服務(wù)調(diào)用是每個(gè)服務(wù)各自寫一個(gè)FeignClient,還是由服務(wù)方提供統(tǒng)一的jar包?
答:我們現(xiàn)在做法是:在定義服務(wù)接口時(shí),這個(gè)服務(wù)接口就是FeignClient,然后把服務(wù)接口和它領(lǐng)域的對(duì)象封裝成統(tǒng)一的jar包,作為服務(wù)方提供。之后,客戶端用它來調(diào)用就可以了。在調(diào)用過程中,框架里的攔截器會(huì)做埋點(diǎn)、注入及監(jiān)控的工作。
問:老的服務(wù)如何調(diào)用FeignClient?
答:用延伸注解來實(shí)現(xiàn)。FeignClient在Spring Cloud用的是比較新的OpenFeign注解,支持一些特殊功能。比如插入自己的http client和做很多攔截器,老的FeignClient不是很友好,而且它跟Spring mvc的注解也不一致,但是作為一個(gè)很老的服務(wù),如果要調(diào)用FeignClient的話,我們通常會(huì)把所有FeignClient用到的class打成一個(gè)大的jar包,為這些老的服務(wù)實(shí)現(xiàn)調(diào)用。
問:如果有機(jī)會(huì)是不是直接選擇自研好一點(diǎn)?
答:作為開發(fā)人員或架構(gòu)師,每個(gè)人都想自研,確實(shí)也有很多團(tuán)隊(duì)自己做自研框架。但自研的問題是從入門到融會(huì)貫通的時(shí)間。雖然Spring Cloud現(xiàn)在十分簡(jiǎn)陋,但上手就可以用。如果在整個(gè)團(tuán)隊(duì)里都用Spring Cloud,可以很快地做一些簡(jiǎn)單的服務(wù)治理,然后再慢慢的優(yōu)化這個(gè)過程。還有一個(gè)原因,Spring Cloud在行業(yè)里的接受度比較高,大家的學(xué)習(xí)曲線比較短,通常自研的框架很多工程師可能不太接受或不太信任。
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/9274139.html
總結(jié)
以上是生活随笔為你收集整理的基于 Spring Cloud 的服务治理实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 酷狗音乐的大数据实践
- 下一篇: gradle idea java ssm