RPC簡介及框架選擇

簡單介紹RPC協議及常見框架,對比傳統restful api和RPC方式的優缺點。常見RPC框架,gRPC及序列化方式Protobuf等
HTTP協議
http協議是基于tcp協議的,tcp協議是流式協議,包頭部分可以通過多出的\r\n來分界,包體部分如何分界呢?這是協議本身要解決的問題。目前一般有兩種方式,第一種方式就是在包頭中有個content-Length字段,這個字段的值的大小標識了POST數據的長度,服務器收到一個數據包后,先從包頭解析出這個字段的值,再根據這個值去讀取相應長度的作為http協議的包體數據。
瀏覽器connect 80端口
RESTful API (http+json)
網站即軟件,而且是一種新型的軟件,這種"互聯網軟件"采用客戶端/服務器模式,建立在分布式體系上,通過互聯網通信,具有高延時(high latency)、高并發等特點。
  它首次出現在 2000 年 Roy Fielding 的博士論文中,他是 HTTP 規范的主要編寫者之一。Representational State Transfer,翻譯是”表現層狀態轉化”,通俗來講就是:資源在網絡中以某種表現形式進行狀態轉移。
總結一下什么是RESTful架構:
  (1)每一個URI代表一種資源;
  (2)客戶端和服務器之間,傳遞這種資源的某種表現層,比如用JSON,XML,JPEG等;
  (3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現"表現層狀態轉化"。

URL定位資源,用HTTP動詞(GET,POST,DELETE,DETC)描述操作。
用HTTP協議里的動詞來實現資源的添加,修改,刪除等操作。即通過HTTP動詞來實現資源的狀態扭轉:
  GET 用來獲取資源,
  POST 用來新建資源(也可以用于更新資源),
  PUT 用來更新資源,
  DELETE 用來刪除資源。
  RPC
進程間通信(IPC,Inter-Process Communication),指至少兩個進程或線程間傳送數據或信號的一些技術或方法。進程是計算機系統分配資源的最小單位。每個進程都有自己的一部分獨立的系統資源,彼此是隔離的。為了能使不同的進程互相訪問資源并進行協調工作,才有了進程間通信。這些進程可以運行在同一計算機上或網絡連接的不同計算機上。 進程間通信技術包括消息傳遞、同步、共享內存和遠程過程調用。 IPC是一種標準的Unix通信機制。

有兩種類型的進程間通信(IPC)。
本地過程調用(LPC)LPC用在多任務操作系統中,使得同時運行的任務能互相會話。這些任務共享內存空間使任務同步和互相發送信息。
遠程過程調用(RPC)RPC類似于LPC,只是在網上工作。RPC開始是出現在Sun微系統公司和HP公司的運行UNIX操作系統的計算機中。
為什么RPC呢?就是無法在一個進程內,甚至一個計算機內通過本地調用的方式完成的需求,比如比如不同的系統間的通訊,甚至不同的組織間的通訊。由于計算能力需要橫向擴展,需要在多臺機器組成的集群上部署應用

RPC的核心并不在于使用什么協議。RPC的目的是讓你在本地調用遠程的方法,而對你來說這個調用是透明的,你并不知道這個調用的方法是部署哪里。通過RPC能解耦服務,這才是使用RPC的真正目的。RPC的原理主要用到了動態代理模式,至于http協議,只是傳輸協議而已。簡單的實現可以參考spring remoting,復雜的實現可以參考dubbo。
簡單的說,

RPC就是從一臺機器(客戶端)上通過參數傳遞的方式調用另一臺機器(服務器)上的一個函數或方法(可以統稱為服務)并得到返回的結果。
RPC 會隱藏底層的通訊細節(不需要直接處理Socket通訊或Http通訊) RPC 是一個請求響應模型。
客戶端發起請求,服務器返回響應(類似于Http的工作方式) RPC 在使用形式上像調用本地函數(或方法)一樣去調用遠程的函數(或方法)。
RPC通信過程
默認socket通信。本地機器的RPC框架反序列化出執行結果,函數return這個結果
在這里插入圖片描述
RPC和restful api對比
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.1、HTTP 2.0。

一般我們考慮用 RPC 而不是 HTTP 構建自己的服務,通常是考慮到下面的因素:
接口是否需要 Schema 約束
是否需要更高效的傳輸協議(TCP,HTTP 2.0)
是否對數據包的大小非常敏感
比如 HTTP 是基于文本的協議,頭部有非常多冗余(對于 RPC 服務而言)。HTTP 中我們用的最多就是 RESTful ,而 RESTful 是個弱 Schema 約束,大家通過文檔溝通,但是如果我就是不在實現的時候對接口文檔約定的參數做檢查,你也不能把我怎么樣。這個時候 Thrift 這種序列化協議的優勢就體現出來了,由于 Schema 的存在,可以保證服務端接受的參數和 Schema 保持一致。
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框架
支持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協議-知乎

tensorflow分布式與tensorflow serving底層通信都是是用的grpc
序列化用protobuf,通信使用http2
latest Google APIs will have gRPC versions of their interfaces, letting you easily build Google functionality into your applications.
支持 C, C++, Node.js, Python, Ruby, Objective-C,PHP and C#
HTTP2
HTTP/2 是 HTTP 協議自 1999 年 HTTP 1.1 發布后的首個更新,主要基于 SPDY 協議。
HTTP/2的主要目標是通過啟用完整請求和響應復用來減少延遲,通過有效壓縮HTTP頭字段來最大限度地降低協議開銷,并添加對請求優先級和服務器推送的支持;多路復用(同一tcp,多個流),頭部壓縮,服務推送。

Protobuf
Protocol Buffers 是一種輕便高效的結構化數據存儲格式,可以用于結構化數據串行化,或者說序列化。它很適合做數據存儲或 RPC 數據交換格式。可用于通訊協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。目前提供了 C++、Java、Python 三種語言的 API。
同 XML 相比, Protobuf 的主要優點在于性能高。它以高效的二進制方式存儲,比 XML 小 3 到 10 倍,快 20 到 100 倍。
框架選擇
如何選擇

什么時候應該選擇gRPC而不是Thrift
  需要良好的文檔、示例
  喜歡、習慣HTTP/2、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版本支持)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249750.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249750.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249750.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CSS3的calc()使用

