微服務(wù)調(diào)用為什么用RPC框架?
RPC是一種概念,http是RPC實(shí)現(xiàn)的一種方式,用http交互其實(shí)就已經(jīng)屬于rpc了!
RPC 協(xié)議名詞解釋在一個典型RPC的使用場景中,包含了服務(wù)發(fā)現(xiàn)、負(fù)載、容錯、網(wǎng)絡(luò)傳輸、序列化等組件,其中RPC協(xié)議就指明了程序如何進(jìn)行網(wǎng)絡(luò)傳輸和序列化 。也就是說一個RPC協(xié)議的實(shí)現(xiàn)就等于一個非透明的RPC調(diào)用,如何做到的的呢?
RPC 協(xié)議的組成1.地址:服務(wù)提供者地址
2.端口:協(xié)議指定開放的端口
3.運(yùn)行服務(wù)
nettyminaRMI服務(wù)servlet容器(jetty/tomcat/Jboss)4.報文編碼:協(xié)議報文編碼 。注①:http 報文編碼 。注②:Dubbo 報文編碼
5.序列化方式
Hessian2SerializationDubboSerializationJavaSerializationJsonSerializationRPC協(xié)議報文編碼與實(shí)現(xiàn)詳解1、HTTP協(xié)議報文
2、Dubbo協(xié)議報文
協(xié)議編解碼過程Dubbo 支持的RPC協(xié)議列表1、dubbo
實(shí)現(xiàn)描述: 傳輸服務(wù): mina, netty(默認(rèn)), grizzy序列化: dubbo, hessian2(默認(rèn)), java, fastjson 自定義報文
連接描述:
單個長連接NIO異步傳輸
適用場景:
1、常規(guī)RPC調(diào)用2、傳輸數(shù)據(jù)量小 3、提供者少于消費(fèi)者
2、rmi
實(shí)現(xiàn)描述:
傳輸:java rmi 服務(wù)序列化:java原生二進(jìn)制序列化
連接描述:
多個短連接BIO同步傳輸
適用場景:
1、常規(guī)RPC調(diào)用2、與原RMI客戶端集成 3、可傳少量文件 4、不支持防火墻穿透
3、hessian
實(shí)現(xiàn)描述:
傳輸服務(wù):servlet容器序列化:hessian二進(jìn)制序列化
連接描述:
基于Http 協(xié)議傳輸,依懶servlet容器配置
適用場景:
1、提供者多于消費(fèi)者2、可傳大字段和文件 3、跨語言調(diào)用
4、http
實(shí)現(xiàn)描述:
傳輸服務(wù):servlet容器序列化:http表單
連接描述:
依懶servlet容器配置
適用場景:
1、數(shù)據(jù)包大小混合
RPC 傳輸實(shí)現(xiàn)RPC的協(xié)議的傳輸是基于 TCP/IP 做為基礎(chǔ)使用Socket 或Netty、mina等網(wǎng)絡(luò)編程組件實(shí)現(xiàn)。但有個問題是TCP是面向字節(jié)流的無邊邊界協(xié)議,其只管負(fù)責(zé)數(shù)據(jù)傳輸并不會區(qū)分每次請求所對應(yīng)的消息,這樣就會出現(xiàn)TCP協(xié)義傳輸當(dāng)中的拆包與粘包問題
拆包與粘包產(chǎn)生的原因們知道tcp是以流動的方式傳輸數(shù)據(jù),傳輸?shù)淖钚挝粸橐粋€報文段(segment)。tcp Header中有個Options標(biāo)識位,常見的標(biāo)識為mss(Maximum Segment Size)指的是,連接層每次傳輸?shù)臄?shù)據(jù)有個最大限制MTU(Maximum Transmission Unit),一般是1500比特,超過這個量要分成多個報文段,mss則是這個最大限制減去TCP的header,光是要傳輸?shù)臄?shù)據(jù)的大小,一般為1460比特。換算成字節(jié),也就是180多字節(jié)。
tcp 為 提高性能,發(fā)送端會將需要發(fā)送的數(shù)據(jù)發(fā)送到緩沖區(qū),等待緩沖區(qū)滿了之后,再將緩沖中的數(shù)據(jù)發(fā)送到接收方。同理,接收方也有緩沖區(qū)這樣的機(jī)制,來接收數(shù)據(jù)。這時就會出現(xiàn)以下情況:
應(yīng)用程序?qū)懭氲臄?shù)據(jù)大于MSS大小,這將會發(fā)生拆包應(yīng)用程序?qū)懭霐?shù)據(jù)小于MSS大小,這將會發(fā)生粘包接收方法不及時讀取套接字緩沖區(qū)數(shù)據(jù),這將發(fā)生粘包。拆包與粘包解決辦法設(shè)置定長消息,服務(wù)端每次讀取既定長度的內(nèi)容作為一條完整消息{"type":"message","content":"hello"}\n使用帶消息頭的協(xié)議、消息頭存儲消息開始標(biāo)識及消息長度信息,服務(wù)端獲取消息頭的時候解析出消息長度,然后向后讀取該長度的內(nèi)容。