让我带你弄明白什么是RPC ,帮你整理一下你的小脑瓜!
一、系統架構的演變
1、單一應用架構
將所有的功能模塊都放在1個工程中編碼、編譯、打包并且部署在1個tomcat容器中的架構。這樣維護成本比較低。
優點:
缺點:
隨著時間推移業務增加,功能不斷迭代,項目會變得臃腫,業務耦合嚴重
新增業務困難
核心業務與邊緣業務混在一塊兒,出現問題相互影響。
2、垂直架構
為了解決單體框架出現的問題,開始按著業務做垂直劃分。把原來的一個單體拆成一堆單體應用,這時候就由原來的單應用變成多應用部署。
優點:
缺點:
3、SOA架構
【領取資料】 即面向服務的架構。其思想就是根據實際業務,把業務拆分成合適的、獨立部署的模塊,模塊之間相互獨立(通過Webservice/Double等技術進行通信)
二、RPC
1、RPC核心和調用的大體流程
1)RPC(remote procedure call) 遠程過程調用,簡單的理解是一個節點請求另外1個節點的服務。
調用過程:
客戶端(Client):服務調用。
客戶端存根(Client Stub):存放服務端地址信息,將客戶端的請求參數數據信息打包成網絡消息, 再通過網絡傳輸發送給服務端。
服務端存根(Server Stub):接受客戶端發送過來的消息并解包,再調用本地服務進行處理。
服務端(Server):服務的真正提供者。
Network Service:底層傳輸,可以是 TCP 或 HTTP
2、完整的RPC架構圖
在一個典型RPC的使用場景中,包括了服務發現、負載、容錯、網絡傳輸、序列化等組件,其中RPC協議就指了程序如何進行網絡傳輸和序列化。
3、RPC核心功能及實現
服務尋址
數據流的序列化和反序列化
三、網絡傳輸
1、服務尋址
2、序列化和反序列化
本地調用,我們只需要把參數壓到棧里,然后然函數直接從棧里讀就行。但是在遠程調用時客戶端和服務端是不同的進程,不能通過內存傳遞參數。這時就需要客戶端把參數轉換成一個字節流,傳給服務端后,再把字節流轉成自己能讀取的格式。
定義:
序列化:將對象轉換轉換成二進制流程的過程叫做序列化
反序列化:將二進制流轉換成對象的過程叫做反序列化
3、網絡傳輸
【領取資料】 網絡傳輸層需要把call ID和序列化的參數字節流傳給服務端,然后再把序列化好的調用結果傳給客戶端。
所以,要實現一個RPC框架,只需要把以下三點實現了就基本完成; :
四、Dubbo
經典的RPC框架
調用關系說明:?
Config 配置中心
Proxy 代理
Registry 注冊中心
Cluster 負載均衡、路由(輪詢、權重、一致性hash)
Monitor 監控
Protocal 發起調用
Exchange 交換
Transport 傳輸(netty)
Serialize 序列化
dubbo 架構特點分別是連通性、健壯性、伸縮性、以及向未來架構的升級
連通性
- 注冊中心負責服務地址的注冊與查找,相當于目錄服務,服務提供者和消費者只在啟動時與注冊中心交互,注冊中心不轉發請求,壓力較小
- 監控中心負責統計各服務調用次數,調用時間等,統計先在內存匯總后每分鐘一次發送到監控中心服務器,并以報表展示
- 服務提供者向注冊中心注冊其提供的服務,并匯報調用時間到監控中心,此時間不包含網絡開銷
- 服務消費者向注冊中心獲取服務提供者地址列表,并根據負載算法直接調用提供者,同時匯報調用時間到監控中心,此時間包含網絡開銷
- 注冊中心,服務提供者,服務消費者三者之間均為長連接,監控中心除外
- 注冊中心通過長連接感知服務提供者的存在,服務提供者宕機,注冊中心將立即推送事件通知消費者
- 注冊中心和監控中心全部宕機,不影響已運行的提供者和消費者,消費者在本地緩存了提供者列表
- 注冊中心和監控中心都是可選的,服務消費者可以直連服務提供者 監控中心宕掉不影響使用,只是丟失部分采樣數據
- 數據庫宕掉后,注冊中心仍能通過緩存提供服務列表查詢,但不能注冊新服務
- 注冊中心對等集群,任意一臺宕掉后,將自動切換到另一臺 注冊中心全部宕掉后,服務提供者和服務消費者仍能通過本地緩存通訊
- 服務提供者無狀態,任意一臺宕掉后,不影響使用
- 服務提供者全部宕掉后,服務消費者應用將無法使用,并無限次重連等待服務提供者恢復
- 注冊中心為對等集群,可動態增加機器部署實例,所有客戶端將自動發現新的注冊中心
- 服務提供者無狀態,可動態增加機器部署實例,注冊中心將推送新的服務提供者信息給消費者
?
健壯性
- 監控中心宕掉不影響使用,只是丟失部分采樣數據
- 數據庫宕掉后,注冊中心仍能通過緩存提供服務列表查詢,但不能注冊新服務
- 注冊中心對等集群,任意一臺宕掉后,將自動切換到另一臺
- 注冊中心全部宕掉后,服務提供者和服務消費者仍能通過本地緩存通訊
- 服務提供者無狀態,任意一臺宕掉后,不影響使用
- 服務提供者全部宕掉后,服務消費者應用將無法使用,并無限次重連等待服務提供者恢復
伸縮性
- 注冊中心為對等集群,可動態增加機器部署實例,所有客戶端將自動發現新的注冊中心
- 服務提供者無狀態,可動態增加機器部署實例,注冊中心將推送新的服務提供者信息給消費者
五、Springboot 中Dubbo使用
1、安裝
2、使用方式
配置類、注解方式
Service 一定要引入dubbo的注解。
看官網
3、超時配置
【領取資料】
<dubbo:reference interface="com.foo.BarService" check="false"timeout="1000"/>配置超時時間的優先順序如下:
其中,服務提供方配置,通過URL經由注冊中心傳遞給消費方。
Dubbo常用的配置
啟動檢查
<dubbo:reference interface="com.foo.BarService" check="false" />超時配置
<dubbo:reference interface="com.foo.BarService" check="false"timeout="1000"/>重試次數
冪等(設置重試次數,查詢、刪除、修改**) 非冪等(不能設置,新增)
<dubbo:reference id="orderService"interface="com.end.dubbo.api.service.OrderService" retries="3" />多版本分組
<dubbo:reference id="orderService"interface="com.end.dubbo.api.service.OrderService" group="g1" />六、api 和spi
Spi:調用方來定制接口,實現方來針對接口實現不同的實現。調用方來選擇自己需要的實現方法。
常見的spi:
JDK中的spi實現方式
原理:
在ServiceLoader的load方法中首先會獲取上下文類加載器,然后構造一個ServiceLoader,在 ServiceLoader中有一個懶加載器,懶加載器會通過BufferedReader來從META-INF/services路徑 下讀取 對應的接口名的全路徑名文件,也就是我們配置的文件,然后通過文件的類解析器讀取文件中的內 容,再通過類加載器加載類的全路徑。
缺點:
dubbo中的spi實現方式
man=dubbo.impl.Man
woman=dubbo.impl.Woman
可以按需加載,可擴展的能力
七、線程派發模型
1、配置
<dubbo:protocol name="dubbo" port="20880" threadpool="fixed" threads="200"iothreads="8" accepts="0" queues="100" dispatcher="all"/>Netty
在netty中存在兩種線程:boss線程和worker線程
1)boss線程
作用:accept客戶端的連接:將接收到的連接注冊到一個worker線程上。
通常情況下,服務端每綁定一個端口,開啟一個boss線程
2)worker線程
作用:處理注冊在其身上的連接connection上的各種io事件
個數:核數+1
注意:一個worker線程可以注冊多個connection;
一個connection只能注冊在一個worker線程上
八、線程池的5種派發策略
默認是all:所有消息都派發到線程池,包括請求,響應,連接事件,斷開事件,心跳等。 即 worker線程接收到事件后,將該事件提交到業務線程池中,自己再去處理其他事。
- direct:worker線程接收到事件后,由worker執行到底(所有消息都不派發到線程池,全部在 Io線程上直接執行)。
- message:只有請求響應消息派發到線程池,其它連接斷開事件,心跳等消息,直接在 IO線 程上執行
- **execution:**只請求消息派發到線程池,不含響應(客戶端線程池),響應和其它連接斷開事 件,心跳等消息,直接在 IO 線程上執行
- **connection:**在 IO 線程上,將連接斷開事件放入隊列,有序逐個執行,其它消息派發到線程
dubbo4個常用的threadpool:
fixed 固定大小線程池,啟動時建立線程,不關閉,一直持有。
cached 緩存線程池,空閑一分鐘自動刪除,需要時重建。
limited 可伸縮線程池,但池中的線程數只會增長不會收縮。只增長不收縮的目的是為了避免收縮時突然帶來大流量引起性能問題.
eager 優先創建Worker線程池。在任務數量大于corePoolSize但是小于maximumPoolSize時,優先創建Worker來處理任務。當任務數量大于maximumPoolSize時,將任務放入阻塞隊列中。阻塞隊列充滿時拋出RejectedExecutionException。(相比于cached:cached在任務數量超過maximumPoolSize時直接拋出異常而不是將任務放入阻塞隊列)
?
Dubbo的線程派發模型
整體步驟:(受限于派發策略,以默認的all為例)
客戶端的主線程發出一個請求后獲得future,在執行get時進行阻塞等待;
服務端使用worker線程(netty通信模型)接收到請求后,將請求提交到server線程池中進行處理!
server線程處理完成之后,將相應結果返回給客戶端的worker線程池(netty通信模型),最后,worker線程將響應結果提交到client線程池進行處理!
client線程將響應結果填充到future中,然后喚醒等待的主線程,主線程獲取結果,返回給客戶端。
最后
最近我整理了整套《JAVA核心知識點總結》,說實話 ,作為一名Java程序員,不論你需不需要面試都應該好好看下這份資料。拿到手總是不虧的~我的不少粉絲也因此拿到騰訊字節快手等公司的Offer
進【Java進階之路群】,找管理員獲取哦-!
?
?
?
總結
以上是生活随笔為你收集整理的让我带你弄明白什么是RPC ,帮你整理一下你的小脑瓜!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RobotFrameWork Web自动
- 下一篇: 【BLENDER】-渲染 背景设置