Thrift 初認識 & Thrift 和Dubbo 的區別

【thirft 簡介】

維基百科:
Thrift是一種接口描述語言和二進制通訊協議,[1]它被用來定義和創建跨語言的服務。[2]它被當作一個遠程過程調用(RPC)框架來使用,是由Facebook爲“大規模跨語言服務開發”而開發的。它通過一個代碼生成引擎聯合了一個軟件棧,來創建不同程度的、無縫的跨平臺高效服務,可以使用C#、C++(基於POSIX兼容系統[3])、Cappuccino、[4]Cocoa、Delphi、Erlang、Go、Haskell、Java、Node.js、OCaml、Perl、PHP、Python、Ruby和Smalltalk。[5]雖然它以前是由Facebook開發的,但它現在是Apache軟件基金會的開源項目了。該實現被描述在2007年4月的一篇由Facebook發表的技術論文中,該論文現由Apache掌管

簡單來說thrift就是Facebook 開發的一個語言中立、平臺中立的RPC 框架。

mac 環境使用brew 安裝:

brew install thrift

PRC

先簡要說一下什麼是RPC。

RPC,即Remote Procedure Call,意爲遠程過程調用,什麼是遠程過程調用?舉個簡單的例子:

假設你和兄弟住在同一個房間,你在外面時突然想起衣服忘洗了,於是打電話讓兄弟把衣服洗了

在這個例子中你和兄弟就相當於兩個應用A/B,你在外面就相當於兩個不同的服務環境,洗衣服就相當於一個服務。

A 應用想調用B應用的服務,但因爲不在同一個環境所以無法操作成功,就相當於你在外面不能洗衣服,而兄弟可以。於是你打電話給兄弟,讓他幫你洗衣服,就是一次遠程過程調用。

遠程過程調用需要在A、B之間建立一個通信通道,就相當於你給兄弟打電話需要通訊信號,手機的那一套的東西,RPC 框架就是把那一套給你屏蔽了,就相當於你只需要買個手機、電話卡就行了。電話與電話之間怎麼鏈接的你就不用管了。

Thrift 語言中立

thrift 通過一箇中間語言IDL(接口定義語言)來定義RPC的數據類型和接口,以.thrift 結尾,然後可以根據需求編譯成想要的文件。

比如創建一個服務Hello,創建文件Hello.thrift,代碼如下:

namespace java service.demo
service Hello{
    string helloString(1:string para)
}

然後通過命令生成java 代碼:

thrift -r -gen java Hello.thrift

生成的代碼中不但包含目標語言的接口定義、方法、數據類型,還包含有RPC協議層和傳輸層的實現代碼:

/**
 * Autogenerated by Thrift Compiler (0.13.0)
 *
 * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
 *  @generated
 */
package com.thrift;

@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
@javax.annotation.Generated(value = "Autogenerated by Thrift Compiler (0.13.0)", date = "2020-02-20")
public class Hello {

  public interface Iface {

    public String helloString(String para) throws org.apache.thrift.TException;

  }

  public interface AsyncIface {

    public void helloString(String para, org.apache.thrift.async.AsyncMethodCallback<String> resultHandler) throws org.apache.thrift.TException;

  }

  public static class Client extends org.apache.thrift.TServiceClient implements Iface {
    public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
      public Factory() {}
      public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
        return new Client(prot);
      }
      public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
        return new Client(iprot, oprot);
      }
    }

    public Client(org.apache.thrift.protocol.TProtocol prot)
    {
      super(prot, prot);
    }

    public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
      super(iprot, oprot);
    }

    public String helloString(String para) throws org.apache.thrift.TException
    {
      send_helloString(para);
      return recv_helloString();
    }

    public void send_helloString(String para) throws org.apache.thrift.TException
    {
      helloString_args args = new helloString_args();
      args.setPara(para);
      sendBase("helloString", args);
    }

    public String recv_helloString() throws org.apache.thrift.TException
    {
      helloString_result result = new helloString_result();
      receiveBase(result, "helloString");
      if (result.isSetSuccess()) {
        return result.success;
      }
      throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "helloString failed: unknown result");
    }

  }
  ...

}

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-AgIG8Rbh-1582208172872)(http://note.youdao.com/yws/res/10552/54EC0AF180E64D34B7D2262F2376D39A)]

當然也可以生產c++ 或者其他的開發語言看自己的需求。

Thirft demo該博客需要把thrift maven版本升級到0.12.0,不然會找不到annotation 類的錯誤

Thrift 協議棧

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Dc3Kx6sE-1582208172874)(http://note.youdao.com/yws/res/10559/A8D89B272593441BBDA9F808FEA27A77)]
Thrift是一種c/s的架構體系。Server主要任務是高效的接受客戶端請求,並將請求轉發給Processor處理。

  • 最上層是用戶自行實現的業務邏輯代碼;
  • Processor是由thrift編譯器自動生成的代碼,它封裝了從輸入數據流中讀數據和向數據流中寫數據的操作,它的主要工作是:從連接中讀取數據,把處理交給用戶實現impl,最後把結果寫到連接上。
  • TProtocol(協議層),定義數據傳輸格式,例如:
    • TBinaryProtocol:二進制格式;
    • TCompactProtocol:壓縮格式;
    • TJSONProtocol:JSON格式;
    • TSimpleJSONProtocol:提供JSON只寫協議, 生成的文件很容易通過腳本語言解析;
    • TDebugProtocol:使用易懂的可讀的文本格式,以便於debug
  • TTransport(傳輸層),定義數據傳輸方式,可以爲TCP/IP傳輸,內存共享或者文件共享等)被用作運行時庫。
    • TSocket:阻塞式socker;
    • TFramedTransport:以frame爲單位進行傳輸,非阻塞式服務中使用;
    • TFileTransport:以文件形式進行傳輸;
    • TMemoryTransport:將內存用於I/O,java實現時內部實際使用了簡單的ByteArrayOutputStream;
    • TZlibTransport:使用zlib進行壓縮, 與其他傳輸方式聯合使用,當前無java實現
  • 底層IO負責實際的數據傳輸,包括socket、文件和壓縮數據流等。
  • Thrift支持的服務模型
    • TSimpleServer:簡單的單線程服務模型,常用於測試;
    • TThreadPoolServer:多線程服務模型,使用標準的阻塞式IO;
    • TNonblockingServer:多線程服務模型,使用非阻塞式IO(需使用TFramedTransport數據傳輸方式);

