RPC框架基礎概念理解以及使用初體驗


RPC:Remote Procedure Call(遠程服務調用)

RPC是做什么的

通過RPC框架機器A某個進程可以通過網絡調用機器B上的進程方法,就像在本地上調用一樣。
RPC可以基於HTTP或者TCP協議通信,TCP協議相對性能較高。

調用圖示(引用zhanglijun童鞋的圖)

image

圖片描述:

  1. client發出調用方法(服務)的請求
  2. client stub作為中轉站,進行請求接口、方法、參數以及服務地址、請求Id的封裝,包裝成RequestMessage對象、序列化——編碼,最后傳輸到網絡上去
  3. 服務端(service)經過網絡接受到RequestMessage
  4. 首先server stub進行字節流的反序列化、解析requestMessage——解碼,最后將請求轉發給server
  5. server調用method(...),返回結果給server stub
  6. server stub將result、返回狀態碼、請求id等進行包裝成ResponseMessage、序列化——編碼、傳輸
  7. client stub得到字節流,進行反序列化、解析ResponseMessage——解碼,將結果返給client
  8. client最終得到結果

RPC框架就是將2-7這幾個步驟封裝起來,幫忙處理網絡IO、編解碼、序列化、服務尋址等工作,這些工作對於調用方和服務方都是透明的。由此,我們也可以得出結論,我們就需要使用代碼實現2-7步驟所需要處理的工作。下面列舉實現一個輕量級RPC框架所需要解決的幾個問題。

RPC框架的實現需要解決的幾個問題

如果想實現一個輕量級rpc框架需要解決什么問題呢:

請求封裝問題

機器A想要調用機器B上面的方法method(),那么A機器就需要詳細描述自己的需求——要調用那個ip上那個端口的進程、調用哪個service,這些都需要描述清楚。

詳細如下:

  • 接口名稱,一個接口提供一種服務,比如HelloworldService
  • 方法名稱,定位一個接口內的某個方法
  • 參數——類型與值,client調用就需要client指定入參,服務端是肯定不知道這些的
  • 超時時間
  • requestId,每一個client發出請求時都需要綁定一個唯一指定requestId,這是因為在並發請求的時候一個服務方可能服務多個client的請求,有了這個requestId,client stub才能將返回結果發放給特定的請求線程而不會混淆。

返回消息對象封裝問題

  • 返回值
  • 狀態code,表示這次請求成功與否
  • requestid

序列化的問題

網絡IO需要傳輸請求消息對象以及響應消息對象,這樣才能達到雙方通信的目的。但是網絡是以字節(byte)准確的說是比特傳輸信息的,因此需要一種技術將對象轉換成字節(序列化),以及再將字節轉換成對象(反序列化)。java自身是有序列化工具的,借助ObjectOutputStream等類就可以序列化對象。但是他的性能、拓展性都不是很好,因此一般借助於第三方的序列化工具

目前,互聯網公司主流使用protobufthriftjacksonhessian

網絡通信問題

消息序列化之后就是網絡通信了,使用java nio是可以實現一個通信框架的,但這屬於高難度動作——專家模式。就碼農way而言,使用netty通信框架,省事省力,經過測試完善的框架也不容易出錯

服務發布的問題

一般情況,如果客戶端依賴的服務掛掉或者切換地址等,那么客戶端可能就無法工作或者需要改變配置。為了能夠達到自動切換服務、尋址等問題,就需要一個服務注冊和發現功能的框架。市面上流行的是zookeeper,他可以將上線的服務注冊進去,提供給客戶端調用。zookeeper會不斷對服務進行心跳檢測,一旦服務掛掉,就會在注冊中心把他消掉。客戶端可以在注冊中心切換到其他可用的服務

zookeeper的服務注冊格式:/{service}/{version}/{ip:port}

關於RPC框架的初體驗

這里並不是商用的RPC框架,沒有服務治理、插件支持等功能,使用的是@黃勇寫的輕量級分布式 RPC 框架,目的在於理解rpc框架核心代碼的功能模塊結構、相關技術選型以及如何運行等幾個問題

關於框架的幾點理解

  • rpc-sample-api模塊,定義了服務接口,這個代碼無論客戶端和服務端都需要用到的
  • rpc-sample-server模塊,對rpc-sample-api的接口進行了實現,啟動RpcBootstrap類,就會將rpc-server模塊寫的RPCServer和注入容器中。這個模塊相當於前面LBS大大圖片里的server端,真正提供服務的實現的模塊
  • rpc-server模塊,相當於server stub,他負責將掃描到的被@RpcService注解的類注冊到zookeeper,對請求、返回值消息進行序列化、編解碼,處理請求等
  • rpc-client模塊,就相當於client stub,他負責將client的請求進行編碼,發送出去,到zookeeper注冊中心去發現可用服務,進行調用
  • rpc-register-zookeeper模塊,該模塊的ZookeeperServiceDiscovery類為rpc-client模塊提供服務發現功能。而zookeeperServiceRegistry類為rpc-server模塊提供了服務注冊的功能。其實就是實例化一個ZkClient對zookeeper服務進行訪問,然后對zookeeper進行注冊服務和發現服務
  • rpc-common模塊,定義了一些工具類和消息對象。消息對象用於封裝請求和返回值消息,工具類主要用於序列化、編解碼等功能

最后,由於本人之前並沒有對nettyprotobuf等工具有詳細了解,代碼細節無法詳述,這里只是簡單地歸納出該框架的幾點模塊關系以及作用

運行步驟

這里主要是本人運行該框架的幾個步驟,其實非常簡單

  • 下載源碼到IDEA,地址https://gitee.com/huangyong/rpc.git
  • 安裝、啟動zookeeper服務,不了解的童鞋可以參考 zookeeper安裝和使用 windows環境
  • 啟動rpc-server,就是rpc-sample-server下的RpcBootstrap類即可,這邊服務端就算啟用了

image

  • 接下來運行rpc-sample-client下面的幾個類,可以看到客戶端代碼其實是通過RpcProxy.create(...)獲取實例,並得到了返回值

image

小結

本文總結了RPC服務是做什么的以及RPC框架相關的幾個概念,接下來描述了如果我們自己寫RPC框架需要解決的幾個問題。並且使用@黃勇童鞋的開源demo,進行rpc使用的初體驗,勉強對rpc框架有了基本的認識。如果想深入使用、了解的童鞋可以嘗試使用阿里的hsf、谷歌的gRpc構建自己的微服務應用或者分布式計算等

參考

你應該知道的RPC原理

輕量級分布式 RPC 框架


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM