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