Re:从 0 开始的微服务架构--(三)微服务架构 API 的开发与治理--转
原文來自:聊聊架構(gòu)公眾號(hào)
前面的文章中有說到微服務(wù)的通信方式,Martin Folwer 先生在他對(duì)微服務(wù)的定義中也提到“每個(gè)服務(wù)運(yùn)行在其獨(dú)立的進(jìn)程中,服務(wù)與服務(wù)間采用 輕量級(jí)的通信機(jī)制 互相協(xié)作(通常是基于 HTTP 協(xié)議的 RESTful API)”。
那么,在各個(gè)微服務(wù)之間具體怎么進(jìn)行輕量級(jí)的通信呢?這篇文章就來聊聊微服務(wù) API 開發(fā)及治理的幾個(gè)方面。
首先需要解釋一下,標(biāo)題中的“內(nèi)網(wǎng)環(huán)境中 的 API”指的是提供給內(nèi)網(wǎng)里的其它微服務(wù)調(diào)用的 API。與其相對(duì)應(yīng)的是“開放給互聯(lián)網(wǎng) 用戶調(diào)用的 API”,它們的開發(fā)方法大體相同,但治理方法卻不太一樣。
例如開放給互聯(lián)網(wǎng)用戶調(diào)用的 API 需要在 API 網(wǎng)關(guān)上加上授權(quán)、鑒權(quán)、限流、限并發(fā)、統(tǒng)計(jì)、計(jì)費(fèi)等等功能。
本篇文章分享的是內(nèi)網(wǎng)環(huán)境中的 API 開發(fā)及治理。
API 開發(fā)
API 開發(fā),首先考慮的就是該用什么樣的協(xié)議,是 HTTP API 還是 RPC?
我們先來介紹一下這兩種 API 類型:
?HTTP API
HTTP API 指的是簡單的基于 HTTP 協(xié)議的 API,具體的例子就是 Spring MVC 的 Controller,例如?
“http://127.0.0.1/helloworld/myapi.do”。
?RPC
RPC 就是 Remote Procedure Call,中文名遠(yuǎn)程過程調(diào)用,在 API 調(diào)用的場(chǎng)景下,大多指的是基于 Socket 通信方法的遠(yuǎn)程調(diào)用(當(dāng)然,我們也可以使用 HTTP 協(xié)議來實(shí)現(xiàn) RPC 調(diào)用,例如 gRPC)。Json-RPC 和 Xml-RPC 指的是使用 Json 或 Xml 作為文本格式的方式傳輸命令和數(shù)據(jù)。
那么回到剛才那個(gè)問題,到底要使用 HTTP API 還是 RPC 呢?我們之所要對(duì)比 HTTP API 和 RPC,主要是因?yàn)榇蠹叶贾?HTTP 簡單,而基于 Socket 的 RPC 性能更好。
這個(gè)問題我們糾結(jié)了很久,直到后來,想明白了下面兩件事,最終決定在絕大部分場(chǎng)景中使用 HTTP API。
HTTP API 的性能足以支撐大多數(shù)項(xiàng)目
通常來講(根據(jù)資料),算上序列化的時(shí)間,RPC 協(xié)議的吞吐量是 HTTP 性能 兩倍(沒有親測(cè)),例如 Protobuf、Thrift、Kyro、Dubbo 等等。
這里面,又以 Thrift 的性能最高。具體的性能測(cè)試報(bào)告可以參考《RPC 框架性能基本比較測(cè)試》。
我們團(tuán)隊(duì)在結(jié)合自身技術(shù)棧、成本、穩(wěn)定性、易用性、可維護(hù)性、業(yè)務(wù)場(chǎng)景等等因素綜合考慮后,覺得我們面臨的大多數(shù)場(chǎng)景中,HTTP 和 RPC 的性能差別并不是主要問題。
再加上下圖所示的 HTTP 性能測(cè)試結(jié)果作為佐證,我們完全可以采用 HTTP API 的方式來進(jìn)行微服務(wù) API 開發(fā)。
再者,當(dāng)業(yè)務(wù)發(fā)展到一定的程度,如果某些業(yè)務(wù)功能的性能壓力變大時(shí),我們還是可以使用 RPC 小范圍地進(jìn)行改造。這也是符合敏捷思想的一個(gè)決定。
下圖是對(duì) helloworld 頁面進(jìn)行 10000 次連續(xù)請(qǐng)求的測(cè)試結(jié)果,總耗時(shí) 1.504 秒,平均每個(gè)請(qǐng)求耗時(shí) 0.15 毫秒。
測(cè)試環(huán)境:原生 Tomcat7(沒有任何優(yōu)化)運(yùn)行在本地虛擬機(jī)上
下面是對(duì) helloworld 頁面以 100 并發(fā)數(shù)進(jìn)行 10 萬次請(qǐng)求的測(cè)試結(jié)果,平均每個(gè)請(qǐng)求耗時(shí) 11.9 毫秒。
測(cè)試環(huán)境:原生 Tomcat7(沒有任何優(yōu)化)運(yùn)行在本地虛擬機(jī)上
所以,按照上面的測(cè)試結(jié)果,HTTP API 方式的性能完全足以支撐絕大多數(shù)的微服務(wù) API 開發(fā)。讓我們把 RPC 方式留給那些可能出現(xiàn)雙十一業(yè)務(wù)量的大型互聯(lián)網(wǎng)公司去玩。
RESTful API 適用于開放 API 的場(chǎng)景
這是另一個(gè)折磨人的問題。相對(duì)于 HTTP API,RESTful API 在 HTTP API 的基礎(chǔ)上增加了一些非常抽象晦澀的概念,例如資源(Resource)、表述(REpresentation)、狀態(tài)轉(zhuǎn)移(State Transfer)、統(tǒng)一接口(Uniform Interface)……。
在經(jīng)歷了一次又一次的折磨,例如“login/logout 是什么 RESTful 方法?”、“批量刪除該怎么實(shí)現(xiàn)?”、“RESTful 的 resource 究竟該怎么定義?”之后,越來越感覺這是一個(gè)形而上學(xué)的問題,太過于抽像。
我們不該盲從于時(shí)髦的技術(shù),需要加上技術(shù)人的基于自身情況的理性思考。所以,RESTful 雖好,但不是我們團(tuán)隊(duì)的菜。
再者,即使團(tuán)隊(duì)中有些人可以理解并正確地實(shí)踐,也很難或者說不可能讓整個(gè)團(tuán)隊(duì)來正確地實(shí)踐這樣一種方法。
所以,我們?cè)谝环瑨暝?#xff0c;選擇了 HTTP API 方式,原來怎么開發(fā),現(xiàn)在還是怎么開發(fā),把主要精力放到了 API 的監(jiān)控和治理上面。
這里推薦大家看看知乎上的這篇討論 《WEB 開發(fā)中,使用 JSON-RPC 好,還是 RESTful API 好?》,幾位大神講得都挺好。
[https://www.zhihu.com/question/28570307]
API 治理API 文檔
API 存在的意義在于有人調(diào)用它,如果調(diào)用方在調(diào)用 API 的時(shí)候很麻煩,甚至不能正確地調(diào)用,那么團(tuán)隊(duì)內(nèi)部及團(tuán)隊(duì)之間的溝通成本及配合程度就會(huì)大受影響。
我們是通過文檔來溝通的,項(xiàng)目開始的時(shí)候還好,但隨著時(shí)間的推移,文檔的更新變得不是那么及時(shí)(這其實(shí)是個(gè)自我辯解的說法,事實(shí)是大部分情況下文檔都不更新了),API 變更時(shí),也不容易找出哪些模塊調(diào)用了這個(gè) API。
所以,得先解決 文檔不及時(shí)更新 的問題。雖然我們可以通過流程管理的方式來強(qiáng)制大家更新文檔,但這對(duì)于開發(fā)人員來說,顯然是不夠科學(xué)或人性化的,因?yàn)樽兏粋€(gè) API,就要在兩個(gè)地方進(jìn)行修改,一是 API 代碼,二是 API 文檔,程序員的思維就得在代碼和文檔之間不斷切換,工作效率必然受影響。
我們就想,能不能只需要在同一個(gè)地方修改,如果能做到,API 文檔的更新就沒有那么麻煩了,于人于已都是好事。
經(jīng)過調(diào)研,我們選擇使用 Swagger 來編寫文檔,按照 Swagger 的規(guī)范,在 API 上加一些描述性的 Annotation 就可以了。
通過以上的 Annotation,將自動(dòng)生成以下在線 API 文檔。
調(diào)用方可以在 API 文檔界面填入?yún)?shù)并點(diǎn)擊“Try it out!”按鈕嘗試調(diào)用這個(gè) API。這樣,在沒有 API 提供方支持的情況下,即可以自行完成絕大部分的 API 調(diào)用,是不是很爽?
調(diào)用鏈管理
API 開發(fā)出來了,API 文檔也寫好了,接下來就是被調(diào)用了。前篇文章講到,通過 Spring Cloud 的 Eureka + Ribbon + Zuul 可以很方便地調(diào)用到這些 API。
那么,如何來追蹤 API 被誰調(diào)用了,調(diào)用是否出錯(cuò)及出錯(cuò)原因,調(diào)用鏈路里各個(gè) API 的性能怎么樣,是不是存在僵尸 API……這些都是關(guān)于 API 治理的問題。
實(shí)現(xiàn)這個(gè)目標(biāo),有一個(gè)比較取巧的方法,就是在 Ribbon 的客戶端里做點(diǎn)文章,在調(diào)用 API 之前記錄一下開始時(shí)間,API 調(diào)用返回后,記錄 API 調(diào)用耗時(shí)、調(diào)用狀態(tài),如果有錯(cuò)則記錄一下錯(cuò)誤原因。
如果還想追蹤調(diào)用鏈,可以在請(qǐng)求頭里加上一個(gè)調(diào)用鏈 ID,這樣就來把調(diào)用關(guān)系都串連起來。
下邊是我們自己研發(fā)的調(diào)用鏈管理組件(DCTrace)的幾個(gè)效果圖:
查看微服務(wù)之間的調(diào)用關(guān)系,調(diào)用性能
查看調(diào)用失敗原因
圖形化查看調(diào)用關(guān)系,太亂 ,下次迭代改進(jìn)一下 [攤手]
站在技術(shù)管理者的角度,可以從調(diào)用鏈里看出來,哪些模塊之間發(fā)生了不正當(dāng)關(guān)系 [噗嗤];哪些模塊之間本該有關(guān)系的,事實(shí)卻沒有;通過對(duì)比 Swagger 和調(diào)用鏈的 API 清單,找出僵尸 API……
API 測(cè)試
使用微服務(wù)架構(gòu)后,API 是每個(gè)微服務(wù)的 唯一能力出口。由于互聯(lián)網(wǎng)行業(yè)的快速發(fā)展,軟件需求變更變得越來越頻繁,迭代升級(jí)的速度變得越來越快。
對(duì)于提供方來說,需要保證變更和迭代的過程中,不影響之前承諾的功能(包括正確性、穩(wěn)定性和性能等)。
對(duì)于調(diào)用方來說,同樣需要確保自身依賴的 API 能正常使用,不能因?yàn)槠渌K的錯(cuò)誤而導(dǎo)致自身業(yè)務(wù)受到影響(包括正確性、穩(wěn)定性和性能等)。
畢竟,從組織角度來看,系統(tǒng)出錯(cuò)就是出錯(cuò),不管原因是自身導(dǎo)致的還是服務(wù)提供方導(dǎo)致的,所以 服務(wù)調(diào)用方就需要對(duì)服務(wù)提供方進(jìn)行管理。
這也就是前幾年契約測(cè)試(Pact)方法大行其道的原因。有興趣的朋友可以去看看這種測(cè)試方法。
對(duì)于 API 白盒測(cè)試,推薦使用基于 Java 的 REST-Assured 測(cè)試框架,用起來特別方便。
[https://github.com/rest-assured/rest-assured]
更進(jìn)一步,基于 HTTP 協(xié)議、JSON/XML 報(bào)文的規(guī)范性,完全可以開發(fā)一個(gè) API 測(cè)試小工具(暫且叫它 小鷹 吧)來替換 REST-Assured。我們也暫未實(shí)踐,只是覺得會(huì)很有用,供大家參考。
基礎(chǔ)步驟是:
服務(wù)提供方開發(fā) API,并正確書寫 Swagger 文檔。
服務(wù)提供方在小鷹的界面上選擇需要測(cè)試的 API,并填寫測(cè)試參數(shù)。(API 清單和參數(shù)都可以通過調(diào)用 Swagger 的 API 獲取)
服務(wù)調(diào)用方根據(jù)自已的理解,也將對(duì)自己有用的服務(wù)方提供的 API 配置到小鷹上。
小鷹 7*24 小時(shí)為服務(wù)提供方和調(diào)用方巡視這些 API,并在異常出現(xiàn)時(shí)發(fā)送警報(bào)。
總 ? 結(jié)
所以,對(duì)于微服務(wù) API 開發(fā),我們
-
使用最常見的技術(shù)(例如 Spring MVC)進(jìn)行 API 開發(fā)
-
使用 REST-Assured(以及未來的 小鷹)進(jìn)行測(cè)試
-
使用 Swagger 來管理 API 文檔
-
使用自研的 DCTrace 進(jìn)行調(diào)用鏈管理
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/7419647.html
總結(jié)
以上是生活随笔為你收集整理的Re:从 0 开始的微服务架构--(三)微服务架构 API 的开发与治理--转的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java7里try-with-resou
- 下一篇: Re:从0开始的微服务架构:(一)重识微