RPC簡介及框架選擇

簡單介紹RPC協議及常見框架,對比傳統restful api和RPC方式的優缺點。常見RPC框架,gRPC及序列化方式Protobuf等html

HTTP協議

http協議是基於tcp協議的,tcp協議是流式協議,包頭部分能夠經過多出的\r\n來分界,包體部分如何分界呢?這是協議自己要解決的問題。目前通常有兩種方式,第一種方式就是在包頭中有個content-Length字段,這個字段的值的大小標識了POST數據的長度,服務器收到一個數據包後,先從包頭解析出這個字段的值,再根據這個值去讀取相應長度的做爲http協議的包體數據。
瀏覽器connect 80端口python

RESTful API (http+json)

理解RESTful架構 - 阮一峯
REST 架構該怎麼生動地理解? - 覃超的回答 - 知乎linux

網站即軟件,並且是一種新型的軟件,這種"互聯網軟件"採用客戶端/服務器模式,創建在分佈式體系上,經過互聯網通訊,具備高延時(high latency)、高併發等特色。
  它首次出如今 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規範的主要編寫者之一。Representational State Transfer,翻譯是」表現層狀態轉化」,通俗來說就是:資源在網絡中以某種表現形式進行狀態轉移。
總結一下什麼是RESTful架構:
  (1)每個URI表明一種資源;
  (2)客戶端和服務器之間,傳遞這種資源的某種表現層,好比用JSON,XML,JPEG等;
  (3)客戶端經過四個HTTP動詞,對服務器端資源進行操做,實現"表現層狀態轉化"。nginx

URL定位資源,用HTTP動詞(GET,POST,DELETE,DETC)描述操做。
用HTTP協議裏的動詞來實現資源的添加,修改,刪除等操做。即經過HTTP動詞來實現資源的狀態扭轉:
  GET 用來獲取資源,
  POST 用來新建資源(也能夠用於更新資源),
  PUT 用來更新資源,
  DELETE 用來刪除資源。golang

RPC

進程間通訊(IPC,Inter-Process Communication),指至少兩個進程或線程間傳送數據或信號的一些技術或方法。進程是計算機系統分配資源的最小單位。每一個進程都有本身的一部分獨立的系統資源,彼此是隔離的。爲了能使不一樣的進程互相訪問資源並進行協調工做,纔有了進程間通訊。這些進程能夠運行在同一計算機上或網絡鏈接的不一樣計算機上。 進程間通訊技術包括消息傳遞、同步、共享內存和遠程過程調用。 IPC是一種標準的Unix通訊機制。web

有兩種類型的進程間通訊(IPC)。spring

  • 本地過程調用(LPC)LPC用在多任務操做系統中,使得同時運行的任務能互相會話。這些任務共享內存空間使任務同步和互相發送信息。
  • 遠程過程調用(RPC)RPC相似於LPC,只是在網上工做。RPC開始是出如今Sun微系統公司和HP公司的運行UNIX操做系統的計算機中。

爲何RPC呢?就是沒法在一個進程內,甚至一個計算機內經過本地調用的方式完成的需求,好比好比不一樣的系統間的通信,甚至不一樣的組織間的通信。因爲計算能力須要橫向擴展,須要在多臺機器組成的集羣上部署應用apache

RPC的核心並不在於使用什麼協議。RPC的目的是讓你在本地調用遠程的方法,而對你來講這個調用是透明的,你並不知道這個調用的方法是部署哪裏。經過RPC能解耦服務,這纔是使用RPC的真正目的。RPC的原理主要用到了動態代理模式,至於http協議,只是傳輸協議而已。簡單的實現能夠參考spring remoting,複雜的實現能夠參考dubbo。django

簡單的說,json

  • RPC就是從一臺機器(客戶端)上經過參數傳遞的方式調用另外一臺機器(服務器)上的一個函數或方法(能夠統稱爲服務)並獲得返回的結果。
  • RPC 會隱藏底層的通信細節(不須要直接處理Socket通信或Http通信) RPC 是一個請求響應模型。
  • 客戶端發起請求,服務器返回響應(相似於Http的工做方式) RPC 在使用形式上像調用本地函數(或方法)同樣去調用遠程的函數(或方法)。

RPC通訊過程

RPC架構簡單理解
遠程過程調用(RPC)詳解

默認socket通訊。本地機器的RPC框架反序列化出執行結果,函數return這個結果


 
RPC通訊過程

RPC和restful api對比

* REST vs JSON-RPC? - stackoverflow
既然有http 請求,爲何還要用rpc調用? - 手不要亂摸的回答 - 知乎
爲何須要RPC,而不是簡單的HTTP接口

