分散式系統常見問題總結(四)- 應用間通訊
分散式系統間通訊的常見方式有兩種,一種是訊息通訊,比如JMS,RocketMQ等,一種是RPC遠端呼叫。我們先來看一下通訊的基礎知識,然後主要來看一下RPC遠端呼叫,訊息通訊大家可以參考我的下一篇文章——分散式常見問題總結(五)- 訊息佇列。
1.傳輸協議 - HTTP,TCP,UDP
看下面的圖,網路通訊按照OSI參考模型分為七層,按照TCP/IP模型分為五層。我們關注的應用層協議有HTTP,Telnet,FTP,TFTP,DNS,SMTP協議。傳輸層的協議有TCP,UDP。
我們來區分下下面幾個概念:
HTTP:超文字傳輸協議,應用層協議,基於傳輸層協議TCP。
TCP:面向連線的傳輸控制協議,傳輸層協議。通訊前需要建立可靠的連線。
UDP:面向無連線的使用者資料報協議,傳輸層協議。通訊前不需要建立連線。
SOCKET:不是協議,是TCP或者UDP協議的具體實現API。
短連線:建立連線,傳送完資料,關閉連線,TCP可以實現短連線,因為HTTP基於TCP,也可實現短連線。對於傳輸資料不頻繁的情況下用短連線。
長連線:建立連線,傳送完資料,保持連線一段時間,TCP可以實現長連線,因為HTTP基於TCP,也可實現長連線。對於傳輸資料頻繁的情況下用長連線。
TCP三次握手四次揮手
TCP通訊之前需要建立連線,我們來簡單的瞭解下。
SYN:同步序號
ACK:應答回覆
三次握手:
a.客戶端 -> 伺服器,傳送SYN請求連線。
b.伺服器 ->客戶端,傳送ACK確認收到請求,傳送SYN是否準備好連線。 (這裡的ACK應答回覆和SYN同步序號是一起傳送的)
c.客戶端 -> 伺服器,傳送ACK確認可以建立連線和通訊。
四次揮手:
a.客戶端 -> 伺服器,傳送SYN請求關閉連線。
b.伺服器 -> 客戶端,傳送ACK確認收到請求,關閉客戶端到伺服器的連線。
c.伺服器 -> 客戶端,傳送SYN請求關閉連線。
d.客戶端 -> 伺服器,傳送ACK確認收到請求,關閉伺服器到客戶端的連線。
b和c不同同時傳送的原因是TCP連線是雙向的,伺服器需要等到伺服器這邊沒有資料傳送才傳送SYN請求關閉連線。ACK和SYN不能同時傳送,所以揮手是四次。
2.網路IO
上面講了通訊協議,基於通訊協議有三種通訊方式:BIO,NIO,AIO。
首先BIO,NIO,AIO都是基於socket套接字來通訊的,socket是傳輸層協議TCP/UDP的具體實現。
BIO:同步阻塞IO,每一個Socket使用一個執行緒來通訊。阻塞表現在,主執行緒呼叫write()方法後,不能做其他事情,阻塞了,等待返回。
NIO:同步非阻塞IO,採用Reactor模式,使用一個執行緒來管理所有的Socket,簡單來說,Channel註冊到Selector,一個執行緒來遍歷Selector通過Channel來通訊。Channel通訊是基於Socket. 有通訊的時候會處理。非阻塞表現在,主執行緒不會阻塞,會有單獨的一個執行緒來處理接受讀操作。同步表現在,如果一個Socket通訊有問題,會影響其它的Socket通訊。
AIO:非同步IO,採用Proactor模式,另外開執行緒來通訊,通訊完成會呼叫類似的回撥函式來通知。我們不用單獨建立執行緒來處理通訊,Java自己會建立一個執行緒池處理通訊,並回調對應的方法。多個通訊之間不會互相影響。
3.RPC遠端呼叫
RPC(Remote Procedure Call)的含義簡單的來說,RPC是程序間通訊的一種方式,它讓我們可以向訪問遠端介面像本地介面一樣。它幫助我們隱藏呼叫的細節。
RPC呼叫需要考慮的兩個關鍵問題
a.遠端通訊協議的選擇,例如Http,基於TCP或者UDP的socket等。
b.資料傳輸的格式,例如Java Object,xml,json,binary等。
基於通訊協議和資料傳輸格式的選擇,出現了很多RPC框架,下面我們來一個個看一下。
a.RMI(遠端方法呼叫)
RMI是Java定製的遠端方法呼叫。通訊是基於socket的通訊,資料傳輸的格式是Java Object,所以傳輸的物件必須序列化,導致了RMI只適合兩個Java應用程式的通訊。通訊大致過程如下:
Java Object -> 序列化 -> 遠端傳輸(Socket) -> 反序列化 -> Java Object
b.XML-RPC,SOAP,WebService
通訊是基於Http的通訊,資料傳輸格式是XML。所以這個通訊架構是可以跨語言的。通訊大致過程如下:
需要傳輸的物件 -> XML -> 遠端傳輸(Http) -> 解析XML -> 需要傳輸的物件
c.binary-RPC, hessian
通訊是基於Http的通訊,資料傳輸格式是二進位制格式。所以這個通訊架構是可以跨語言的。通訊大致過程如下:
需要傳輸的物件 -> 二進位制格式 -> 遠端傳輸(Http) -> 解析二進位制 -> 需要傳輸的物件
d.我們可以自己實現一個簡單的RPC框架
通訊可以基於Http,可以使用java提供的Httpclient來通訊,資料傳輸格式可以是Json。通訊大致過程如下:
需要傳輸的物件 -> Json -> 遠端傳輸(Http) -> 解析Json -> 需要傳輸的物件
現在應用直接的通訊架構太多了,我們學習一個應用間通訊架構可以主要關注他的通訊協議和資料傳輸格式。