Thrift RPC實戰(zhàn)(一) 初次體驗Thrift

1.前言:

Thrift作為Facebook開源的RPC框架, 通過IDL中間語言, 并借助代碼生成引擎生成各種主流語言的rpc框架服務(wù)端/客戶端代碼,主要特點(diǎn):

開發(fā)速度快:

通過編寫RPC接口IDL文件,利用編譯生成器自動生成Server端骨架(Skeletons)和客戶端Stubs,省去開發(fā)者自定義和維護(hù)接口編解碼、消息傳輸、服務(wù)器多線程模型等基礎(chǔ)工作;Server端開發(fā)者只需按照服務(wù)骨架,寫好自己的業(yè)務(wù)處理程序(Handlers)即可,Client端程序只需創(chuàng)建IDL中定義的服務(wù)對象,然后就像調(diào)用本地對象的方法一樣調(diào)用遠(yuǎn)端服務(wù)。

接口維護(hù)簡單高效:

通過維護(hù)Thrift格式的IDL(Interface Description Language)文件(注意寫好注釋),即可作為給Clients使用的接口文檔使用,也自動生成接口代碼,始終保持代碼和文檔的一致性。且Thrift協(xié)議可靈活支持接口的可擴(kuò)展性。

學(xué)習(xí)成本低:

因為其來自Google Protocol Buffers開發(fā)團(tuán)隊,所以其IDL文件風(fēng)格類似Google Protocol Buffers,且更加易讀易懂;特別是RPC服務(wù)接口的風(fēng)格就像寫一個一般的面向?qū)ο蟮腃lass一樣簡單。

初學(xué)者只需參照http://thrift.apache.org/ 幾個小時即可理解和使用Thrift。

多語言/跨語言支持:

Thrift支持C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi等多種語言,即可生成上述語言的服務(wù)器端和客戶端程序。

對于我們經(jīng)常使用的Java、PHP、Python、C++支持良好,雖然對iOS環(huán)境的Objective-C(Cocoa)支持稍遜,但也完全滿足我們的使用要求。

已驗證成熟穩(wěn)定:

Thrift在很多開源項目中已經(jīng)被驗證是穩(wěn)定和高效的,例如Cassandra、Evernode等;在Facebook、Baidu等后臺產(chǎn)品中也有使用。

2.基礎(chǔ)知識

2.1 Thrift 軟件棧

Thrift對軟件棧的定義非常的清晰, 使得各個組件能夠松散的耦合, 針對不同的應(yīng)用場景, 選擇不同是方式去搭建服務(wù).
  


Paste_Image.png

評注:
  Transport: 傳輸層,定義數(shù)據(jù)傳輸方式,可以為TCP/IP傳輸,內(nèi)存共享或者文件共享等
  protocol: 協(xié)議層, 定義數(shù)據(jù)傳輸格式,可以為二進(jìn)制或者XML等
  Processor: 處理層, 這部分由定義的idl來生成, 封裝了協(xié)議輸入輸出流, 并委托給用戶實現(xiàn)的handler進(jìn)行處理.
  Server: 服務(wù)層, 整合上述組件, 提供網(wǎng)絡(luò)模型(單線程/多線程/事件驅(qū)動), 最終形成真正的服務(wù).

Thrift 對語言的支持

Thrift和Google Protobuf相比, 都提供了可擴(kuò)展序列化機(jī)制, 不但兼容性好而且壓縮率高. 兩者在這塊各有長短, 性能上PB稍有優(yōu)勢. 但在語言的支持度上, Protobuf只支持c++/java/python這三種主流的語言, Thrift則幾乎覆蓋了大部分的語言, 從這點(diǎn)上來說, Thrift的優(yōu)勢非常的明顯.

Thrift 支持的數(shù)據(jù)類型

基本類型:
  bool: 布爾值
  byte: 8位有符號整數(shù)
  i16: 16位有符號整數(shù)
  i32: 32位有符號整數(shù)
  i64: 64位有符號整數(shù)
  double: 64位浮點(diǎn)數(shù)
  string: UTF-8編碼的字符串
  binary: 二進(jìn)制串
結(jié)構(gòu)體類型:
  struct: 定義的結(jié)構(gòu)體對象
容器類型:
  list: 有序元素列表
  set: 無序無重復(fù)元素集合
  map: 有序的key/value集合
異常類型:
  exception: 異常類型
服務(wù)類型:
  service: 具體對應(yīng)服務(wù)的類

3.小試牛刀

3.1定義thrift文件


namespace java com.yangyang.thrift.api

service HelloService {
  string hello(1: string name);
}

3.2使用thrift提供的代碼生成工具生成代碼

thrift -gen java -out ../java/ hello.thrift

3.3新建thrift-demo工程

在pom文件中加入thrift以及l(fā)og4j的jar

<dependency>
    <groupId>org.apache.thrift</groupId>
    <artifactId>libthrift</artifactId>
    <version>0.9.3</version>
</dependency>
<dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
</dependency>
<dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.5</version>
</dependency>
<dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.5</version>
</dependency>

編寫服務(wù)端代碼:


package com.yangyang.thrift.server;

import com.yangyang.thrift.api.HelloService;
import com.yangyang.thrift.com.yangyang.thrift.service.HelloServiceImpl;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadPoolServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by chenshunyang on 2016/10/30.
 */
public class ServerDemo {
    public static void main(String[] args) throws TTransportException {
        Logger logger = LoggerFactory.getLogger(ServerDemo.class);
        int port= 9000 ;
        // *) 傳輸層(Transport), 設(shè)置監(jiān)聽端口為9000
        TServerSocket serverTransport = new TServerSocket(port);

        // *) 協(xié)議層
        TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory(true, true);
        // *) 處理層(Processor)
        HelloServiceImpl handler = new HelloServiceImpl();
        HelloService.Processor<HelloServiceImpl> processor = new HelloService.Processor<HelloServiceImpl>(handler);

        // *) 服務(wù)層(Server)
        TServer server = new TThreadPoolServer(
                new TThreadPoolServer.Args(serverTransport)
                        .protocolFactory(protocolFactory)
                        .processor(processor));

        // *) 啟動監(jiān)聽服務(wù)
        server.serve();
        logger.info("服務(wù)已經(jīng)啟動,端口為:"+port);
    }
}

編寫客戶端代碼:

package com.yangyang.thrift;

import com.yangyang.thrift.api.HelloService;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;

/**
 * Created by chenshunyang on 2016/10/30.
 */
public class ClientDemo {
    public static void main(String[] args) throws TException {
        // *) 傳輸層
        TTransport transport = new TSocket("localhost", 9000);
        transport.open();
        // *) 協(xié)議層, 與服務(wù)端對應(yīng)
        TProtocol protocol = new TBinaryProtocol(transport);
        // *) 創(chuàng)建RPC客戶端
        HelloService.Client client = new HelloService.Client(protocol);
        // *) 調(diào)用服務(wù)
        System.out.println(client.hello("chenshunyang"));
        // *) 關(guān)閉句柄
        transport.close();

    }

}

先運(yùn)行服務(wù)端,后運(yùn)行客戶端,觀察結(jié)果,可以看到客戶端輸出結(jié)果:
hello chenshunyang

歡迎大家掃碼關(guān)注我的微信公眾號,與大家一起分享技術(shù)與成長中的故事。


我的微信公眾號.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容