什么是calc()? 學習calc()之前&#xff0c;我們有必要先知道calc()是什么&#xff1f;只有知道了他是個什么東東&#xff1f;在實際運用中更好的使用他。 calc()從字面我們可以把他理解為一個函數function。其實calc是英文單詞calculate(計算)的縮寫&#xff0c;是css3的一個新…

typescript 類型映射 (ReadOnly、Partial)

有時候需要一個類型&#xff0c;是依賴于上一個類型但是&#xff0c;對屬性的要求去不同interface Person{name: string;agent: number; } type Person2 Readonly<Person>; type Person3 Partial<Person>; class Test {run() {let person: Person {name: dd,age…

JAVA中幾種常用的RPC框架介紹

RPC是遠程過程調用的簡稱&#xff0c;廣泛應用在大規模分布式應用中&#xff0c;作用是有助于系統的垂直拆分&#xff0c;使系統更易拓展。Java中的RPC框架比較多&#xff0c;各有特色&#xff0c;廣泛使用的有RMI、Hessian、Dubbo等。RPC還有一個特點就是能夠跨語言&#xff0…

C#中的多線程 - 同步基礎

C#中的多線程 - 同步基礎 C#中的多線程 - 同步基礎 1同步概要在第 1 部分&#xff1a;基礎知識中&#xff0c;我們描述了如何在線程上啟動任務、配置線程以及雙向傳遞數據。同時也說明了局部變量對于線程來說是私有的&#xff0c;以及引用是如何在線程之間共享&#xff0c;允許…

WC2019 自閉記

不咕了 Day 1 2019/1/24 辣么快就到冬令營了&#xff0c;還沉迷于被柿子吊打的狀態的菜雞一時半會還反應不過來。我們學校這次分頭去的冬令營&#xff0c;差點上不了車。這次做的動車居然直達廣州&#xff0c;強啊。 然鵝還是到太晚&#xff0c;沒飯吃了。路上花了15大洋買了個…

v-slot vue2.6新增指令使用指南