REST是一種設計風格,它的不少思惟方式與RPC是徹底衝突的。 RPC的思想是把本地函數映射到API,也就是說一個API對應的是一個function,我本地有一個getAllUsers,遠程也能經過某種約定的協議來調用這個getAllUsers。至於這個協議是Socket、是HTTP仍是別的什麼並不重要; RPC中的主體都是動做,是個動詞,表示我要作什麼。 而REST則否則,它的URL主體是資源,是個名詞。並且也僅支持HTTP協議,規定了使用HTTP Method表達本次要作的動做,類型通常也不超過那四五種。這些動做表達了對資源僅有的幾種轉化方式。
RPC的根本問題是耦合。RPC客戶端以多種方式與服務實現緊密耦合,而且很難在不中斷客戶端的狀況下更改服務實現。RPC更偏向內部調用,REST更偏向外部調用。

Web 服務應該算是 RPC 的一個子集,理論上 RPC 能實現的功能, 用 Web 服務也能實現,甚至不少 RPC 框架選用 HTTP 協議做爲傳輸層。
如今不少網站的 API 都是以 HTTP 服務的形式提供的,這也算是 RPC 的一種形式。

區別主要在這 2 個東西設計的出發點不太同樣:

  • HTTP 是面向瀏覽器設計的應用層協議,操做的核心在資源。咱們更多的用 Web 服務在作網站。
  • RPC 是爲了在像在本地調用一個函數那樣調用遠程的代碼而設計的,因此更關注減小本地調用和遠程調用的差別,像 SOAP(簡單對象訪問協議) 這種東西是能夠把對象當參數傳的。

咱們討論 RPC 和 Web 的區別,實際上是在談論 2 個東西:序列化協議和傳輸協議。序列化協議好比常見的 XML,JSON 和比較現代的 Protocol Buffers、Thrift。 傳輸協議好比 TCP、UDP 以及更高層的 HTTP 1.一、HTTP 2.0。

通常咱們考慮用 RPC 而不是 HTTP 構建本身的服務,一般是考慮到下面的因素:

  • 接口是否須要 Schema 約束
  • 是否須要更高效的傳輸協議(TCP,HTTP 2.0)
  • 是否對數據包的大小很是敏感

好比 HTTP 是基於文本的協議,頭部有很是多冗餘(對於 RPC 服務而言)。HTTP 中咱們用的最多就是 RESTful ,而 RESTful 是個弱 Schema 約束,你們經過文檔溝通,可是若是我就是不在實現的時候對接口文檔約定的參數作檢查,你也不能把我怎麼樣。這個時候 Thrift 這種序列化協議的優點就體現出來了,因爲 Schema 的存在,能夠保證服務端接受的參數和 Schema 保持一致。

RPC框架

誰能用通俗的語言解釋一下什麼是 RPC 框架? - 洪春濤的回答 - 知乎
經常使用的跨語言通訊方案
深刻淺出 RPC - 深刻篇

  • Call ID映射。咱們怎麼告訴遠程機器咱們要調用Multiply,而不是Add或者FooBar呢?在本地調用中,函數體是直接經過函數指針來指定的,咱們調用Multiply,編譯器就自動幫咱們調用它相應的函數指針。可是在遠程調用中,函數指針是不行的,由於兩個進程的地址空間是徹底不同的。因此,在RPC中,全部的函數都必須有本身的一個ID。這個ID在全部進程中都是惟一肯定的。客戶端在作遠程過程調用時,必須附上這個ID。而後咱們還須要在客戶端和服務端分別維護一個 {函數 <--> Call ID} 的對應表。二者的表不必定須要徹底相同,但相同的函數對應的Call ID必須相同。當客戶端須要進行遠程調用時,它就查一下這個表,找出相應的Call ID,而後把它傳給服務端,服務端也經過查表,來肯定客戶端須要調用的函數,而後執行相應函數的代碼。
  • 序列化和反序列化。客戶端怎麼把參數值傳給遠程的函數呢?在本地調用中,咱們只須要把參數壓到棧裏,而後讓函數本身去棧裏讀就行。可是在遠程過程調用時,客戶端跟服務端是不一樣的進程,不能經過內存來傳遞參數。甚至有時候客戶端和服務端使用的都不是同一種語言(好比服務端用C++,客戶端用Java或者Python)。這時候就須要客戶端把參數先轉成一個字節流,傳給服務端後,再把字節流轉成本身能讀取的格式。這個過程叫序列化和反序列化。同理,從服務端返回的值也須要序列化反序列化的過程。
  • 網絡傳輸。遠程調用每每用在網絡上,客戶端和服務端是經過網絡鏈接的。全部的數據都須要經過網絡傳輸,所以就須要有一個網絡傳輸層。網絡傳輸層須要把Call ID和序列化後的參數字節流傳給服務端,而後再把序列化後的調用結果傳回客戶端。只要能完成這二者的,均可以做爲傳輸層使用。所以,它所使用的協議實際上是不限的,能完成傳輸就行。儘管大部分RPC框架都使用TCP協議,但其實UDP也能夠,而gRPC乾脆就用了HTTP2。Java的Netty也屬於這層的東西。

