<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          詳解RPC的一次調用過程

          共 2315字,需瀏覽 5分鐘

           ·

          2021-07-27 17:36

          只要涉及到分布式服務,就繞不開RPC調用。RPC是什么,我認為大部分同學都能說出個一二三。

          那么RPC一次調用,到底經歷了哪些過程?

          一直在說RPC耗時優(yōu)化,那到底時間耗在了哪里? 

          本篇帶大家一起來梳理清晰。再遇到面試官問RPC,直接滅丫

          Part1前言 扯一扯RPC的蛋

          RPC ?(Remote Procedure Call) 遠程過程調用,目的是讓調用遠程服務的體驗,就像調用本地方法一樣簡單。

          已經有了HTTP,為啥還要實現個RPC? 首先,兩者不在一個水平面,不好比較。http是一種傳輸協(xié)議,RPC由TCP傳輸協(xié)議和其他部分組成,算是一種架構;再者,效率和性能有所差異,Http相比tcp傳輸更耗性能;再再者,定位不同,Rpc一般用于實現內部網絡各服務間的高性能調用,Http一般用于跨環(huán)境的數據傳輸和接口調用。

          RPC亙古不變的三個主題? 客戶端、服務端、注冊中心。后續(xù)包括服務注冊、服務發(fā)現、路由尋址、序列化、IO模型等等事項,都是在圍繞三者之間的合作和交互來進行的。

          常見RPC有哪些? 

          出鏡最多的要數dubbo,因為總被面試官問到;

          性能優(yōu)良的grpc,google出品,可以在任何環(huán)境下運行;

          美團的OCTO和pigeon,一個章魚水里游,一個鴿子天上飛;

          京東之前的saf,是對dubbo的定制化開發(fā),后面升級到了自研的jsf框架,其作者之一的章老板之前就已經是螞蟻的P8大佬了;

          螞蟻自研的sofaRPC也有章老板的參與,由于設計初衷和螞蟻內部的使用規(guī)模,功能豐富度和服務穩(wěn)定性上,那是相當不錯,目前也已經開源。

          Part2一次RPC調用的心路歷程



          一次RPC調用的心路歷程

          如上圖所示,一次rpc調用的過程,基本都囊括在內:

          Stub 存根

          處于真正調用之前。進行場景判斷、條件過濾等,以dubbo為例,可以用于壓測場景的數據mock等功能支持。

          路由尋址和負載均衡

          上面的圖其實有點不太準確,路由尋址和服務節(jié)點的負載均衡應該是一起完成的,在選定provider之后就是直連了。圖里只是為了對稱一些好看。

          尋址: 以safa為例,支持直連和注冊中心尋址。實現方案是在地址維護器中按配置加載直連分組和集群分組,在客戶端指定路由策略時,進行分別獲取。

          負載均衡: safa在負載算法上要支持的相對更全面一些:一致性hash、本機優(yōu)先、隨機負載、輪詢負載、加權一致性hash、加權輪詢。

          dubbo支持的負載均衡
          sofa支持的負載均衡

          序列化和反序列化

          序列化方式有很多種,包括jdk原生,kryo、hessian、protoStuff,thrift,JSON等。

          這里挑兩個經常使用,但是經常遇坑的來說下:

          hessian: 相比于Java原生序列化,效率更高、數據更小,但是需要注意,hessian反序列化時,是將屬性都取出來放到map里,因此,如果父類和子類有name相同的屬性,子類的會被覆蓋,因此,使用hessian時,要注意父子類不能有相同的屬性名。

          protoStuff:  相比Protobuf,stuff不需要寫.proto文件,效率上甚至比Protobuf更快。而快的原因之一,就是因為其序列化方式是按對象屬性的順序來執(zhí)行的,所以,如果順序變了,就會反序列化失敗。因此,在對使用了protoStuff序列化方式的對象新增字段時,最好是加到最后。

          編碼 解碼

          序列化之后為啥還要進行編碼呢?

          序列化其實是為了將待傳輸的對象轉化成標準二進制信息,為傳遞做準備,同時盡可能壓縮大小,方便傳輸。

          而編碼,是為了通信高效,一般的,都會加上超時策略、請求ID、網絡協(xié)議等信息。

          網絡傳輸

          一般大部分的RPC都選netty作為通信框架,而在底層是TCP的傳輸協(xié)議,而在上層,還有一層通信協(xié)議:

          • Bolt,RPC私有協(xié)議,sofa所屬
          • Dubbo,RPC私有化協(xié)議
          • Hessian,RPC公有化協(xié)議
          • thrift,Facebook出品,
          • 還有如RESTful等其他通信協(xié)議

          通信協(xié)議的目的,是為了讓中間件開發(fā)者能將更多的精力放在產品功能特性實現上,而不是重復地一遍遍制造通信框架的輪子。

          Part3RPC執(zhí)行耗時都耗在了哪里

          我是動圖,請多給我點時間

          從上圖分析中可以看出一次rpc調用的具體耗時節(jié)點。

          對于客戶端來說,耗時主要由:建連時間 + 序列化時間 + 等待服務端處理時間 組成;

          對于服務端來說,耗時主要由:線程池等待時間 + 服務處理時間 + 結果序列化時間 組成。

          所以,對于我們一線開發(fā),如果要對RPC耗時進行調優(yōu),最需要關注的,有客戶端的路由尋址、序列化方式,有服務端的服務線程池等待、反序列化、服務端處理速率、結果序列化 這幾塊。

          ‘建連’,一般因為我們采用長連接心跳檢測,是可以保證這個時間相對穩(wěn)定。

          比如,借鑒sofa,用增量更新的直接分組,來加速路由尋址;采用速度更快的序列化策略;調整服務端線程池到合適的大小,即能滿足請求處理,又不至于增加過多的線程切換損耗;用異步調用的方式替代同步阻塞等等。

          Part4總結

          本文從RPC的一次調用觸發(fā),結合一些開源的框架代碼,給大家梳理了RPC的調用過程和耗時分析。讓大家對RPC調用有一個更直觀的體會。特別是耗時分析這一部分,對我們一線研發(fā)的開發(fā)有些直接的指導意義。

          希望大家能有所得,有任何問題,歡迎留言指正、探討~

          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一起操逼| 壹屌探花 | 黄色18禁止网站 | 国产精品黄 | 美女天天日 |