菜菜哥,我最近終於把Socket通訊調通了web
這麼底層的東西你如今都會了,恭喜你離漲薪又進一步呀編程
http協議不也是利用的Socket嗎數組
能夠這麼說,http協議是基於TCP協議的,底層的數據傳輸能夠說是利用的socket瀏覽器
既然Socket通訊會了,那一個rpc的框架不就很容易就能實現了嗎?緩存
一個比較完備的rpc框架可能並不是像你所想那樣簡單,要否則人人均可以出RPC框架了服務器
有那麼難嗎?我以爲沒有那麼難呀網絡
若是你能解決掉這些問題,我以爲你真的是大牛了架構
RPC是遠程過程調用(Remote Procedure Call)的縮寫形式,是在多任務操做系統或聯網的計算機之間運行的程序和進程所用的通訊技術框架
擼碼的人都應該知道,現代編程中最經常使用的系統之間通訊方式是:http調用和rpc調用。對於同一個網絡或者說是互通的網絡環境中,rpc調用方式是系統間通訊交互最經常使用的方式,比基於http協議的通訊方式性能高出數倍甚至數個量級。我司的平臺rpc通訊,每秒在幾萬甚至更高,每次調用的通訊時間在必定程度上幾乎能夠忽略不計,再加上咱們首席架構師深厚的系統設計功力,採用進程內緩存等等優化措施,一次rpc調用的總體平均時間也在一毫秒之下。這是http協議沒法達到的速度,若是你在瀏覽器的F12的窗口觀察過,一個http協議調用若是總體花費的時間在5毫秒甚至10毫秒,那麼其實就能夠認爲這個http請求響應時間是很短的了。異步
因此絕大部分公司內部的系統之間通訊都會採用rpc調用這種方式。這裏不要擡槓,若是你的公司內部系統通訊採用的是基於http協議的,那說明大家的系統頗有可能沒有性能的要求。
RPC調用雖然簡化了擼碼的難度,可是想要實現一套rpc框架,何止容易,一套優秀的rpc框架,更是難如登天。
多數rpc框架的服務端以service的方式來運行,爲了不和其餘進程發生監聽端口的衝突,通常會隨機選擇一個端口來進行監聽。雖然這看上去很好,可是卻給client端帶來了麻煩,若是服務端監聽固定端口,client鏈接服務端的時候,最少能夠在代碼中固定寫死服務端的IP和端口。可是如今服務端監聽的端口是隨機的,並且更可怕的是服務器有可能會更換或者切換IP,那client怎麼才能正確的去和服務端創建鏈接呢?
服務端之因此會採用這種隨機方式來監聽端口,其中很大一個緣由是爲了之後擴容。client如何正確的去鏈接服務器則採用了一個集中式的方案,服務端引入了一個服務註冊中心的概念,有的系統可能會以別的名稱來體現,可是做用是相似的。這個註冊中心存儲着全部的服務端信息,其中包括每一個服務端的IP和端口,有的甚至還有版本信息,每一個服務端進程啓動的時候,都是採用主動鏈接註冊中心,主動註冊的方式。client端在發起鏈接服務的時候,首先去註冊中心查找已經註冊的服務端信息,而後進行鏈接。這樣rpc調用在某種程度上在鏈接步驟就實現了「自動化」。
當client和服務端創建tcp鏈接以後(有的rpc框架會採用udp協議),下一個問題就是client和服務端怎麼相認的問題了。舉個栗子:客戶端想要實現一個獲取用戶姓名的方法,方法名怎麼定義才能讓服務端正確識別出來呢?是傳一個字符串「GetName」,仍是傳一個整數1來表明呢?服務端的返回結果,若是發生異常改如何返回呢?
當咱們在本地調用一個函數,語法,語義,以及語法語義的分析,編譯器已經幫咱們作好了這些,可是rpc是遠程過程調用,雖然表面上和本地相似,可是已經出現了跨網絡的狀況,語法語義等等這些分析須要client和服務端協商一致。
其實現代幾乎大部分rpc通訊都遵循一個標準:
當client發起一個遠程調用的時候,它首先會先調用本地的Stub,它負責將調用的接口,函數以及參數按照約定好的協議格式進行編碼,而後經過本地的Runtime進行傳輸,最後經過網卡將數據包發送到指定的服務器。
服務器Runtime接收到請求以後,會首先調用本地的Stub按照約定好的協議格式進行解碼,最後調用服務端具體的函數。函數執行完畢,把結果利用本地的Stub編碼以後經過runtime發送給客戶端。客戶端Runtime接收到消息利用本地Stub進行解碼,而後進行其餘處理。
因而可知,現代的rpc框架實際上是把協議的封裝和數據的發送分別抽象成了單獨的層。Stub負責協議部分,Runtime處理數據發送以及網絡相關部分。
數據經過網絡傳輸過程當中,每一個數據包的完整性如何來識別,若是是一個簡單int型數據很簡單,可是若是是一個類或者一個數組,甚至是其餘變長的類型,rpc的通訊協議如何約束這些,若是能正確識別出來數據是協議部分最難處理的部分。更況且還有大頭小頭編碼的問題。
凡是基於網絡傳輸的形式,任何通訊都是不可靠的,網絡本質是不可靠的。包括網絡抖動,錯誤等形成的丟包,粘包現象,如何正確的處理也是一個rpc通訊中很重要的部分。一個rpc請求失敗,是直接丟棄仍是重試,這些策略都須要去規定。
1.一個rpc調用若是採用同步的方式,性能會大大打折扣,如何實現rpc的異步調用,這是一個rpc是否優秀的重要指標。
2.不管rpc的網絡傳輸多麼優秀,都會有性能損耗,可否把某些結果數據設置緩存?
3.不管是client仍是服務端,處理請求的線程可否重用(線程池)?
4.可否支持多語言呢?
socket雖易,RPC卻難