偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

RPC框架:從原理到選型,一文帶你搞懂RPC

開發(fā) 架構(gòu)
RPC(Remote Procedure Call Protocol)遠(yuǎn)程過(guò)程調(diào)用協(xié)議。一個(gè)通俗的描述是:客戶端在不知道調(diào)用細(xì)節(jié)的情況下,調(diào)用存在于遠(yuǎn)程計(jì)算機(jī)上的某個(gè)對(duì)象,就像調(diào)用本地應(yīng)用程序中的對(duì)象一樣。

本文轉(zhuǎn)載自微信公眾號(hào)「樓仔」,作者夢(mèng)樓。轉(zhuǎn)載本文請(qǐng)聯(lián)系樓仔公眾號(hào)。

RPC系列的文章是我去年寫的,當(dāng)時(shí)寫的比較散,現(xiàn)在重新進(jìn)行整理。對(duì)于想學(xué)習(xí)RPC框架的同學(xué),通過(guò)這篇文章,讓你知其然并知其所以然,便于以后技術(shù)選型,下面是文章內(nèi)容目錄:

RPC

什么是RPC

RPC(Remote Procedure Call Protocol)遠(yuǎn)程過(guò)程調(diào)用協(xié)議。一個(gè)通俗的描述是:客戶端在不知道調(diào)用細(xì)節(jié)的情況下,調(diào)用存在于遠(yuǎn)程計(jì)算機(jī)上的某個(gè)對(duì)象,就像調(diào)用本地應(yīng)用程序中的對(duì)象一樣。

比較正式的描述是:一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。

那么我們至少?gòu)倪@樣的描述中挖掘出幾個(gè)要點(diǎn):

  • RPC是協(xié)議:既然是協(xié)議就只是一套規(guī)范,那么就需要有人遵循這套規(guī)范來(lái)進(jìn)行實(shí)現(xiàn)。目前典型的RPC實(shí)現(xiàn)包括:Dubbo、Thrift、GRPC、Hetty等。
  • 網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)IO模型對(duì)其透明:既然RPC的客戶端認(rèn)為自己是在調(diào)用本地對(duì)象。那么傳輸層使用的是TCP/UDP還是HTTP協(xié)議,又或者是一些其他的網(wǎng)絡(luò)協(xié)議它就不需要關(guān)心了。
  • 信息格式對(duì)其透明:我們知道在本地應(yīng)用程序中,對(duì)于某個(gè)對(duì)象的調(diào)用需要傳遞一些參數(shù),并且會(huì)返回一個(gè)調(diào)用結(jié)果。至于被調(diào)用的對(duì)象內(nèi)部是如何使用這些參數(shù),并計(jì)算出處理結(jié)果的,調(diào)用方是不需要關(guān)心的。那么對(duì)于遠(yuǎn)程調(diào)用來(lái)說(shuō),這些參數(shù)會(huì)以某種信息格式傳遞給網(wǎng)絡(luò)上的另外一臺(tái)計(jì)算機(jī),這個(gè)信息格式是怎樣構(gòu)成的,調(diào)用方是不需要關(guān)心的。
  • 應(yīng)該有跨語(yǔ)言能力:為什么這樣說(shuō)呢?因?yàn)檎{(diào)用方實(shí)際上也不清楚遠(yuǎn)程服務(wù)器的應(yīng)用程序是使用什么語(yǔ)言運(yùn)行的。那么對(duì)于調(diào)用方來(lái)說(shuō),無(wú)論服務(wù)器方使用的是什么語(yǔ)言,本次調(diào)用都應(yīng)該成功,并且返回值也應(yīng)該按照調(diào)用方程序語(yǔ)言所能理解的形式進(jìn)行描述。

為什么要用RPC

其實(shí)這是應(yīng)用開發(fā)到一定的階段的強(qiáng)烈需求驅(qū)動(dòng)的。如果我們開發(fā)簡(jiǎn)單的單一應(yīng)用,邏輯簡(jiǎn)單、用戶不多、流量不大,那我們用不著。當(dāng)我們的系統(tǒng)訪問(wèn)量增大、業(yè)務(wù)增多時(shí),我們會(huì)發(fā)現(xiàn)一臺(tái)單機(jī)運(yùn)行此系統(tǒng)已經(jīng)無(wú)法承受。此時(shí),我們可以將業(yè)務(wù)拆分成幾個(gè)互不關(guān)聯(lián)的應(yīng)用,分別部署在各自機(jī)器上,以劃清邏輯并減小壓力。此時(shí),我們也可以不需要RPC,因?yàn)閼?yīng)用之間是互不關(guān)聯(lián)的。

