zoukankan      html  css  js  c++  java
  • 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(官网)

  • 相关阅读:
    10 个雷人的注释,就怕你不敢用!
    Java 14 之模式匹配,非常赞的一个新特性!
    poj 3661 Running(区间dp)
    LightOJ
    hdu 5540 Secrete Master Plan(水)
    hdu 5584 LCM Walk(数学推导公式,规律)
    hdu 5583 Kingdom of Black and White(模拟,技巧)
    hdu 5578 Friendship of Frog(multiset的应用)
    hdu 5586 Sum(dp+技巧)
    hdu 5585 Numbers
  • 原文地址:https://www.cnblogs.com/yeyang/p/12580739.html
Copyright © 2011-2022 走看看