既然有 HTTP 協(xié)議,為什么還要有 RPC
HTTP和RPC
什么是HTTP
HTTP協(xié)議(Hyper Text Transfer Protocol),又叫做超文本傳輸協(xié)議。平時(shí)上網(wǎng)在瀏覽器上敲個(gè)網(wǎng)址就能訪問網(wǎng)頁,這里用到的就是HTTP協(xié)議。
什么是RPC
RPC(Remote Procedure Call),又叫做遠(yuǎn)程過程調(diào)用。它并不是一個(gè)具體的協(xié)議,而是一種調(diào)用方式。
像之前的單體時(shí)代,我們的 service 調(diào)用就是自己實(shí)現(xiàn)的方法,是本地進(jìn)程內(nèi)的調(diào)用。
public User getUserById(Long id) {
return userDao.getUserById(id); // 這叫本地調(diào)用
}
現(xiàn)在都是微服務(wù)了,根據(jù)業(yè)務(wù)模塊做了不同的拆分,像用戶的服務(wù)不用我這個(gè)小組負(fù)責(zé),我這小組只要寫訂單服務(wù)就行了。
但是我們服務(wù)需要用到用戶的信息,于是我們需要調(diào)用用戶小組的服務(wù),于是代碼變成了以下這種
public User getUserById(Long id) {
return userConsumer.getUserById(id); // 遠(yuǎn)程調(diào)用
}
我們像調(diào)用本地方法那樣去調(diào)用它,屏蔽掉一些網(wǎng)絡(luò)細(xì)節(jié),這樣用起來豈不是很方便。
值得注意的是,雖然大部分RPC協(xié)議底層使用TCP,但實(shí)際上它們不一定非得使用TCP,改用UDP或者HTTP,其實(shí)也可以做到類似的功能。
既然有RPC了,為什么還要有HTTP?
RPC 調(diào)用使用的場(chǎng)景更多的公司內(nèi)部的多個(gè)服務(wù)之間的通信。
服務(wù)的拆分獨(dú)立部署,那服務(wù)間的調(diào)用就必然需要網(wǎng)絡(luò)通信,用 Http的方式 調(diào)用當(dāng)然可行,但是比較麻煩。
想要服務(wù)被拆分了但是使用起來還是和之前本地調(diào)用一樣方便,所以就出現(xiàn)了 RPC 框架,來屏蔽這些底層調(diào)用細(xì)節(jié),使得我們編碼上還是和之前本地調(diào)用相差不多。
HTTP 協(xié)議比較的冗余,RPC 都是內(nèi)部調(diào)用所以不需要太考慮通用性,只要公司內(nèi)部保持格式統(tǒng)一即可。
HTTP和RPC有什么區(qū)別
我們來看看RPC和HTTP區(qū)別比較明顯的幾個(gè)點(diǎn)。
服務(wù)發(fā)現(xiàn)
首先要向某個(gè)服務(wù)器發(fā)起請(qǐng)求,你得先建立連接,而建立連接的前提是,你得知道IP地址和端口。這個(gè)找到服務(wù)對(duì)應(yīng)的IP端口的過程,其實(shí)就是服務(wù)發(fā)現(xiàn)。
在HTTP中,你知道服務(wù)的域名,就可以通過DNS服務(wù)去解析得到它背后的IP地址。
而RPC的話,就有些區(qū)別,一般會(huì)有專門的中間服務(wù)去保存服務(wù)名和IP信息,比如consul。想要訪問某個(gè)服務(wù),就去這些中間服務(wù)去獲得IP和端口信息。
底層連接形式
以主流的HTTP1.1協(xié)議為例,其默認(rèn)在建立底層TCP連接之后會(huì)一直保持這個(gè)連接(keep alive),之后的請(qǐng)求和響應(yīng)都會(huì)復(fù)用這條連接。
RPC,也跟HTTP類似,也是通過建立TCP長鏈接進(jìn)行數(shù)據(jù)交互,但不同的地方在于,RPC協(xié)議一般還會(huì)再建個(gè)連接池,在請(qǐng)求量大的時(shí)候,建立多條連接放在池內(nèi),要發(fā)數(shù)據(jù)的時(shí)候就從池里取一條連接出來,用完放回去,下次再復(fù)用,可以說非常環(huán)保。
由于連接池有利于提升網(wǎng)絡(luò)請(qǐng)求性能,所以不少編程語言的網(wǎng)絡(luò)庫里都會(huì)給HTTP加個(gè)連接池,比如go就是這么干的。這一塊兩者也沒太大區(qū)別。
傳輸?shù)膬?nèi)容
基于TCP傳輸?shù)南ⅲ篽eader是用于標(biāo)記一些特殊信息、body則是放我們真正需要傳輸?shù)膬?nèi)容。
可以看到像header里的很多信息,其實(shí)如果我們約定好之后,就不用每次都傳輸了,比如"content-type"這個(gè)字段。
RPC,因?yàn)樗ㄖ苹潭雀?,可以采用體積更小的protobuf或其他序列化協(xié)議去保存結(jié)構(gòu)體數(shù)據(jù),同時(shí)也不需要像HTTP那樣考慮各種瀏覽器行為,比如302重定向跳轉(zhuǎn)什么的。因此性能也會(huì)更好一些。
HTTP原理
RPC原理