子組件 <template><div class"wrapper"><slot name"demo" :msg"msg" text"this is a slot demo , ">this is demo slot.</slot></div> </template><script>export default {components: {…

跨語言RPC框架Thrift詳解

一、 概念 Apache的Thrift軟件框架&#xff0c;是用來進行可伸縮的、跨語言的服務開發&#xff0c;它通過一個代碼生成引擎來構建高效、無縫的服務&#xff0c;這些服務能夠實現跨語言調度&#xff0c;目前支持的語言有&#xff1a; C, Java, Python, PHP, Ruby, Erlang, Perl,…

小知識

1.時間格式的處理 new Date().format(yyyy-MM-dd hh:mm:ss) 2.保留兩位小數的方法 element.recTime element.recTime.toFixed(2) 3.如何判斷一個對象為空的方法 JSON.stringify(this.getEcho) ! "{}" 4.判斷時間是否為標準格式的方法 (this.formValidate.outDateti…

增加標 和增加其內容

create table student( sno varchar(20) not null comment學號, sname varchar(20) not null comment學生姓名, ssex varchar(20) not null comment學生性別, sbirthday datetime comment學生出生年月, class varchar(20) comment 學生所在班級, primary key…

RPC服務和HTTP服務對比

很長時間以來都沒有怎么好好搞清楚RPC&#xff08;即Remote Procedure Call&#xff0c;遠程過程調用&#xff09;和HTTP調用的區別&#xff0c;不都是寫一個服務然后在客戶端調用么&#xff1f;這里請允許我迷之一笑~Naive&#xff01;本文簡單地介紹一下兩種形式的C/S架構&am…

MTK-TP(電阻屏校準程序ts_lib移植)

現今的項目中已經很少有使用電阻TP&#xff0c;但總有些奇怪的需求。如果項目中遇到需要校準電阻屏如何保證較快且較穩的調試TP呢。這里介紹使用ts_lib庫來進行調試。 當然也可以使用一些常見的校準算法&#xff0c;采集5點&#xff0c;但最終的公式應該是不變的&#xff1a; X…

mac vscode 實用快捷鍵

cmddel:光標左邊刪到頭 cmdfndel:光標右側刪到頭轉載于:https://www.cnblogs.com/smzd/p/11474488.html

ONENET讀取與控制麒麟座MINI開發板LED狀態

硬件 麒麟座MINI開發板V1.4 嵌入式軟件 OneNET_Demo_ESP8266_EDP_Led 工程修改內容 led.c文件修改 函數LED_Init&#xff0c;mini開發板LED所在GPIO為PB6、PB7、PB8、PB9 函數LED_GetValue&#xff0c;mini開發板LED狀態與IO口狀態相反 /** * brief LED指示燈初始化函數**/v…

洛谷 - P1217 - 回文質數 - 枚舉

https://www.luogu.org/problemnew/show/P1217 考慮暴力生成所有的回文數然后再判斷是不是質數。注意個位的選擇實際上只有4種。所以是 $4*10^3*10^34*10^6$ &#xff0c;完全充裕的復雜度。 #include<bits/stdc.h> using namespace std; #define ll long longint a,b; v…

git commit之后,想撤銷commit

寫完代碼后&#xff0c;我們一般這樣git add . //添加所有文件git commit -m "本功能全部完成"執行完commit后&#xff0c;想撤回commit&#xff0c;怎么辦&#xff1f;這樣涼拌&#xff1a;git reset --soft HEAD^這樣就成功的撤銷了你的commit注意&#xff0c;僅僅…

引用數據類型

1.Scanner類 Scanner類是引用數據類型的一種&#xff0c;我們可以使用該類來完成用戶鍵盤錄入&#xff0c;獲取到錄入的數據。 引用數據類型的使用&#xff1a; 與定義基本數據類型變量不同&#xff0c;引用數據類型的變量定義及賦值有一個相對固定的步驟或格式。 數據類型 變…

phpmyadmin登錄遠程mysql數據庫

之前只用phpmyadmin登錄本地的mysql&#xff0c;管理另一個遠程數據庫的時候發現&#xff0c;單純用命令行處理字符串、換行符實在是不好使&#xff0c;所以配置了遠程登錄mysql&#xff0c;很簡單的問題結果沒有搜到合適的方法&#xff0c;所以記錄下我的配置方式。 phpmyadmi…

activemq的使用場景

一、消息隊列概述 消息隊列中間件是分布式系統中重要的組件&#xff0c;主要解決應用耦合&#xff0c;異步消息&#xff0c;流量削鋒等問題。實現高性能&#xff0c;高可用&#xff0c;可伸縮和最終一致性架構。是大型分布式系統不可缺少的中間件。 目前在生產環境&#xff0c…

復習JavaScript隨手記

數據類型 基本類型 stringnumberbooleanundefinednumber類型,包含整數浮點數 NaN和自己都不相等,涉及NaN的計算結果都是NaN isNaN()函數用于判斷一個數是不是NaN 引用類型 object類型 function類型 繼承自object object類型定義了prototype屬性 可以通過它動態給對象綁定方法和…

TP5在前端時間戳轉換為時間格式

value"{:date(Y-m-d H:i:s,$data[add_date])}" 例如&#xff1a; <td>{:date(Y-m-d H:i:s,$d[create_time])}</td> 轉載于:https://www.cnblogs.com/shark1100913/p/9468077.html