zoukankan      html  css  js  c++  java
  • Apache Thrift使用总结

    使用感受

    之前对Thrift的理解有点不准确,使用之后发现Thrift比想象中的要简单得多。

    Thrift做的事情就是跨语言的分布式RPC,通过编写.thrift文件声明接口类和方法,client调用定义的方法,Server端实现定义的接口。尽管的确RPC是须要网络请求,但不像Netty这样的NIO网络编程库(还要关注许多传输数据中的细节,比方数据怎样序列化、怎样在字节数组里建立结构、怎样在两端解析字节数组、怎样处理Handler里的事件状态、怎样把多个Handler按顺序串起来),Thrift掩盖了传输数据这件事情,开发人员使用的时候就是纯纯的RPC的使用感受。


    基本使用

    Thrift使用起来差点儿没有不论什么门槛,能够看这篇HelloWorld的文章,尽管有点老,可是看完之后基本使用起来没有不论什么障碍了。

    官方给出的这个样例更加全面些,全面在.thrift文件中能够声明的东西列的更全些。

    以下看看两个.thrift的定义:

    shared.thrift

    /**
     * This Thrift file can be included by other Thrift files that want to share
     * these definitions.
     */
    
    namespace java com.baidu.mordor.sink.service
    
    struct SharedStruct {
      1: i32 key
      2: string value
    }
    
    service SharedService {
      SharedStruct getStruct(1: i32 key)
    }

    tutorial.thrift

    /**
     * The first thing to know about are types. The available types in Thrift are:
     *
     *  bool        Boolean, one byte
     *  byte        Signed byte
     *  i16         Signed 16-bit integer
     *  i32         Signed 32-bit integer
     *  i64         Signed 64-bit integer
     *  double      64-bit floating point value
     *  string      String
     *  binary      Blob (byte array)
     *  map<t1,t2>  Map from one type to another
     *  list<t1>    Ordered list of one type
     *  set<t1>     Set of unique elements of one type
     *
     * Did you also notice that Thrift supports C style comments?
     */
    
    // Just in case you were wondering... yes. We support simple C comments too.
    
    /**
     * Thrift files can reference other Thrift files to include common struct
     * and service definitions. These are found using the current path, or by
     * searching relative to any paths specified with the -I compiler flag.
     *
     * Included objects are accessed using the name of the .thrift file as a
     * prefix. i.e. shared.SharedObject
     */
    include "shared.thrift"
    
    /**
     * Thrift files can namespace, package, or prefix their output in various
     * target languages.
     */
    namespace java com.baidu.mordor.sink.service
    
    
    /**
     * Thrift lets you do typedefs to get pretty names for your types. Standard
     * C style here.
     */
    typedef i32 MyInteger
    
    /**
     * Thrift also lets you define constants for use across languages. Complex
     * types and structs are specified using JSON notation.
     */
    const i32 INT32CONSTANT = 9853
    const map<string,string> MAPCONSTANT = {'hello':'world', 'goodnight':'moon'}
    
    /**
     * You can define enums, which are just 32 bit integers. Values are optional
     * and start at 1 if not supplied, C style again.
     */
    enum Operation {
      ADD = 1,
      SUBTRACT = 2,
      MULTIPLY = 3,
      DIVIDE = 4
    }
    
    /**
     * Structs are the basic complex data structures. They are comprised of fields
     * which each have an integer identifier, a type, a symbolic name, and an
     * optional default value.
     *
     * Fields can be declared "optional", which ensures they will not be included
     * in the serialized output if they aren't set.  Note that this requires some
     * manual management in some languages.
     */
    struct Work {
      1: i32 num1 = 0,
      2: i32 num2,
      3: Operation op,
      4: optional string comment,
    }
    
    /**
     * Structs can also be exceptions, if they are nasty.
     */
    exception InvalidOperation {
      1: i32 what,
      2: string why
    }
    
    /**
     * Ahh, now onto the cool part, defining a service. Services just need a name
     * and can optionally inherit from another service using the extends keyword.
     */
    service Calculator extends shared.SharedService {
    
       void ping(),
    
       i32 add(1:i32 num1, 2:i32 num2),
    
       i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),
    
       /**
        * This method has a oneway modifier. That means the client only makes
        * a request and does not listen for any response at all. Oneway methods
        * must be void.
        */
       oneway void zip()
    
    }
    
    

    Thrift通过IDL(接口定义语言),在.thrift文件中声明接口类和方法,声明struct结构、const、Exception等,还能够include别的.thrift文件,这套语法与C很类似。通过编写IDL和generate代码,做到了不同语言之间的RPC,client实现接口类和使用结构类的时候很easy好用。
    上面样例的代码能够从官方下载到,能够放到本地看一下他的使用,很easy。


    Thrift重要组件

    Thrift API里三个重要组成部分:Protocal,Transport,Server。


    Protocal定义了消息怎样序列化。常见的是TBinaryProtocol,TJSONProtocol,TCompactProtocol。


    Transport定义了消息在client和服务端怎样通信。常见的是TSocket,TFramedTransport,TNonblockingTransport等。


    Server从transport端接收序列化后的消息,依据protocal反序列化回来,然后调用用户实现的消息handler(接口实现类),最后把返回的数据序列化后再传回给client。常见的TServer为TSimpleServer,THsHaServer,TThreadPoolServer,TNonBlockingServer,TThreadedSelectorServer。以下会详细介绍各个Server的特点,开发人员须要选择适合自己场景的一套 Server+相应的Transport+相应的Protocol。


    TServer说明

    Thrift实现的几种不同的TServer。对于Java而言,版本号按0.9.0为准:

    TSimpleServer在sever端仅仅有一个I/O堵塞的单线程,每次仅仅接受并服务一个client,适合測试使用,不能用于线上服务。


    TNonblockingServer改动了TSimpleServer里堵塞的缺点,借助NIO里的Selector实现非堵塞I/O,同意多个client连接而且client能够使用select()选择。可是处理消息和select()的是同一个线程,当有大量client连接的时候,性能是不理想的。


     THsHaServer(半同步半异步server)在以上基础上,使用一个单独线程来处理网络I/O,一个worker线程池来处理消息。优点是仅仅要有空暇worker线程,消息能够被及时、并行处理,吞吐量会大一些。


    TThreadedSelectorServer,与THsHaServer的差别是处理网络I/O也是多线程了,它维护两个线程池,一个负责网络I/O,一个负责数据处理。优点是当网络I/O是瓶颈的情况下,性能比THsHaServer更好。


    TThreadPoolServer有一个专用的线程来接收connections,连接被建立后,会从ThreadPoolExecutor里取一个工作线程来负责这次连接,直到连接断开后线程回到线程池里,且线程池大小可配。也就是说,并发性的大小可依据服务器设定,假设不介意开许多线程的话,TThreadPoolServer是个还不错的选择。


    全文完 :)


  • 相关阅读:
    loaded some nib but the view outlet was not set
    指标评比
    IOS DEVELOP FOR DUMMIES
    软件测试题二
    javascript select
    DOM节点类型详解
    mysql操作
    UVA 10055
    solutions for 'No Suitable Driver Found For Jdbc'
    解决git中文乱码问题
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4182949.html
Copyright © 2011-2022 走看看