【Thrift 與Dubbo 的區別】

轉載自參考博客:https://blog.csdn.net/JustKian/article/details/102495650

透明化服務調用

Thrift:通過IDL(接口定義語言)實現,Thrift是支持跨語言的,而要實現跨語言機制,就需要一種中間語言來完成,那就是IDL。首先定義好了IDL之後(即定義好了一個service),由於server和Client都需要持有這個與之語言相對應的服務接口,那就需要thrift來將IDL編譯成與之語言相對應的接口類,比如server端是java,client端是C#,則server端需要編譯成java類,client編譯成C#類。然後server端負責接口的具體實現,client只需要持有這個對象接口,進行調用即可,然後通過網絡通信傳給server。server負責解析client傳遞過來的數據,由於服務對象接口統一爲IDL(thrift格式),所以統一瞭解析形式,只和本地的開發語言有關。

Dubbo:通過java反射和動態代理實現這一功能,由於只支持Java,所以Client和Server端開發語言機制一樣,所以它們能夠通過spring框架進行依賴,server端一般將對象方法接口註冊發佈到Zookeper中,然後Client可以直接從Zookeper中獲取server端發佈的對象方法接口,這樣Client可以通過Spring進行自動裝配獲得server端發佈的對象方法服務接口。

網絡通信

thrift 參考上文

Thrift實際上是實現了C/S模式,通過代碼生成工具將thrift文生成服務器端和客戶端代碼(可以爲不同語言),從而實現服務端和客戶端跨語言的支持。用戶在Thirft文件中聲明自己的服務,這些服務經過編譯後會生成相應語言的代碼文件,然後客戶端調用服務,服務器端提服務便可以了。

dubbo網絡通訊層主要實現了以下功能:

  • 多種網絡通訊框架的抽象封裝(netty,mina,grizzly)
  • 每個客戶端主機和服務端保存單個長鏈接通信
  • 異步調用轉同步
  • tcp鏈接的心跳和自動重連
  • 基於header頭通訊協議,請求的編解碼器

dubbo的網絡通信基於NIO框架,一般基於事件的NIO網絡框架都涉及到 channel , channelHandle核心概念,網絡數據buffer, 網絡數據編解碼器,dubbo爲了能夠適配多種NIO框架,將以上概念全部又抽象了一層接口。如果有netty開發經驗或者瞭解netty helloworld demo程序對於理解這個章節非常有幫助。

參考鏈接:

https://www.jianshu.com/p/1e0c8c08e89d

https://www.jianshu.com/p/1a1404ce2201

https://blog.csdn.net/qq418517226/article/details/51906357

序列化

thrift只支持對thrift協議描述的IDL進行序列化,包含如下幾種序列化格式:

  • TBinaryProtocol:二進制格式;
  • TCompactProtocol:壓縮格式;
  • TJSONProtocol:JSON格式;
  • TSimpleJSONProtocol:提供JSON只寫協議, 生成的文件很容易通過腳本語言解析;
  • TDebugProtocol:使用易懂的可讀的文本格式,以便於debug

dubbo支持各種協議的序列化(實際上,dubbo沒有IDL這一機制,因爲實際上他就是通過java服務對象接口進行交互的)
例如他也可支持thrift協議,只需要thrift將IDL轉換爲一個java服務對象接口,那麼dubbo就可以使用了

【附錄】

  • 基本類型:
    • bool:布爾值,true 或 false,對應 Java 的 boolean
    • byte:8 位有符號整數,對應 Java 的 byte
    • i16:16 位有符號整數,對應 Java 的 short
    • i32:32 位有符號整數,對應 Java 的 int
    • i64:64 位有符號整數,對應 Java 的 long
    • double:64 位浮點數,對應 Java 的 double
    • string:utf-8編碼的字符串,對應 Java 的 String
  • 結構體類型:
    • struct:定義公共的對象,類似於 C 語言中的結構體定義,在 Java 中是一個 JavaBean
  • 容器類型:
    • list:對應 Java 的 ArrayList
    • set:對應 Java 的 HashSet
    • map:對應 Java 的 HashMap
  • 異常類型:
    • exception:對應 Java 的 Exception
  • 服務類型:
    • service:對應服務的類
發佈了24 篇原創文章 · 獲贊 27 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章