目前有不少Java的RPC框架,有基於Json的,有基於XML,也有基於二進制對象的。

論複雜度,RPC框架確定是高於簡單的HTTP接口的。但毋庸置疑,HTTP接口因爲受限於HTTP協議,須要帶HTTP請求頭,致使傳輸起來效率或者說安全性不如RPC


 
RPC框架封裝

經常使用RPC框架

支持Java最多,golang

  • Netty - Netty框架不侷限於RPC,更多的是做爲一種網絡協議的實現框架,好比HTTP,因爲RPC須要高效的網絡通訊,就可能選擇以Netty做爲基礎。
  • brpc是一個基於protobuf接口的RPC框架,在百度內部稱爲「baidu-rpc」,它囊括了百度內部全部RPC協議,並支持多種第三方協議,從目前的性能測試數據來看,brpc的性能領跑於其餘同類RPC產品。
  • Dubbo是Alibaba開發的一個RPC框架,遠程接口基於Java Interface, 依託於Spring框架。
  • gRPC的Java實現的底層網絡庫是基於Netty開發而來,其Go實現是基於net庫。
  • Thrift是Apache的一個項目(http://thrift.apache.org),前身是Facebook開發的一個RPC框架,採用thrift做爲IDL (Interface description language)。
  • jsonrpc

JSON-RPC

python web接口實現(restful方式、jsonrpc方式)
區塊鏈項目中用的較多?資料不是不少
JSON-RPC是一種序列化協議。JSON 是 JS 對象的字符串表示法,它使用文本表示一個 JS 對象的信息,本質是一個字符串。
很是簡單,方便,速度慢
相關Python 包(直接集成到flask和django)
Flask-JSONRPC,django-json-rpc;jsonrpcserver,jsonrpcclient

thrift

Python RPC 之 Thrift
Facebook開源的跨語言RPC框架。

gRPC

gRPC 官方文檔中文版
深刻了解gRPC協議-知乎

  1. tensorflow分佈式與tensorflow serving底層通訊都是是用的grpc
    序列化用protobuf,通訊使用http2
  2. latest Google APIs will have gRPC versions of their interfaces, letting you easily build Google functionality into your applications.
  3. 支持 C, C++, Node.js, Python, Ruby, Objective-C,PHP and C#

HTTP2

一文讀懂 HTTP2 特性 - 又拍雲的文章 - 知乎
HTTP/2 和 HTTP/1 速度對比
http://www.http2demo.io/
HTTP/2
HTTP/2 是 HTTP 協議自 1999 年 HTTP 1.1 發佈後的首個更新,主要基於 SPDY 協議。
HTTP/2的主要目標是經過啓用完整請求和響應複用來減小延遲,經過有效壓縮HTTP頭字段來最大限度地下降協議開銷,並添加對請求優先級和服務器推送的支持;多路複用(同一tcp,多個流),頭部壓縮,服務推送。

Protobuf

經常使用的跨語言通訊方案
Google Protocol Buffer 的使用和原理
Protobuf 語法指南
Protocol Buffers 是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC 數據交換格式。可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。目前提供了 C++、Java、Python 三種語言的 API。
同 XML 相比, Protobuf 的主要優勢在於性能高。它以高效的二進制方式存儲,比 XML 小 3 到 10 倍,快 20 到 100 倍。

框架選擇

gRPC vs Thrift
RPC框架性能基本比較測試
怎麼看待谷歌的開源 RPC 框架 gRPC? - 知乎
微服務的服務間通訊與服務治理
最佳實踐 | 7大維度看國外企業爲啥選擇gRPC打造高性能微服務?

如何選擇

何時應該選擇gRPC而不是Thrift
  須要良好的文檔、示例
  喜歡、習慣HTTP/二、ProtoBuf
  對網絡傳輸帶寬敏感
何時應該選擇Thrift而不是gRPC
  須要在很是多的語言間進行數據交換
  對CPU敏感
  協議層、傳輸層有多種控制要求
  須要穩定的版本
  不須要良好的文檔和示例

總的來講,Python rpc框架選擇較少,thrift性能最好,grpc性能比thrift稍差,緣由是多了http2,而thrift直接基於tcp,但grpc序列化方案更通用(protobuf)優秀,文檔較好;
jsonrpc 自己基於http/1進行通訊,速度最慢,相對於以前速度無提高,只是接口和數據格式更爲統一;

gRPC不足

1)GRPC還沒有提供鏈接池 2)還沒有提供「服務發現」、「負載均衡」機制 3)由於基於HTTP2,絕大部多數HTTP Server、Nginx都尚不支持,即Nginx不能將GRPC請求做爲HTTP請求來負載均衡,而是做爲普通的TCP請求。(nginx將會在1.9版本支持)

做者:63e7d8aa8856 連接:https://www.jianshu.com/p/b0343bfd216e 來源:簡書 簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
相關文章
相關標籤/搜索