The Apache Thrift

1. 下载Thrift

  http://thrift.apache.org/download/

  - thrift-0.9.1.tar.gz

  - Thrift compiler for Windows (thrift-0.9.1.exe) : window下编译环境,OS、Linux 需要自己安装编译环境

2. 编写.thrift 文件

  - Thrift Types

    Base Types: bool ( A boolean value - true or false) ,  byte ( An 8-bit signed integer ) , 

          i16 ( A 16-bit signed integer ) ,  i32 ( A 32-bit signed integer ) , 

          i64 ( A 64-bit signed integer ) ,  double ( A 64-bit floating point number ) , 

          string ( A text string encoded using UTF-8 encoding ) ;

    Special Types: binary ( A sequence of unencoded bytes, a specialized form of the

              string type above ) ;

    Containers:  list ( An ordered list of elements, Java ArrayList ) , 

          set ( An unordered set of unique elements, Java HashSet ) , 

          map ( A map of strictly unique keys to values, Java HashMap );

    struct :  define a common object ;

    exception :  与struct类似,通常定义异常处理类;

    service :  相当于定义接口或者抽象类,定义有参数列表、有返回值的方法 ;

  - Thrift IDL

    Description

    Document  ::=  Header* Definition*   

            ( 0 or more headers followed by 0 or more definitions )

      Header ::=  Include | CppInclude | Namespace

              ( a Thrift include / a C++ include / a namespace declaration )

        Include : 导入其他thrift文件  ( e. include "shared.thrift" )

        Namespace : 根据目标语言指定namespace, package, 或 prefix,

              目标语言-'*' | 'cpp' | 'java' | 'py' | 'perl' | 'rb' | 'cocoa' | 'csharp'

              (e. namespace java org.apache.thrift  目标语言java,指定包名)

      Definition ::=  Const | Typedef | Enum | Senum | Struct | Union | Exception | Service

        Const ::=  'const' FieldType Identifier '=' ConstValue ListSeparator?  

             定义全局常量 ( e. const i32 INT32CONSTANT = 9853 )

        Typedef : 定义类型别名 ( e. typedef i32 MyInteger) 

        Enum  ::=  'enum' Identifier '{' (Identifier ('=' IntConstant)? ListSeparator?)* '}'

             定义枚举类型,值类型i32,值可选,默认值生成器从1开始,无负数

        Struct ::=  'struct' Identifier 'xsd_all'? '{' Field* '}' 定义对象

        Union  ::=  'union' Identifier 'xsd_all'? '{' Field* '}' 类似Struct, 类似C++ union {} in .

        Exception  ::=  'exception' Identifier '{' Field* '}' 类似Struct,通常定义异常处理机制

        Service ::=  'service' Identifier ( 'extends' Identifier )? '{' Function* '}'  

             定义一组服务接口,service可继承service

      ------------------------------------------

      上述表达式说明:

    Field  ::=  FieldID? FieldReq? FieldType Identifier ('= ConstValue)? ListSeparator?  

             ( e.  1: i32 num1 = 0,)

      FieldID         ::=  IntConstant ':'

      FieldReq        ::=  'required' | 'optional'

    Function  ::=  'oneway'? FunctionType Identifier '(' Field* ')' Throws? ListSeparator?  

            ( e. i32 add(1:i32 num1, 2:i32 num2),)

      FunctionType    ::=  FieldType | 'void'

      Throws          ::=  'throws' '(' Field* ')'

      'oneway' 表示客户端请求无须等待响应,返回值必须是void.  (e. oneway void zip() )

    FieldType ::= Identifier | BaseType | ContainerType

    DefinitionType ::= BaseType | ContainerType

      BaseType ::= 'bool' | 'byte' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary' | 'slist'

      ContainerType ::= MapType | SetType | ListType

        MapType ::= 'map' CppType? '<' FieldType ',' FieldType '>'

        SetType ::= 'set' CppType? '<' FieldType '>'

        ListType ::= 'list' '<' FieldType '>' CppType?

        CppType ::= 'cpp_type' Literal

    Literal   ::=  ('"' [^"]* '"') | ("'" [^']* "'")

    Identifier      ::=  ( Letter | '_' ) ( Letter | Digit | '.' | '_' )*

    ListSeparator   ::=  ',' | ';'

    Letter       ::=  ['A'-'Z'] | ['a'-'z']

    Digit             ::=  ['0'-'9']

 -----------------------------

    实例:  tutorial.thrift

namespace java com.test.message

//常量
const i32 MSG_TYPR = 100

//包装类
struct Message {
  1: i32 userId = 100,
  2: i32 toUserId,
  3: string data,
      //relData 不是必须 (optional)
  4: optional string relData,
}

//定义异常处理类
exception InvalidException {
  1: i32 toUserId,
  2: string error
}

service PushService {
    //Thrift中不存在重载,也就是方法名不能一样
    void send(1:i32 num1, 2:i32 num2, 3:string data, 4:string relDate),
    void sendByMessage(1:Message message)
}

 

3. 编译.thrift 文件,生成代码

  在thrift-0.9.1.exe目录下执行 。 e.  thrift-0.9.1.exe --gen java tutorial.thrift

thrift --gen <language> <Thrift filename> 

  编译后会生成搭建RPC服务器与客户端有用的的源代码。目录结构:

|-- gen-java
|   `-- com
|       `-- test
|           `-- message
|                  |-- InvalidException.java
|                  |-- Message.java
|                  |-- PushService.java
|                  `-- transferConstants.java

 

4. 编写服务端

  首先实现编辑生成的PushService.java 中 PushService.Iface 接口,用于服务端处理服务。

public class PushServiceHandler implements PushService.Iface{
    
    @Override
    public void send(int num1, int num2, String data, String relDate) throws TException {
        System.out.println(" --- ServHandler send ---");
        System.out.println("userId:" + num1 + ", toUserId:" + num2 + ", data:" + data + ", relDate:" + relDate);
    }

    @Override
    public void sendByMessage(Message message) throws TException {
        System.out.println(" --- ServHandler sendByMessage ---");
        System.out.println(message);
    }
}

 

  然后是Service代码

        try {
            // 处理来自客户端的数据
            PushServiceHandler handler = new PushServiceHandler();
            PushService.Processor<PushServiceHandler> processor = new PushService.Processor<PushServiceHandler>(handler);
            
            TServerTransport serverTransport = new TServerSocket(9090);
            // 通过Address和Handler封装Service
            TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
            
            System.out.println("Starting the simple server...");
            server.serve(); // 启动服务
        } catch (Exception e) {
            e.printStackTrace();
        }

 

  Client 主要代码

    try {
            //连接服务端
            TTransport transport = new TSocket("localhost", 9090);
            transport.open();
            //传输协议,可选JSON : TJSONProtocol 等其他协议
            TProtocol protocol = new TBinaryProtocol(transport);
            
            //客户端调用接口
            PushService.Client client = new PushService.Client(protocol);
            
            client.send(100, 10001, "推送信息", "关联内容");
            System.out.println("--- Client send ---");

            client.sendByMessage(new Message(100, 10001, "推送信息"));
            System.out.println("--- Client sendByMessage ---");
            
            //关闭连接
            transport.close();
            
        } catch (Exception e) {
            e.printStackTrace();
        }

 

  运行Service,等待Client调用;

  运行Client,传递数据到Service,等待Service返回数据,处理返回结果,线程结束。

Client:

--- Client send ---
--- Client sendByMessage ---

Server:
Starting the simple server...
--- ServHandler send --- userId:100, toUserId:10001, data:推送信息, relDate:关联内容 --- ServHandler sendByMessage --- Message(userId:100, toUserId:10001, data:推送信息)

 

  

5.   Protocols, Transports and Servers

  Protocols: 支持文本与二进制协议,二进制远优于文本协议,文本协议多用于开发调试。

    TBinaryProtocol - 二进制编码

    TCompactProtocol - 二进制编码,非常高效,使用Variable-Length Quantity (VLQ) 进行编码

    TJSONProtocol - 使用JSON格式进行编码

    TSimpleJSONProtocol - 提供只写的JSON编码,适用于脚本解析

    TDebugProtocol - 在开发模式中提供可阅读的文本编码 (C++)

  transports: 上面protocols定义了"what"-传输什么,而transports定义了"how"-怎样传输

    TSocket - 堵塞式I/O进行传输

    TFramedTransport - 分块传输,当service端使用非阻塞式服务( TNonblockingServer )的时候使用

    TFileTransport - 写入到文件进行传输

    TZlibTransport - 采用zlib进行压缩,与其他传输相结合,不提供java实现

  servers: 每一个Server只能有一个Service

    TSimpleServer - 单线程,标准阻塞式I/O,常用于测试

    TThreadPoolServer - 多线程,标准阻塞式I/O

    TNonblockingServer - 多线程,非阻塞式I/O ( JAVA实现使用NIO ),传输协议必须用TFramedTransport

 

参考资料:

  http://jnb.ociweb.com/jnb/jnbJun2009.html

  http://thrift.apache.org/

  http://thrift.apache.org/static/files/

  http://www.thrift.pl/

  http://wiki.apache.org/thrift/

  http://www.javacodegeeks.com/2012/03/apache-thrift-quickstart-tutorial.html

  http://en.wikipedia.org/wiki/Variable_length_unsigned_integer

 

 

转载于:https://www.cnblogs.com/cmoske/p/3499057.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值