當(dāng)我們的業(yè)務(wù)越來(lái)越多、應(yīng)用也越來(lái)越多時(shí),自然的,我們會(huì)發(fā)現(xiàn)有些功能已經(jīng)不能簡(jiǎn)單劃分開來(lái)或者劃分不出來(lái)。此時(shí),可以將公共業(yè)務(wù)邏輯抽離出來(lái),將之組成獨(dú)立的服務(wù)Service應(yīng)用 。而原有的、新增的應(yīng)用都可以與那些獨(dú)立的Service應(yīng)用 交互,以此來(lái)完成完整的業(yè)務(wù)功能。

所以此時(shí),我們急需一種高效的應(yīng)用程序之間的通訊手段來(lái)完成這種需求,所以你看,RPC大顯身手的時(shí)候來(lái)了!

其實(shí)描述的場(chǎng)景也是服務(wù)化 、微服務(wù)和分布式系統(tǒng)架構(gòu)的基礎(chǔ)場(chǎng)景。即RPC框架就是實(shí)現(xiàn)以上結(jié)構(gòu)的有力方式。

常用的RPC框架

  • Thrift:thrift是一個(gè)軟件框架,用來(lái)進(jìn)行可擴(kuò)展且跨語(yǔ)言的服務(wù)的開發(fā)。它結(jié)合了功能強(qiáng)大的軟件堆棧和代碼生成引擎,以構(gòu)建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 這些編程語(yǔ)言間無(wú)縫結(jié)合的、高效的服務(wù)。
  • gRPC:一開始由 google 開發(fā),是一款語(yǔ)言中立、平臺(tái)中立、開源的遠(yuǎn)程過(guò)程調(diào)用(RPC)系統(tǒng)。
  • Dubbo:Dubbo是一個(gè)分布式服務(wù)框架,以及SOA治理方案。其功能主要包括:高性能NIO通訊及多協(xié)議集成,服務(wù)動(dòng)態(tài)尋址與路由,軟負(fù)載均衡與容錯(cuò),依賴分析與降級(jí)等。Dubbo是阿里巴巴內(nèi)部的SOA服務(wù)化治理方案的核心框架,Dubbo自2011年開源后,已被許多非阿里系公司使用。
  • Spring Cloud:Spring Cloud由眾多子項(xiàng)目組成,如Spring Cloud Config、Spring Cloud Netflix、Spring Cloud Consul 等,提供了搭建分布式系統(tǒng)及微服務(wù)常用的工具,如配置管理、服務(wù)發(fā)現(xiàn)、斷路器、智能路由、微代理、控制總線、一次性token、全局鎖、選主、分布式會(huì)話和集群狀態(tài)等,滿足了構(gòu)建微服務(wù)所需的所有解決方案。Spring Cloud基于Spring Boot, 使得開發(fā)部署極其簡(jiǎn)單。

RPC原理

RPC調(diào)用流程

要讓網(wǎng)絡(luò)通信細(xì)節(jié)對(duì)使用者透明,我們需要對(duì)通信細(xì)節(jié)進(jìn)行封裝,我們先看下一個(gè)RPC調(diào)用的流程涉及到哪些通信細(xì)節(jié):

  1. 服務(wù)消費(fèi)方(client)調(diào)用以本地調(diào)用方式調(diào)用服務(wù);
  2. client stub接收到調(diào)用后負(fù)責(zé)將方法、參數(shù)等組裝成能夠進(jìn)行網(wǎng)絡(luò)傳輸?shù)南Ⅲw;
  3. client stub找到服務(wù)地址,并將消息發(fā)送到服務(wù)端;
  4. server stub收到消息后進(jìn)行解碼;
  5. server stub根據(jù)解碼結(jié)果調(diào)用本地的服務(wù);
  6. 本地服務(wù)執(zhí)行并將結(jié)果返回給server stub;
  7. server stub將返回結(jié)果打包成消息并發(fā)送至消費(fèi)方;
  8. client stub接收到消息,并進(jìn)行解碼;
  9. 服務(wù)消費(fèi)方得到最終結(jié)果。

RPC的目標(biāo)就是要2~8這些步驟都封裝起來(lái),讓用戶對(duì)這些細(xì)節(jié)透明。

