目前大部分的系統架構都是微服務架構,就算沒有註冊中心、服務管理,也確定是多個服務,單體服務比較少了。
你們平時須要在應用內調用rpc接口也比較多,那麼有沒有思考過微服務之間的調用和應用內直接調用有什麼區別呢?面試時是否是常常被被問到微服務呢,本篇文章針對微服務間的方法調用和應用內方法調用的有啥區別
這個很小的點,談談個人經驗前端
先從單體應用提及
單體應用
單體引用經過一個服務節點直接組裝好數據,返回給調用者。全部的方法調用都發生在應用內部。面試
微服務應用docker
商品詳情服務須要調用商品,營銷等多個服務組裝好商品詳情頁的數據數據庫
微服務調用和應用內調用不一樣點在於它是跨進程的,甚至是跨節點的,這意味着什麼呢api
使用k8s編排微服務時,咱們可讓不一樣的服務放在同一個節點的不一樣docker container上,可是考慮到網絡不可靠,和容災,
服務之間不可避免會放到不一樣的節點/機架上,因此下文都以跨節點來討論安全
意味着兩點網絡
關於網絡有幾個著名的錯誤推論架構
The network is reliable(網絡是可靠的)
Latency is zero.(延遲能夠爲0)
Bandwidth is infinite(帶寬是無限的)
The network is secure(網絡是安全的)
Topology doesn't change(網絡拓撲結構不會變)
Transport cost is zero(網絡傳輸耗時爲0)
The network is homogeneous(網絡是同類的)tcp
存在上述兩個問題後,那麼咱們須要在寫微服務間方法調用時注意什麼的微服務
對外部有了依賴
微服務架構設計中有一條重要的原則叫嚴出寬進
,嚴出意思就是說你提供給其餘服務的東西要儘量的進行嚴格的校驗。寬進就是你調用別人的接口要寬容,兼容各類狀況。好比說你須要考慮別人的節點down了/api超時/api不可用等等因素。
爲了解決這個問題,咱們必需要針對具體業務,分析依賴類型,是強依賴仍是弱依賴,強依賴包裝成本身的服務異常返回碼/或者直接告訴前端調用不可用。弱依賴,catch全部異常,不管依賴方發生什麼,不能影響個人接口返回。
此外,我依賴的服務某段時間內接口錯誤率很高,調用方還在不停的發送請求,那麼就會一直獲得錯誤的結果,這時候這些請求實際上是無效的,因此這時候須要客戶端熔斷,再也不去調用服務方,給服務方恢復的時間,等過段時間再去重試,發現服務方可用時,再去調用。
網絡調用
網絡調用是耗時的,因此咱們須要利用池化技術,複用鏈接,好比在單體應用中咱們須要與數據庫鏈接,會利用到數據庫鏈接池來提升數據操做效率。那麼微服務調用也是這麼個道理,咱們與其餘服務建議http/tcp鏈接,也須要創建鏈接池。另一個服務可能會依賴多個微服務,不能由於和某個服務之間的鏈接出了問題,影響到與其餘服務的鏈接,因此須要作鏈接池隔離。
服務間調用有可能失敗,因此咱們須要有重試機制,好比由於網絡抖動引起的超時問題,咱們能夠經過重試提升API的可用性。
可是思考一下壞的狀況,某段時間網絡或者服務端真的有問題了。客戶端超時時間設置的很大的話,客戶端等待的時間就會很長,而後再加上重試機制,就會將客戶端的鏈接佔滿,形成客戶端相關API不可用。
分享幾個微服務調用的故障案例,幫助你們進行場景化思考
爲啥要分享這些案例呢,由於TMD的這些案例都是血的教訓,形成線上故障,不是個人錯,卻要我背鍋
案例1:
新上線了一個產品功能,須要推廣,放在另一個流量比較大的產品模塊中,展現一些咱們產品功能的數據。
出於某種緣由,咱們的服務mock了rpc調用數據,返回null。結果其餘服務整個前臺頁面掛了,掛了,掛了。
典型的強弱依賴問題,調用方沒有處理好依賴類型,明明是一個弱依賴沒有處理,變成了強依賴,形成功能掛了
案例2:
依賴的某個服務須要根據主鍵List<id>
來批量查詢,依賴服務內部作分庫分表拆分,升級了sdk
在提供的sdk client中作分表路由,將批量id拆分紅N個rpc調用。這麼作的緣由是防止批量查詢把數據庫鏈接池打爆。
忽略了網絡調用
案例3
別人調咱們的服務的某個接口,這個接口RT(耗時時間)P95 < 30ms。可是客戶端調用的超時時間設置成了500ms,在某次不知道是什麼緣由的狀況下,調用方的鏈接大量block,形成線程阻塞,相關API不可用。看服務方監控,該接口返回時間正常,服務方沒有任何異常。
沒有正確的設置超時時間
微服務調用和應用內調用有很大的區別,咱們不能在進行服務間調用時無感知,須要知道它面臨的問題
解法能夠精煉爲4條
這些問題看似都很簡單,可是根據個人觀察,真的有不少人寫了無數的rpc調用,尚未意識到這些問題。
關注【方丈的寺院】,與方丈一塊兒開始技術修行之路