• thrift入门学习


    目录

    Thrift基础

    1.数据类型

    基本类型

    值得注意的是没有无符号类型

    • bool表示一个布尔值,取true或false

    • byte表示一个带符号字节

    • i16表示一个带符号16位整型

    • i32表示一个带符号32位整型

    • i64表示一个带符号64位整型

    • double表示一个带符号64位浮点数

    • string 表示一个使用UTF-8编码的字符串

    结构

    类似于c语言中的结构体

    struct Example {
      1:i32 number=10,
      2:i64 bigNumber,
      3:double decimals,
      4:string name="thrifty"
    }

    容器

    在Thrift中,有3种可供使用的容器

    • list<type> 一个有序重复元素列表,可映射为C++中STL vector,Java中的ArrayList

    • set<type> 一个无序不重复元素集合,可映射为C++中STL set,Java中的HashSet

    • map<type1, type2>一个键值对映射表,可映射为C++中STL map,Java中的HashMap

    异常

    exception RequestException {
      1:i32 code;
      2:string detail;
    }

    服务

    service StringCache {
      void set(1:i32 key, 2:string value),
      string get(1:i32 key) throws (1:KeyNotFound knf),
      void delete(1:i32 key)
    }

    2.Thrift HelloWorld

    创建ThriftTest项目,项目包含3个模块,thrift-idl,thrift-server,thrift-client。

    2.1 thrift-idl模块

    thrift-idl模块的作用是定义idl文件,idl文件相当于是client端和server端的通信约定。

    下面的Hello.thrift就是idl文件,将其放到main/thrift这个目录下面。

    Hello.thrift的内容如下

    代码块
    namespace java thrift.demo
    service Hello{
        string echo(1:string str)
    }

    添加thrift相关的maven依赖和插件

            <dependency>
                <groupId>org.apache.thrift</groupId>
                <artifactId>libthrift</artifactId>
                <version>0.8.0</version>
            </dependency>
            <plugins>
                <plugin>
                    <groupId>org.apache.thrift.tools</groupId>
                    <artifactId>maven-thrift-plugin</artifactId>
                    <version>0.1.11</version>
                    <executions>
                        <execution>
                            <id>thrift-sources</id>
                            <phase>generate-sources</phase>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>thrift-test-sources</id>
                            <phase>generate-test-sources</phase>
                            <goals>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>

    然后,执行mvn install命令安装thrift-idl的jar包到本地,以便thrift-server模块和thrift-client模块能够引入。

    2.2 thrift-server模块

    引入依赖

            <dependency>
                <groupId>thrift.demo</groupId>
                <artifactId>thrift-idl</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--thrift依赖slf4j进行日志输出-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.5</version>
            </dependency>

    创建HelloServiceImpl类,并实现Hello.Iface接口。

    public class HelloServiceImpl implements Hello.Iface{
    ​
        @Override
        public String echo(String str) throws TException {
            return "server端收到的数据为[" + str + "]";
        }
    }
     

    创建server端。

    public class App
    {
        public static void main( String[] args )
        {
            try {
                System.out.println("服务端开启....");
                //1.创建TProcessor,TProcessor依赖了上面的HelloServiceImpl的具体实例
                TProcessor tprocessor = new Hello.Processor<Hello.Iface>(new HelloServiceImpl());
                //2.创建TserverTransport
                TServerSocket serverTransport = new TServerSocket(9898);
                //3.创建TProtocol
                TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory();
                TServer.Args tArgs = new TServer.Args(serverTransport);
                tArgs.processor(tprocessor);
                tArgs.protocolFactory(factory);
                //4.创建Tserver,传入需要的参数,server将以上内容集成在一起
                TServer server = new TSimpleServer(tArgs);
                //5.启动server
                server.serve();
            }catch (TTransportException e) {
                e.printStackTrace();
            }
        }
    }

    2.3 thrift-client模块

    引入依赖

            <dependency>
                <groupId>thrift.demo</groupId>
                <artifactId>thrift-idl</artifactId>
                <version>1.0-SNAPSHOT</version>
            </dependency>
            <!--thrift依赖slf4j进行日志输出-->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.5</version>
            </dependency> 

    创建client端

    public class App
    {
        public static void main( String[] args ) {
            System.out.println("客户端启动....");
            TTransport transport = null;
            try {
                //1.创建TTransport
                transport = new TSocket("localhost", 9898, 30000);
                // 2.创建TProtocol  协议要和服务端一致
                TProtocol protocol = new TBinaryProtocol(transport);
                //3.创建Client 打开transport
                Hello.Client client = new Hello.Client(protocol);
                transport.open();
                //4.调用Client响应方法
                String result = client.echo("哈哈");
                System.out.println("Thrift client result =: " + result);
            } catch (TTransportException e) {
                e.printStackTrace();
            } catch (TException e) {
                e.printStackTrace();
            } finally {
                if (null != transport) {
                    transport.close();
                }
            }
        }
    }
     

    2.4 运行

    依次启动server端和client端,将可以看到client端调用成功,输出如下。

    客户端启动....
    Thrift client result =: server端收到的数据为[哈哈]

    Thrift原理分析

    Thrift网络栈

     

     +-------------------------------------------+
      | Server                                    |
      | (single-threaded, event-driven etc)       |
      +-------------------------------------------+
      | Processor                                 |
      | (compiler generated)                      |
      +-------------------------------------------+
      | Protocol                                  |
      | (JSON, compact etc)                       |
      +-------------------------------------------+
      | Transport                                 |
      | (raw TCP, HTTP etc)                       |
      +-------------------------------------------+
    
    

    Transport

    Transport定义了服务端和客户端的消息的传输方式,比如http或socket

    Protocol

    Protocol定义了消息的传输协议,比如JSON、xml、二进制格式

    Processor

    Processor是需要用户自己实现的消息处理器,用于处理业务逻辑

    Server

    Server将上面的组件组装起来。从transport接受序列化消息,根据protocol协议反序列化,调用用户定义的消息处理器processor,并将消息处理器返回结果序列化,然后写回transport响应客户端。

    Thrift支持的传输方式

    Thrift封装了一层传输层来支持底层的网络通信,在Thrift中称为Transport,不仅提供open,close,flush等方法,还有一些read/write方法.

    • TSocket:阻塞式IO的Transport实现,用在客户端.

    • TServerSocket:非阻塞式Socket,用于服务器端,用于监听TSocket.

    • TNonblockingSocket:非阻塞式IO的实现

    • TMemoryInputTransport: 封装了一个字节数组byte[]来做输入流的封装

    • TFramedTransport- 同样使用非阻塞方式,按块的大小进行传输,输入流封装了TMemoryInputTransport

    Thrift支持的传输协议

    Thrift支持多种传输协议,我们可以根据自己的需要来选择合适的类型,总体上来说,分为文本传输和二进制传输,由于二进制传输在传输速率和节省带宽上有优势,所以大部分情况下使用二进制传输是比较好的选择。

    • TBinaryProtocol:使用二进制编码格式传输,是Thrift默认的传输协议

    • TCompactProtocol:使用压缩格式传输

    • TJSONProtocol:使用Json格式传输

    • TDebugProtocol:使用易读易懂的文本格式进行传输,以便进行debug

    • TSimpleJSONProtocol:提供JSON只写的协议,适用于通过脚本语言解析

    Thrift支持的服务模型

    • TSimpleServer:这种工作模式只有一个线程,循环监听传过来的请求并对其进行处理,处理完才能接受下一个请求,是一种阻塞式IO的实现,因为效率比较低,实际线上环境一般用不到.一般用于开发时候演示工作流程时使用。

    • TNonblockingServer:(单线程+IO多路复用)这种模式与TsimpleServer最大的区别就是使用NIO,也就是非阻塞是IO的方式实现IO的多路复用,它可以同时监听多个socket的变化,但因为业务处理上还是单线程模式,所以在一些业务处理比较复杂耗时的时候效率还是不高,因为多个请求任务依然需要排队一个一个进行处理.

    • TThreadPoolServer:(多线程+阻塞IO)这种模式引入了线程池,主线程只负责accept,即监听Socket,当有新的请求(客户端Socket)来时,就会在线程池里起一个线程来处理业务逻辑,这样在并发量比较大的时候(但不超过线程池的数量)每个请求都能及时被处理,效率比较高,但一旦并发量很大的时候(超过线程池数量),后面来的请求也只能排队等待.

    • TThreadedSelectorServer:(多线程+IO多路复用)这是一种多线程半同步半异步的服务模型,是Thrift提供的最复杂最高级的服务模型,内部有一个专门负责处理监听Socket的线程,有多个专门处理业务中网络IO的线程,有一个专门负责决定将新Socket连接分配给哪一个线程处理的起负载均衡作用的线程,还有一个工作线程池.这种模型既可以响应大量并发连接的请求又可以快速对wangluoIO进行读写,能适配很多场景,因此是一种使用比较高频的服务模型.

    参考资料

    http://thrift.apache.org/docs/concepts Thrift network stack(官网)

  • 相关阅读:
    文本字符集转换
    添加HP消息队列
    fedora19/opensuse13.1 配置svn client
    前端html---介绍前端,标签,列表
    数据分析1
    项目流程
    git 使用
    mongo基础
    linux上面pycharm汉化
    pythonNet 09协程
  • 原文地址:https://www.cnblogs.com/yeyang/p/12580739.html
Copyright © 2020-2023  润新知