【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:對應服務的類