業務網關的落地實踐

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着系統規模變大、複雜度越來越高,微服務架構漸漸成爲主流。當一個單體應用被拆分成許許多多的微服務應用後,也帶來了一些問題。一些與業務非強相關的功能,比如權限控制、日誌輸出、數據加密、熔斷限流等,每個微服務應用都需要,因此存在着大量重複的代碼實現。而且由於系統的迭代、人員的更替,各個微服務中這些功能的實現細節出現了較大的差異,導致維護成本變高。另一方面,原先單體應用下非常容易做的接口管理,在服務拆分後沒有了一個集中管理的地方,無法統計已存在哪些接口、接口定義是什麼、運行狀態如何。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關就是爲了解決上述問題。作爲微服務體系中的核心基礎設施,一般需要具備接口管理、協議適配、熔斷限流、安全防護等功能,各種開源的網關產品(比如 zuul)都提供了優秀高可擴展性的架構、可以很方便的實現我們需要的一些功能、比如鑑權、日誌監控、熔斷限流等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,僅有這些功能還不夠。企業內部系統一般都是異構的,存在多種協議的接口,而對外提供服務的接口依然是 http 協議的。因此,協議轉換是非常現實的需求。還有數據聚合的能力,開源產品提供的都是一對一路由功能,並不直接提供聚合、編排的能力。而在實際開發中,需要對一些小接口進行聚合是很常見的,如果需要去寫代碼、發佈就會很繁瑣,而且以後小接口升級還得同步更新。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,我們參考 SpringCloud 網關產品的優秀設計理念,在基礎網關的功能上支持多種下游協議、支持服務編排功能,並提供可視化的配置平臺。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"1 技術選型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.1 方案對比"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們選擇了 Java 微服務體系中三個主流的 API 網關框架 Zuul1、Zuul2 和 SpringCloud Gateway,在線程模型、協議適配、熔斷限流,服務編排等方面進行了對比。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/44\/40\/44011a93bc3b48de0ab665ef662fe240.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"三種框架的優缺點都很明顯,但是都缺少了對 dubbo 的支持,同時也沒有數據聚合(服務編排)的能力,因此我們借鑑它們的優秀架構,自研業務網關。下面看一下 Zuul2 的系統架構。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1.2 系統架構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/a5\/ba\/a50b676c4af18ef885e14326c7b910ba.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是典型的網關係統架構,由三種功能 Filter 以及異常 Filter 組成。Inbound Filters 主要負責對 request 的校驗、加工、攔截,Endpoint Filter 負責路由 & 下游接口調用,Outbound Filters 負責對 response 的校驗、加工、日誌監控等,Exception Filter 則負責功能 Filter 中的異常處理。這套架構簡單清晰、可擴展性強,可以很容易實現模塊化、並且各個模塊(Filter)間彼此無耦合,類似 Plugin 的獨立性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2 體系結構"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先看一下網關的體系結構。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/a4\/e5\/a467389a804cccd8f06f5cd244f1e4e5.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"校驗攔截層提供了網關的基礎能力,通過 Inbound Filters 和 Outbound Filters 來實現,可無限擴展。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務調度層和接口通信層提供了核心能力,通過 EndPoint Filter 來實現。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"異常處理統一交由 Exception Filter 來處理,之後會重新流轉到 Outbound Filters 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/6a\/a6\/6abb9d0c42391b18c9171e34b936f0a6.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3 創新之處"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.1 協議轉換"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"公司內部 rpc 服務採用 dubbo 這套解決方案的基礎上二次開發,大量的微服務採用 dubbo 協議,網關也必須要支持 dubbo 接口的轉發。dubbo 的泛化調用非常適合網關的場景,它需要接口定義和接口配置(zkaddress、group、version 等)兩部分信息。其中,接口定義信息手工填寫非常繁瑣,爲了避免人爲因素導致的配置錯誤,網關會根據 jar 包的 maven 座標去拉取 jar 包進行掃描,獲取到接口的具體方法簽名。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關管理所有的 Dubbo Reference,監聽配置平臺的推送消息,動態管理 Reference 的生命週期以及運行參數,比如實時調整 dubbo 接口的超時時間、實時升級 dubbo 接口的版本等。所有的 Reference 對象都在初始化後才交付給執行器,保證接口的執行效率。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/b3\/bb\/b3f2d6a46a7a1dc13d0f94be4a3060bb.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.2 服務編排"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"微服務架構下會更依賴通過各微服務之間的協作來實現一個完整的業務流程,這種協作就是服務編排。編排涉及到 RPC、分佈式事務等,需要有完善的編排框架來支撐。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"編排的實現,需要解決四個關鍵點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"複雜依賴:存在 M:N 的依賴關係"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"執行時機:如何並行,如何避免阻塞等待"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"數據傳遞:如何根據上游數據構建下游參數"}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"異常處理:異常時應該整體中斷,還是服務降級"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中,複雜依賴和執行時機是難點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"複雜依賴"},{"type":"text","text":":採用服務自治的思路,通過定義每個服務所關心的服務即可。通過分析,發現這是個有向無環圖,通過成環檢測可以發現不合理的依賴關係。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"執行時機"},{"type":"text","text":":採用面向協作的思路,通過消息的交互序列來控制各個服務的交互,參與交互的服務都是對等的,沒有集中的控制。如上圖所示,所有服務通過消息總線共享事件通知,決定自身是否執行。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/ed\/7c\/ed53fe5f22c8b0341268418712314f7c.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3.3 嵌入式網關"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼需要嵌入式?要解決什麼問題?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一般主要業務接口都會附帶着調用很多小接口,並隨着主接口的數據一併返給調用方。主業務接口一般比較穩定,但是小接口的迭代相對比較頻繁。此時,因爲小接口的迭代導致修改主業務接口所在的工程,就顯得那麼的多餘。我們希望能把與主業務接口無耦合的小接口透傳化,達到小接口升級、主接口無感知的目標。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們將網關的核心能力抽象出來形成一個 jar 包,主要包括配置同步、服務編排、協議轉換,稱作“嵌入式網關”。宿主工程引入嵌入式網關,並將調用下游接口的地方改成嵌入式網關的執行入口就行了,剩下的就是去配置平臺配置這個接口的相關信息。如果是 dubbo 接口的話,還可以順便將依賴的 api jar 包刪掉,因爲泛化調用不需要引入 jar 包。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"嵌入式網關提供了宿主工程透傳化改造的能力,可以實現非強耦合下游接口的數據純透傳化,降低宿主工程的業務複雜度,並且可享受網關係統的所有能力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4 高可用探索"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如何考量一個網關產品的優劣?常用的性能指標包括:吞吐量、耗時、錯誤率。有個非常關鍵的指標:高可用性,也就是傳說中的幾個9。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"高可用性涵蓋了內部和外部的各種不確定因素,這裏講一下網關係統在高可用性方面做的努力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/af\/06\/af5334fce3b7b4237d08ce685728c406.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"5 落地效果"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.1 人效"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關上線後,最直接的收益是人效方面。因爲減少了一個協作團隊,因此相應節省了開發與測試的工時。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"選擇了幾個比較獨立的業務做數據分析,整體節省了大概27%左右的工時。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/48\/05\/48428ea6b6d22007b4120ea4b6923905.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"注:節省工時包括“ API 層服務團隊的開發、自測聯調,以及對應 QA 的工時”。前端跟後端按2:1,開發跟 qa 按3:1算,=前端*67%"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"注:”商品售賣“通過嵌入式網關實現了與主接口的解耦,迭代過程中無主工程的發佈。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"5.2 故障處理"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於網關具備了調整數據的能力,對於一些由於數據不規範或者缺失導致的故障,提供了快速恢復的手段。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"故障案例:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/34\/b4\/3467fae6a29ef0d8d4f7e09e14479eb4.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"6 典型案例"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"1、新開發一個純透傳的接口"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常規:寫代碼調用下游接口,定義 bean,將結果添加到 response 中。當下遊增加字段時,需要代碼迭代。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關:在配置平臺上配置下游服務,無需定義 bean,純透傳,下游接口增加字段無需任何改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"2、活動首頁配置獲取接口,新增一個維度的配置,該配置數據由一個新接口提供(數據聚合)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常規:寫代碼調用新的下游接口,將結果添加到 response 中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關:在配置平臺上增加一個下游服務,將結果掛載到 response 中,後續迭代無需任何改動。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"3、touch接口的跨域解決"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常規:針對下游接口做 ng 轉發,或者由下游接口做跨域處理。當下遊使用 jsonp 時,還可能存在 xss 漏洞隱患。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關:在公司 touch 域名下增加了\/gw 的 location 配置,開發人員無需考慮跨域問題。還支持 jsonp,並且做了 xss 漏洞防禦。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"4、從一個接口獲取酒店列表,然後從另一個接口給每一個酒店補充評論信息"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"常規:調用第一個接口獲取酒店列表,做簡單業務判斷後,對列表做循環調用第二個評論接口,並將數據補充進去。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"網關:定義兩個下游接口,將第二個評論接口設置爲依賴”第一個酒店列表接口“,並且指定循環用的字段路徑,還可以指定失敗時的降級內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"horizontalrule"},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"頭圖"},{"type":"text","text":":Unsplash"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"作者"},{"type":"text","text":":施黎明"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"原文"},{"type":"text","text":":"},{"type":"link","attrs":{"href":"https:\/\/mp.weixin.qq.com\/s\/D5r9KPq54o5uthA9jYW2yw","title":"","type":null},"content":[{"type":"text","text":"業務網關的落地實踐"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"來源"},{"type":"text","text":":Qunar技術沙龍 - 微信公衆號 [ID:QunarTL]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"轉載:著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。"}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章