<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] ## **RPC協議基本組成** --- ### **RPC 協議名詞解釋** 在一個典型RPC的使用場景中,包含了服務發現、負載、容錯、網絡傳輸、序列化等組件,其中RPC協議就指明了程序如何進行網絡傳輸和序列化 。也就是說一個RPC協議的實現就等于一個非透明的遠程調用實現,如何做到的的呢? ![](https://img.kancloud.cn/f3/e0/f3e003d0243c8487263a280e7939a0ea_986x698.png) ### **協議基本組成:** ![](https://img.kancloud.cn/f0/8d/f08d920e086c53a9aa078fdfe050d300_501x382.png) 1. 地址:服務提供者地址 2. 端口:協議指定開放的端口 3. 報文編碼:協議報文編碼 ,分為請求頭和請求體兩部分。 4. 序列化方式:將請求體序列化成對象 1. Hessian2Serialization、 2. DubboSerialization、 3. JavaSerialization 4. JsonSerialization 5. 運行服務: 網絡傳輸實現 1. netty 2. mina 3. RMI 服務 4. servlet 容器(jetty、Tomcat、Jboss)? ## **Dubbo中所支持RPC協議使用** --- **dubbo 支持的RPC協議列表** | **名稱** | **實現描述** | **連接描述** | **適用場景** | |:----|:----|:----|:----| | **dubbo** | 傳輸服務: mina, netty(默認), grizzy序列化: hessian2(默認), java, fastjson自定義報文 | 單個長連接NIO異步傳輸 | 1、常規RPC調用2、傳輸數據量小3、提供者少于消費者 | | **rmi** | 傳輸:java rmi 服務序列化:java原生二進制序列化 | 多個短連接BIO同步傳輸 | 1、常規RPC調用 2、與原RMI客戶端集成 3、可傳少量文件 4、不防火墻穿透 | | **hessian** | 傳輸服務:servlet容器序列化:hessian二進制序列化 | 基于Http 協議傳輸,依懶servlet容器配置 | 1、提供者多于消費者 2、可傳大字段和文件 ~~3、跨語言調用~~ | | **http** | 傳輸服務:servlet容器序列化:java原生二進制序列化 | 依懶servlet容器配置 | 1、數據包大小混合 | | **thrift** | 與thrift RPC 實現集成,并在其基礎上修改了報文頭 | 長連接、NIO異步傳輸 | | ***關于RMI不支持防火墻穿透的補充說明:*** 原因在于RMI 底層實現中會有兩個端口,一個是固定的用于服務發現的注冊端口,另外會生成一個***隨機***端口用于網絡傳輸。因為這個隨機端口就不能在防火墻中提前設置開放開。所以存在*防火墻穿透問題* ### **協議的使用與配置:** Dubbo框架配置協議非常方便,用戶只需要在? provider 應用中 配置*<**dubbo:protocol>*?元素即可。 ``` ?<!-- ?? name: 協議名稱 dubbo|rmi|hessian|http| ?? host:本機IP可不填,則系統自動獲取 ?? port:端口、填-1表示系統自動選擇 ?? server:運行服務? mina|netty|grizzy|servlet|jetty ?? serialization:序列化方式 hessian2|java|compactedjava|fastjson ?? 詳細配置參見dubbo 官網 dubbo.io ?--> ?<dubbo:protocol name="dubbo" host="192.168.0.11" port="20880" server="netty"? ? serialization=“hessian2” charset=“UTF-8” /> ?? ``` #TODO 演示采用其它協議來配置Dubbo - [ ] dubbo 協議采用 json 進行序列化??(源碼參見:com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol*)* - [ ] 采用RMI協議?(源碼參見:*com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol)* - [ ] 采用Http協議?(源碼參見:*com.alibaba.dubbo.rpc.protocol.http.HttpProtocol.InternalHandler)* - [ ] 采用Heason協議?(源碼參見:com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol.HessianHandler) new PrintWriter(System.out) ``` netstat -aon|findstr "17732" ``` 序列化: | | 特點 | |:----|:----| | fastjson | 文本型:體積較大,性能慢、跨語言、可讀性高 | | fst | 二進制型:體積小、兼容 JDK 原生的序列化。要求 JDK 1.7 支持。 | | hessian2 | 二進制型:跨語言、容錯性高、體積小 | | java | 二進制型:在JAVA原生的基礎上 可以寫入Null | | compactedjava | 二進制型:與java 類似,內容做了壓縮 | | nativejava | 二進制型:原生的JAVA 序列化 | | kryo | 二進制型:體積比hessian2 還要小,但容錯性 沒有hessian2 好 | ### Hessian 序列化: * 參數及返回值需實現?Serializable?接口 * 參數及返回值不能自定義實現?List,?Map,?Number,?Date,?Calendar?等接口,只能用 JDK 自帶的實現,因為 hessian 會做特殊處理,自定義實現類中的屬性值都會丟失。 * Hessian 序列化,只傳成員屬性值和值的類型,不傳方法或靜態變量,兼容情況?[[1]](http://dubbo.apache.org/zh-cn/docs/user/references/protocol/dubbo.html#fn1)[[2]](http://dubbo.apache.org/zh-cn/docs/user/references/protocol/dubbo.html#fn2): | **數據通訊** | **情況** | **結果** | |:----|:----|:----| | A->B | 類A多一種 屬性(或者說類B少一種 屬性) | 不拋異常,A多的那 個屬性的值,B沒有, 其他正常 | | A->B | 枚舉A多一種 枚舉(或者說B少一種 枚舉),A使用多 出來的枚舉進行傳輸 | 拋異常 | | A->B | 枚舉A多一種 枚舉(或者說B少一種 枚舉),A不使用 多出來的枚舉進行傳輸 | 不拋異常,B正常接 收數據 | | A->B | A和B的屬性 名相同,但類型不相同 | 拋異常 | | A->B | serialId 不相同 | 正常傳輸 | 接口增加方法,對客戶端無影響,如果該方法不是客戶端需要的,客戶端不需要重新部署。輸入參數和結果集中增加屬性,對客戶端無影響,如果客戶端并不需要新屬性,不用重新部署。 輸入參數和結果集屬性名變化,對客戶端序列化無影響,但是如果客戶端不重新部署,不管輸入還是輸出,屬性名變化的屬性值是獲取不到的。 總結:服務器端和客戶端對領域對象并不需要完全一致,而是按照最大匹配原則。 - [ ] 演示Hession2 序列化的容錯性 ## **三 、RPC協議報文編碼與實現詳解** --- ### **RPC 傳輸實現:** RPC的協議的傳輸是基于 TCP/IP 做為基礎使用Socket 或Netty、mina等網絡編程組件實現。但有個問題是TCP是面向字節流的無邊邊界協議,其只管負責數據傳輸并不會區分每次請求所對應的消息,這樣就會出現TCP協義傳輸當中的拆包與粘包問題 ### **拆包與粘包產生的原因:** 我們知道tcp是以流動的方式傳輸數據,傳輸的最小單位為一個報文段(segment)。tcp Header中有個Options標識位,常見的標識為mss(Maximum Segment Size)指的是,連接層每次傳輸的數據有個最大限制MTU(Maximum Transmission Unit),一般是1500比特,超過這個量要分成多個報文段,mss則是這個最大限制減去TCP的header,光是要傳輸的數據的大小,一般為1460比特。換算成字節,也就是180多字節。 tcp為提高性能,發送端會將需要發送的數據發送到緩沖區,等待緩沖區滿了之后,再將緩沖中的數據發送到接收方。同理,接收方也有緩沖區這樣的機制,來接收數據。這時就會出現以下情況: 1. 應用程序寫入的數據大于MSS大小,這將會發生拆包。 2. 應用程序寫入數據小于MSS大小,這將會發生粘包。 3. 接收方法不及時讀取套接字緩沖區數據,這將發生粘包。 ### **拆包與粘包解決辦法:** 1. 設置定長消息,服務端每次讀取既定長度的內容作為一條完整消息。 2. {"type":"message","content":"hello"}\n 3. 使用帶消息頭的協議、消息頭存儲消息開始標識及消息長度信息,服務端獲取消息頭的時候解析出消息長度,然后向后讀取該長度的內容。 **比如:** Http協議 heade 中的 Content-Length 就表示消息體的大小。 ????? ![](https://box.kancloud.cn/e7cede899514b7e539229400cac8bcbc_590x444.png) ?????? (注①:http 報文編碼) ### Dubbo 協議報文編碼: **注②Dubbo? 協議報文編碼:** ![](https://img.kancloud.cn/b1/cb/b1cb18e57978bbdebe0850ffd14de48d_804x230.png) * **magic**:類似java字節碼文件里的魔數,用來判斷是不是dubbo協議的數據包。魔數是常量0xdabb,用于判斷報文的開始。 * **flag**:標志位, 一共8個地址位。低四位用來表示消息體數據用的序列化工具的類型(默認hessian),高四位中,第一位為1表示是request請求,第二位為1表示雙向傳輸(即有返回response),第三位為1表示是心跳ping事件。 * **status**:狀態位, 設置請求響應狀態,dubbo定義了一些響應的類型。具體類型見 com.alibaba.dubbo.remoting.exchange.Response * **invoke id:**消息id, long 類型。每一個請求的唯一識別id(由于采用異步通訊的方式,用來把請求request和返回的response對應上) * **body length:**消息體 body 長度, int 類型,即記錄Body Content有多少個字節。 ![](https://img.kancloud.cn/3b/2c/3b2ce740a436701815d5b5f7a5eab111_1031x327.png) *(注:相關源碼參見?**c**om.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec**)* ### ***Dubbo協議的編解碼過程:*** ![](https://img.kancloud.cn/b2/43/b24378710492ade4aa9fa2a879335992_682x311.png) **Dubbo 協議編解碼實現過程**?*(源碼來源于**dubbo2.5.8? )* ``` 1、DubboCodec.encodeRequestData() 116L // 編碼request 2、DecodeableRpcInvocation.decode() 89L // 解碼request 3、DubboCodec.encodeResponseData() 184L // 編碼response 4、DecodeableRpcResult.decode() 73L // 解碼response ``` **?**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看