下面是網(wǎng)上的另外一幅圖,感覺(jué)一目了然:

如何做到透明化遠(yuǎn)程服務(wù)調(diào)用

怎么封裝通信細(xì)節(jié)才能讓用戶像以本地調(diào)用方式調(diào)用遠(yuǎn)程服務(wù)呢?對(duì)java來(lái)說(shuō)就是使用代理!java代理有兩種方式:1) jdk 動(dòng)態(tài)代理;2)字節(jié)碼生成。盡管字節(jié)碼生成方式實(shí)現(xiàn)的代理更為強(qiáng)大和高效,但代碼維護(hù)不易,大部分公司實(shí)現(xiàn)RPC框架時(shí)還是選擇動(dòng)態(tài)代理方式。

下面簡(jiǎn)單介紹下動(dòng)態(tài)代理怎么實(shí)現(xiàn)我們的需求。我們需要實(shí)現(xiàn)RPCProxyClient代理類,代理類的invoke方法中封裝了與遠(yuǎn)端服務(wù)通信的細(xì)節(jié),消費(fèi)方首先從RPCProxyClient獲得服務(wù)提供方的接口,當(dāng)執(zhí)行helloWorldService.sayHello("test")方法時(shí)就會(huì)調(diào)用invoke方法。

public class RPCProxyClient implements java.lang.reflect.InvocationHandler{
private Object obj;
public RPCProxyClient(Object obj){
this.obj=obj;
}
/**
* 得到被代理對(duì)象;
*/
public static Object getProxy(Object obj){
return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new RPCProxyClient(obj));
}
/**
* 調(diào)用此方法執(zhí)行
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//結(jié)果參數(shù);
Object result = new Object();
// ...執(zhí)行通信相關(guān)邏輯
// ...
return result;
}
}

public class Test {
public static void main(String[] args) {
HelloWorldService helloWorldService = (HelloWorldService)RPCProxyClient.getProxy(HelloWorldService.class);
helloWorldService.sayHello("test");
}
}

其實(shí)就是通過(guò)動(dòng)態(tài)代理模式,在執(zhí)行該方法的前后對(duì)數(shù)據(jù)進(jìn)行封裝和解碼等,讓用于感覺(jué)就像是直接調(diào)用該方法一樣,殊不知,我們對(duì)方法前后都經(jīng)過(guò)了復(fù)雜的處理。

如何對(duì)消息進(jìn)行編碼和解碼

確定消息數(shù)據(jù)結(jié)構(gòu)

客戶端的請(qǐng)求消息結(jié)構(gòu)一般需要包括以下內(nèi)容:

  • 接口名稱:在我們的例子里接口名是“HelloWorldService”,如果不傳,服務(wù)端就不知道調(diào)用哪個(gè)接口了;
  • 方法名:一個(gè)接口內(nèi)可能有很多方法,如果不傳方法名服務(wù)端也就不知道調(diào)用哪個(gè)方法;
  • 參數(shù)類型&參數(shù)值:參數(shù)類型有很多,比如有bool、int、long、double、string、map、list,甚至如struct等,以及相應(yīng)的參數(shù)值;
  • 超時(shí)時(shí)間 + requestID(標(biāo)識(shí)唯一請(qǐng)求id)

服務(wù)端返回的消息結(jié)構(gòu)一般包括以下內(nèi)容:

  • 狀態(tài)code + 返回值
  • requestID

序列化

一旦確定了消息的數(shù)據(jù)結(jié)構(gòu)后,下一步就是要考慮序列化與反序列化了。

什么是序列化?序列化就是將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制串的過(guò)程,也就是編碼的過(guò)程。

什么是反序列化?將在序列化過(guò)程中所生成的二進(jìn)制串轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對(duì)象的過(guò)程。

為什么需要序列化?轉(zhuǎn)換為二進(jìn)制串后才好進(jìn)行網(wǎng)絡(luò)傳輸嘛!

為什么需要反序列化?將二進(jìn)制轉(zhuǎn)換為對(duì)象才好進(jìn)行后續(xù)處理!

現(xiàn)如今序列化的方案越來(lái)越多,每種序列化方案都有優(yōu)點(diǎn)和缺點(diǎn),它們?cè)谠O(shè)計(jì)之初有自己獨(dú)特的應(yīng)用場(chǎng)景,那到底選擇哪種呢?從RPC的角度上看,主要看三點(diǎn):

  • 通用性:比如是否能支持Map等復(fù)雜的數(shù)據(jù)結(jié)構(gòu);
  • 性能:包括時(shí)間復(fù)雜度和空間復(fù)雜度,由于RPC框架將會(huì)被公司幾乎所有服務(wù)使用,如果序列化上能節(jié)約一點(diǎn)時(shí)間,對(duì)整個(gè)公司的收益都將非??捎^,同理如果序列化上能節(jié)約一點(diǎn)內(nèi)存,網(wǎng)絡(luò)帶寬也能省下不少;
  • 可擴(kuò)展性:對(duì)互聯(lián)網(wǎng)公司而言,業(yè)務(wù)變化飛快,如果序列化協(xié)議具有良好的可擴(kuò)展性,支持自動(dòng)增加新的業(yè)務(wù)字段,而不影響老的服務(wù),這將大大提供系統(tǒng)的靈活度。

目前互聯(lián)網(wǎng)公司廣泛使用Protobuf、Thrift、Avro等成熟的序列化解決方案來(lái)搭建RPC框架,這些都是久經(jīng)考驗(yàn)的解決方案。

消息里為什么要有requestID?這個(gè)問(wèn)題很簡(jiǎn)單,就不說(shuō)明了,你能回答出來(lái)么?

如何發(fā)布自己的服務(wù)

這個(gè)我前面的很多文章都提到過(guò),Java常用zookeeper,Go常用ETCD,服務(wù)端進(jìn)行注冊(cè)和心跳,客戶端獲取機(jī)器列表,沒(méi)啥高深的,比如zookeeper:

gRPC & Thrift

gRPC

gRPC 簡(jiǎn)介

gRPC是一個(gè)高性能、通用的開源RPC框架,其由Google 2015年主要面向移動(dòng)應(yīng)用開發(fā)并基于HTTP/2協(xié)議標(biāo)準(zhǔn)而設(shè)計(jì),基于ProtoBuf序列化協(xié)議開發(fā),且支持眾多開發(fā)語(yǔ)言。

由于是開源框架,通信的雙方可以進(jìn)行二次開發(fā),所以客戶端和服務(wù)器端之間的通信會(huì)更加專注于業(yè)務(wù)層面的內(nèi)容,減少了對(duì)由gRPC框架實(shí)現(xiàn)的底層通信的關(guān)注。

如下圖,DATA部分即業(yè)務(wù)層面內(nèi)容,下面所有的信息都由gRPC進(jìn)行封裝。

gRPC 特點(diǎn)

  • 語(yǔ)言中立,支持多種語(yǔ)言;
  • 基于 IDL 文件定義服務(wù),通過(guò) proto3 工具生成指定語(yǔ)言的數(shù)據(jù)結(jié)構(gòu)、服務(wù)端接口以及客戶端 Stub;
  • 通信協(xié)議基于標(biāo)準(zhǔn)的 HTTP/2 設(shè)計(jì),支持雙向流、消息頭壓縮、單 TCP 的多路復(fù)用、服務(wù)端推送等特性,這些特性使得 gRPC 在移動(dòng)端設(shè)備上更加省電和節(jié)省網(wǎng)絡(luò)流量;
  • 序列化支持 PB(Protocol Buffer)和 JSON,PB 是一種語(yǔ)言無(wú)關(guān)的高性能序列化框架,基于 HTTP/2 + PB, 保障了 RPC 調(diào)用的高性能。

gRPC 交互過(guò)程

  • 交換機(jī)在開啟gRPC功能后充當(dāng)gRPC客戶端的角色,采集服務(wù)器充當(dāng)gRPC服務(wù)器角色;
  • 交換機(jī)會(huì)根據(jù)訂閱的事件構(gòu)建對(duì)應(yīng)數(shù)據(jù)的格式(GPB/JSON),通過(guò)Protocol Buffers進(jìn)行編寫proto文件,交換機(jī)與服務(wù)器建立gRPC通道,通過(guò)gRPC協(xié)議向服務(wù)器發(fā)送請(qǐng)求消息;
  • 服務(wù)器收到請(qǐng)求消息后,服務(wù)器會(huì)通過(guò)Protocol Buffers解譯proto文件,還原出最先定義好格式的數(shù)據(jù)結(jié)構(gòu),進(jìn)行業(yè)務(wù)處理;
  • 數(shù)據(jù)處理完后,服務(wù)器需要使用Protocol Buffers重編譯應(yīng)答數(shù)據(jù),通過(guò)gRPC協(xié)議向交換機(jī)發(fā)送應(yīng)答消息;
  • 交換機(jī)收到應(yīng)答消息后,結(jié)束本次的gRPC交互。

簡(jiǎn)單地說(shuō),gRPC就是在客戶端和服務(wù)器端開啟gRPC功能后建立連接,將設(shè)備上配置的訂閱數(shù)據(jù)推送給服務(wù)器端。我們可以看到整個(gè)過(guò)程是需要用到Protocol Buffers將所需要處理數(shù)據(jù)的結(jié)構(gòu)化數(shù)據(jù)在proto文件中進(jìn)行定義。

什么是Protocol Buffers?

你可以理解ProtoBuf是一種更加靈活、高效的數(shù)據(jù)格式,與XML、JSON類似,在一些高性能且對(duì)響應(yīng)速度有要求的數(shù)據(jù)傳輸場(chǎng)景非常適用。ProtoBuf在gRPC的框架中主要有三個(gè)作用:

  • 定義數(shù)據(jù)結(jié)構(gòu)
  • 定義服務(wù)接口
  • 通過(guò)序列化和反序列化,提升傳輸效率

為什么ProtoBuf會(huì)提高傳輸效率呢?

我們知道使用XML、JSON進(jìn)行數(shù)據(jù)編譯時(shí),數(shù)據(jù)文本格式更容易閱讀,但進(jìn)行數(shù)據(jù)交換時(shí),設(shè)備就需要耗費(fèi)大量的CPU在I/O動(dòng)作上,自然會(huì)影響整個(gè)傳輸速率。Protocol Buffers不像前者,它會(huì)將字符串進(jìn)行序列化后再進(jìn)行傳輸,即二進(jìn)制數(shù)據(jù)。

可以看到其實(shí)兩者內(nèi)容相差不大,并且內(nèi)容非常直觀,但是Protocol Buffers編碼的內(nèi)容只是提供給操作者閱讀的,實(shí)際上傳輸?shù)牟⒉粫?huì)以這種文本形式,而是序列化后的二進(jìn)制數(shù)據(jù)。字節(jié)數(shù)會(huì)比JSON、XML的字節(jié)數(shù)少很多,速率更快。

如何支撐跨平臺(tái),多語(yǔ)言呢?

Protocol Buffers自帶一個(gè)編譯器也是一個(gè)優(yōu)勢(shì)點(diǎn)。前面提到的proto文件就是通過(guò)編譯器進(jìn)行編譯的,proto文件需要編譯生成一個(gè)類似庫(kù)文件,基于庫(kù)文件才能真正開發(fā)數(shù)據(jù)應(yīng)用。具體用什么編程語(yǔ)言編譯生成這個(gè)庫(kù)文件呢?由于現(xiàn)網(wǎng)中負(fù)責(zé)網(wǎng)絡(luò)設(shè)備和服務(wù)器設(shè)備的運(yùn)維人員往往不是同一組人,運(yùn)維人員可能會(huì)習(xí)慣使用不同的編程語(yǔ)言進(jìn)行運(yùn)維開發(fā),那么Protocol Buffers其中一個(gè)優(yōu)勢(shì)就能發(fā)揮出來(lái)——跨語(yǔ)言。

從上面的介紹,我們得出在編碼方面Protocol Buffers對(duì)比JSON、XML的優(yōu)點(diǎn):

  • 簡(jiǎn)單,體積小,數(shù)據(jù)描述文件大小只有1/10至1/3;
  • 傳輸和解析的速率快,相比XML等,解析速度提升20倍甚至更高;
  • 可編譯性強(qiáng)。

基于HTTP 2.0標(biāo)準(zhǔn)設(shè)計(jì)

除了Protocol Buffers之外,從交互圖中和分層框架可以看到, gRPC還有另外一個(gè)優(yōu)勢(shì)——它是基于HTTP 2.0協(xié)議的。

由于gRPC基于HTTP 2.0標(biāo)準(zhǔn)設(shè)計(jì),帶來(lái)了更多強(qiáng)大功能,如多路復(fù)用、二進(jìn)制幀、頭部壓縮、推送機(jī)制。這些功能給設(shè)備帶來(lái)重大益處,如節(jié)省帶寬、降低TCP連接次數(shù)、節(jié)省CPU使用等。gRPC既能夠在客戶端應(yīng)用,也能夠在服務(wù)器端應(yīng)用,從而以透明的方式實(shí)現(xiàn)兩端的通信和簡(jiǎn)化通信系統(tǒng)的構(gòu)建。

HTTP 版本分為HTTP 1.X、 HTTP 2.0,其中HTTP 1.X是當(dāng)前使用最廣泛的HTTP協(xié)議,HTTP 2.0稱為超文本傳輸協(xié)議第二代。HTTP 1.X定義了四種與服務(wù)器交互的方式,分別為:GET、POST、PUT、DELETE,這些在HTTP 2.0中均保留。HTTP 2.0的新特性:

  • 雙向流、多路復(fù)用
  • 二進(jìn)制幀
  • 頭部壓縮

Thrift

Thrift 簡(jiǎn)介

thrift是一種可伸縮的跨語(yǔ)言服務(wù)的RPC軟件框架。它結(jié)合了功能強(qiáng)大的軟件堆棧的代碼生成引擎,以建設(shè)服務(wù),高效、無(wú)縫地在多種語(yǔ)言間結(jié)合使用。2007年由facebook貢獻(xiàn)到apache基金,是apache下的頂級(jí)項(xiàng)目,具備如下特點(diǎn):

  • 支持多語(yǔ)言:C、C++ 、C# 、D 、Delphi 、Erlang 、Go 、Haxe 、Haskell 、Java 、JavaScript、node.js 、OCaml 、Perl 、PHP 、Python 、Ruby 、SmallTalk
  • 消息定義文件支持注釋,數(shù)據(jù)結(jié)構(gòu)與傳輸表現(xiàn)的分離,支持多種消息格式
  • 包含完整的客戶端/服務(wù)端堆棧,可快速實(shí)現(xiàn)RPC,支持同步和異步通信

Thrift框架結(jié)構(gòu)

Thrift是一套包含序列化功能和支持服務(wù)通信的RPC(遠(yuǎn)程服務(wù)調(diào)用)框架,也是一種微服務(wù)框架。其主要特點(diǎn)是可以跨語(yǔ)言使用,這也是這個(gè)框架最吸引人的地方。

圖中code是用戶實(shí)現(xiàn)的業(yè)務(wù)邏輯,接下來(lái)的 Service.Client和 write()/read()是thrift根據(jù)IDL生成的客戶端和服務(wù)端的代碼,對(duì)應(yīng)于RPC中Client stub和Server stub。TProtocol 用來(lái)對(duì)數(shù)據(jù)進(jìn)行序列化與反序列化,具體方法包括二進(jìn)制,JSON 或者 Apache Thrift 定義的格式。TTransport 提供數(shù)據(jù)傳輸功能,使用 Apache Thrift 可以方便地定義一個(gè)服務(wù)并選擇不同的傳輸協(xié)議。

Thrift網(wǎng)絡(luò)棧結(jié)構(gòu)

thirft使用socket進(jìn)行數(shù)據(jù)傳輸,數(shù)據(jù)以特定的格式發(fā)送,接收方進(jìn)行解析。我們定義好thrift的IDL文件后,就可以使用thrift的編譯器來(lái)生成雙方語(yǔ)言的接口、model,在生成的model以及接口代碼中會(huì)有解碼編碼的代碼。thrift網(wǎng)絡(luò)棧結(jié)構(gòu)如下:

Transport層

代表Thrift的數(shù)據(jù)傳輸方式,Thrift定義了如下幾種常用數(shù)據(jù)傳輸方式:

  • TSocket: 阻塞式socket;
  • TFramedTransport: 以frame為單位進(jìn)行傳輸,非阻塞式服務(wù)中使用;
  • TFileTransport: 以文件形式進(jìn)行傳輸。

TProtocol層

代表thrift客戶端和服務(wù)端之間傳輸數(shù)據(jù)的協(xié)議,通俗來(lái)講就是客戶端和服務(wù)端之間傳輸數(shù)據(jù)的格式(例如json等),thrift定義了如下幾種常見(jiàn)的格式:

  • TBinaryProtocol: 二進(jìn)制格式;
  • TCompactProtocol: 壓縮格式;
  • TJSONProtocol: JSON格式;
  • TSimpleJSONProtocol: 提供只寫的JSON協(xié)議。

Server模型

  • TSimpleServer: 簡(jiǎn)單的單線程服務(wù)模型,常用于測(cè)試;
  • TThreadPoolServer: 多線程服務(wù)模型,使用標(biāo)準(zhǔn)的阻塞式IO;
  • TNonBlockingServer: 多線程服務(wù)模型,使用非阻塞式IO(需要使用TFramedTransport數(shù)據(jù)傳輸方式);
  • THsHaServer: THsHa引入了線程池去處理,其模型讀寫任務(wù)放到線程池去處理,Half-sync/Half-async處理模式,Half-async是在處理IO事件上(accept/read/write io),Half-sync用于handler對(duì)rpc的同步處理;

gRPC VS Thrift

功能比較

直接貼上網(wǎng)上的兩幅截圖:

性能比較

也是基于網(wǎng)上測(cè)試的結(jié)果,僅供參考:

  • 整體上看,長(zhǎng)連接性能優(yōu)于短連接,性能差距在兩倍以上;
  • 對(duì)比Go語(yǔ)言的兩個(gè)RPC框架,Thrift性能明顯優(yōu)于gRPC,性能差距也在兩倍以上;
  • 對(duì)比Thrift框架下的的兩種語(yǔ)言,長(zhǎng)連接下Go 與C++的RPC性能基本在同一個(gè)量級(jí),在短連接下,Go性能大概是C++的二倍;
  • 對(duì)比Thrift&C++下的TSimpleServer與TNonblockingServer,在單進(jìn)程客戶端長(zhǎng)連接的場(chǎng)景下,TNonblockingServer因?yàn)榇嬖诰€程管理開銷,性能較TSimpleServer差一些;但在短連接時(shí),主要開銷在連接建立上,線程池管理開銷可忽略;
  • 兩套R(shí)PC框架,以及兩大語(yǔ)言運(yùn)行都非常穩(wěn)定,5w次請(qǐng)求耗時(shí)約是1w次的5倍;

如何選型

什么時(shí)候應(yīng)該選擇gRPC而不是Thrift:

  • 需要良好的文檔、示例
  • 喜歡、習(xí)慣HTTP/2、ProtoBuf
  • 對(duì)網(wǎng)絡(luò)傳輸帶寬敏感

什么時(shí)候應(yīng)該選擇Thrift而不是gRPC:

  • 需要在非常多的語(yǔ)言間進(jìn)行數(shù)據(jù)交換
  • 對(duì)CPU敏感
  • 協(xié)議層、傳輸層有多種控制要求
  • 需要穩(wěn)定的版本
  • 不需要良好的文檔和示例

小節(jié)

上面詳細(xì)介紹gRPC和Thrift的特點(diǎn)和區(qū)別,小節(jié)如下:

  • GRPC主要就是搞了個(gè)ProtoBuf,然后采用HTTP協(xié)議,所以協(xié)議部分沒(méi)有重復(fù)造輪子,重點(diǎn)就在ProtoBuf上。
  • Thrift的數(shù)據(jù)格式是用的現(xiàn)成的,沒(méi)有單獨(dú)搞一套,但是它在傳輸層和服務(wù)端全部是自己造輪子,所以可以對(duì)協(xié)議層、傳輸層有多種控制要求。

gRPC示例

除了理論,我們還需注重實(shí)踐,gPRC的使用姿勢(shì)看這篇文章 ??【RPC基礎(chǔ)系列3】gRPC簡(jiǎn)單示例??

Dubbo & Spring Cloud

Dubbo

Dubbo 是一個(gè)分布式服務(wù)框架,致力于提供高性能和透明化的 RPC 遠(yuǎn)程服務(wù)調(diào)用方案,以及 SOA 服務(wù)治理方案。簡(jiǎn)單的說(shuō),Dubbo 就是個(gè)服務(wù)框架,說(shuō)白了就是個(gè)遠(yuǎn)程服務(wù)調(diào)用的分布式框架。

Dubbo 總體架構(gòu):

Dubbo特點(diǎn):

  • 遠(yuǎn)程通訊: 提供對(duì)多種基于長(zhǎng)連接的 NIO 框架抽象封裝(非阻塞 I/O 的通信方式,Mina/Netty/Grizzly),包括多種線程模型,序列化(Hessian2/ProtoBuf),以及“請(qǐng)求-響應(yīng)”模式的信息交換方式。
  • 集群容錯(cuò): 提供基于接口方法的透明遠(yuǎn)程過(guò)程調(diào)用(RPC),包括多協(xié)議支持(自定義 RPC 協(xié)議),以及軟負(fù)載均衡(Random/RoundRobin),失敗容錯(cuò)(Failover/Failback),地址路由,動(dòng)態(tài)配置等集群支持。
  • 自動(dòng)發(fā)現(xiàn): 基于注冊(cè)中心目錄服務(wù),使服務(wù)消費(fèi)方能動(dòng)態(tài)的查找服務(wù)提供方,使地址透明,使服務(wù)提供方可以平滑增加或減少機(jī)器。

Spring Cloud

Spring Cloud 基于 Spring Boot,為微服務(wù)體系開發(fā)中的架構(gòu)問(wèn)題,提供了一整套的解決方案——服務(wù)注冊(cè)與發(fā)現(xiàn),服務(wù)消費(fèi),服務(wù)保護(hù)與熔斷,網(wǎng)關(guān),分布式調(diào)用追蹤,分布式配置管理等。

Dubbo vs Spring Cloud

使用 Dubbo 構(gòu)建的微服務(wù)架構(gòu)就像組裝電腦,各環(huán)節(jié)我們的選擇自由度很高,但是最終結(jié)果很有可能因?yàn)橐粭l內(nèi)存質(zhì)量不行就點(diǎn)不亮了,總是讓人不怎么放心,但是如果你是一名高手,那這些都不是問(wèn)題;而 Spring Cloud 就像品牌機(jī),在 Spring Source 的整合下,做了大量的兼容性測(cè)試,保證了機(jī)器擁有更高的穩(wěn)定性,但是如果要在使用非原裝組件外的東西,就需要對(duì)其基礎(chǔ)有足夠的了解。

關(guān)于 Dubbo 和 Spring Cloud 的相關(guān)概念和對(duì)比,我個(gè)人比較傾向于 Spring Cloud,原因就是真正的微服務(wù)框架、提供整套的組件支持、使用簡(jiǎn)單方便、強(qiáng)大的社區(qū)支持等等,另外,因?yàn)榭紤]到 .NET/.NET Core 的兼容處理,RPC 并不能很好的實(shí)現(xiàn)跨語(yǔ)言(需要借助跨語(yǔ)言庫(kù),比如 gRPC、Thrift,但因?yàn)?Dubbo 本身就是“gRPC”,在 Dubbo 之上再包一層 gRPC,有點(diǎn)重復(fù)封裝了),而 HTTP REST 本身就是支持跨語(yǔ)言實(shí)現(xiàn),所以,Spring Cloud 這一點(diǎn)還是非常好的(Dubbox 也支持,但性能相比要差一些)。

但凡事無(wú)絕對(duì),每件事物有好的地方也有不好的地方,總的來(lái)說(shuō),Dubbo 和 Spring Cloud 的主要不同體現(xiàn)在兩個(gè)方面:服務(wù)調(diào)用方式不同和專注點(diǎn)不同(生態(tài)不同)。


責(zé)任編輯:武曉燕 來(lái)源: 樓仔
相關(guān)推薦

2023-04-03 15:04:00

RPCPHP語(yǔ)言

2023-03-06 21:29:41

mmap技術(shù)操作系統(tǒng)

2025-04-07 03:02:00

電腦內(nèi)存數(shù)據(jù)

2023-09-08 08:20:46

ThreadLoca多線程工具

2021-07-08 10:08:03

DvaJS前端Dva

2024-07-12 14:46:20

2021-01-13 05:21:59

參數(shù)

2024-11-19 13:20:55

2021-09-07 09:46:40

JavaScriptGenerator函數(shù)

2021-09-11 10:41:27

PythonPickle模塊

2023-12-15 15:55:24

Linux線程同步

2023-09-22 10:45:47

云原生云計(jì)算

2021-11-06 10:18:30

Python變量常量

2021-08-05 06:54:05

觀察者訂閱設(shè)計(jì)

2021-12-01 11:40:14

Python 輸入輸出

2022-03-24 08:51:48

Redis互聯(lián)網(wǎng)NoSQL

2024-04-12 12:19:08

語(yǔ)言模型AI

2021-07-21 05:24:32

EventBus3.0Android單例模式

2021-07-21 09:24:25

MongoDB數(shù)據(jù)庫(kù) Python

2022-11-07 18:36:03

組件RPC框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)