• 使用Thrift RPC编写程序(服务端和客户端)


    1. Thrift类介绍
    Thrift代码包(位于thrift-0.6.1/lib/cpp/src)有以下几个目录:

    concurrency:并发和时钟管理方面的库
    processor:Processor相关类
    protocal:Protocal相关类
    transport:transport相关类
    server:server相关类

     
    1.1 Transport类(how is transmitted?)
    负责数据传输,有以下几个可用类:
    TFileTransport:文件(日志)传输类,允许client将文件传给server,允许server将收到的数据写到文件中;
    THttpTransport:采用Http传输协议进行数据传输;
    TSocket:采用TCP Socket进行数据传输;
    TZlibTransport:压缩后对数据进行传输,或者将收到的数据解压。
    下面几个类主要是对上面几个类地装饰(采用了装饰模式),以提高传输效率。
    TBufferedTransport:对某个Transport对象操作的数据进行buffer,即从buffer中读取数据进行传输,或者将数据直接写入buffer;
    TFramedTransport:同TBufferedTransport类似,也会对相关数据进行buffer,同时,它支持定长数据发送和接收;
    TMemoryBuffer:从一个缓冲区中读写数据。
    1.2 Protocol类(what is transmitted?)
    负责数据编码,主要有以下几个可用类:
    TBinaryProtocol:二进制编码
    TJSONProtocol:JSON编码
    TCompactProtocol:密集二进制编码
    TDebugProtocol:以用户易读的方式组织数据
    1.3 Server类(providing service for clients)
    TSimpleServer:简单的单线程服务器,主要用于测试
    TThreadPoolServer:使用标准阻塞式IO的多线程服务器
    TNonblockingServer:使用非阻塞式IO的多线程服务器,TFramedTransport必须使用该类型的server
    1.5 对象序列化和反序列化 Thrift中的Protocol负责对数据进行编码,因而可使用Protocol相关对象进行序列化和反序列化。
     
     
    2.编写client和server
     
    2.1 client端代码编写
    Client编写的方法分为以下几个步骤:
    (1) 定义TTransport,为你的client设置传输方式(如socket, http等)。
    (2) 定义Protocal,使用装饰模式(Decorator设计模式)封装TTransport,为你的数据设置编码格式(如二进制格式,JSON格式等)
    (3) 实例化client对象,调用服务接口。
    说明:如果用户在thrift文件中定义了一个叫${server_name}的service,则会生成一个叫${server_name}Client的对象。
     
    2.2 Server端代码编写
    (1) 定义一个TProcess,这个是thrift根据用户定义的thrift文件自动生成的类
    (2) 使用TServerTransport获得一个TTransport
    (3) 使用TTransportFactory,可选地将原始传输转换为一个适合的应用传输(典型的是使用TBufferedTransportFactory)
    (4) 使用TProtocolFactory,为TTransport创建一个输入和输出
    (5) 创建TServer对象(单线程,可以使用TSimpleServer;对于多线程,用户可使用TThreadPoolServer或者TNonblockingServer),调用它的server()函数。
    说明:thrift会为每一个带service的thrift文件生成一个简单的server代码(桩),
     
     
    3.示例:
     

    1. thrift生成代码

    创建Thrift文件:G: est hriftdemoHello.thrift ,内容如下:

     
    namespace java com.micmiu.thrift.demo
     
    service  HelloWorldService {
      string sayHello(1:string username)
    }
    thrift-0.8.0.exe 是官网提供的windows下编译工具,运用这个工具生成相关代码:
    thrift-0.8.0.exe -r -gen java ./demoHello.thrift
     
    将生成的HelloWorldService.java 文件copy到自己测试的工程中,我的工程是用maven构建的,故在pom.xml中增加如下内容:
     
    <dependency>
         <groupId>org.apache.thrift</groupId>
         <artifactId>libthrift</artifactId>
         <version>0.8.0</version>
    </dependency>
    <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>1.5.8</version>
    </dependency>
     

    2. 实现接口Iface

    java代码:HelloWorldImpl.java
     
    package com.micmiu.thrift.demo;
    import org.apache.thrift.TException;

    public class HelloWorldImpl implements HelloWorldService.Iface {
         public HelloWorldImpl() {
         }
         @Override
         public String sayHello(String username) throws TException {
              return "Hi," + username + " welcome to my blog www.micmiu.com";
         }
    }
     

    3.TSimpleServer服务端

    简单的单线程服务模型,一般用于测试。

    编写服务端server代码:HelloServerDemo.java
     
    package com.micmiu.thrift.demo;
    import org.apache.thrift.TProcessor;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.protocol.TCompactProtocol;
    import org.apache.thrift.protocol.TJSONProtocol;
    import org.apache.thrift.protocol.TSimpleJSONProtocol;
    import org.apache.thrift.server.TServer;
    import org.apache.thrift.server.TSimpleServer;
    import org.apache.thrift.transport.TServerSocket;

    public class HelloServerDemo {
         public static final int SERVER_PORT = 8090;
         public void startServer() {
              try {
                   System.out.println("HelloWorld TSimpleServer start ....");
                   TProcessor tprocessor = new HelloWorldService.Processor&lt;HelloWorldService.Iface&gt;(
                             new HelloWorldImpl());
                   // HelloWorldService.Processor&lt;HelloWorldService.Iface&gt; tprocessor =
                   // new HelloWorldService.Processor&lt;HelloWorldService.Iface&gt;(
                   // new HelloWorldImpl());
                   // 简单的单线程服务模型,一般用于测试
                   TServerSocket serverTransport = new TServerSocket(SERVER_PORT);
                   TServer.Args tArgs = new TServer.Args(serverTransport);
                   tArgs.processor(tprocessor);
                   tArgs.protocolFactory(new TBinaryProtocol.Factory());
                   // tArgs.protocolFactory(new TCompactProtocol.Factory());
                   // tArgs.protocolFactory(new TJSONProtocol.Factory());
                   TServer server = new TSimpleServer(tArgs);
                   server.serve();
              } catch (Exception e) {
                   System.out.println("Server start error!!!");
                   e.printStackTrace();
              }
         }
         /**
         * @param args
         */
         public static void main(String[] args) {
              HelloServerDemo server = new HelloServerDemo();
              server.startServer();
         }
    }
     
    编写客户端Client代码:HelloClientDemo.java
     
    package com.micmiu.thrift.demo;
    import org.apache.thrift.TException;
    import org.apache.thrift.protocol.TBinaryProtocol;
    import org.apache.thrift.protocol.TCompactProtocol;
    import org.apache.thrift.protocol.TJSONProtocol;
    import org.apache.thrift.protocol.TProtocol;
    import org.apache.thrift.transport.TSocket;
    import org.apache.thrift.transport.TTransport;
    import org.apache.thrift.transport.TTransportException;

    public class HelloClientDemo {
         public static final String SERVER_IP = "localhost";
         public static final int SERVER_PORT = 8090;
         public static final int TIMEOUT = 30000;
         /**
         *
         * @param userName
         */
         public void startClient(String userName) {
              TTransport transport = null;
              try {
                   transport = new TSocket(SERVER_IP, SERVER_PORT, TIMEOUT);
                   // 协议要和服务端一致
                   TProtocol protocol = new TBinaryProtocol(transport);
                   // TProtocol protocol = new TCompactProtocol(transport);
                   // TProtocol protocol = new TJSONProtocol(transport);
                   HelloWorldService.Client client = new HelloWorldService.Client(
                             protocol);
                   transport.open();
                   String result = client.sayHello(userName);
                   System.out.println("Thrify client result =: " + result);
              } catch (TTransportException e) {
                   e.printStackTrace();
              } catch (TException e) {
                   e.printStackTrace();
              } finally {
                   if (null != transport) {
                        transport.close();
                   }
              }
         }
         /**
         * @param args
         */
         public static void main(String[] args) {
              HelloClientDemo client = new HelloClientDemo();
              client.startClient("Michael");
         }
    }
     

    先运行服务端程序,日志如下:

     
    HelloWorld TSimpleServer start ....

    再运行客户端调用程序,日志如下:

     
    Thrify client result =: Hi,Michael welcome to my blog www.micmiu.com

    测试成功,和预期的返回信息一致。

     
     
    总结:Server端和client端编码基本步骤
     

    1.服务端编码基本步骤:

    • 实现服务处理接口impl
    • 创建TProcessor
    • 创建TServerTransport
    • 创建TProtocol
    • 创建TServer
    • 启动Server

    2.客户端编码基本步骤:

    • 创建Transport
    • 创建TProtocol
    • 基于TTransport和TProtocol创建 Client
    • 调用Client的相应方法
     
     
    参考资料:http://www.micmiu.com/soa/rpc/thrift-sample/
                   http://dongxicheng.org/search-engine/thrift-rpc/
                   
  • 相关阅读:
    面试时面试官想要听到什么答案(关于一些vue的问题)
    Redis主从复制以及主从复制原理
    当面试官问你:如何进行性能优化?
    swoole通往大神之路——swoole任务中心说明及进程任务架构搭建
    全局句柄表
    句柄表(私有句柄表)
    关于VAD的两种内存隐藏方式
    通过修改VAD属性破除锁页机制
    R3环申请内存时页面保护与_MMVAD_FLAGS.Protection位的对应关系
    利用内存锁定技术防止CE修改
  • 原文地址:https://www.cnblogs.com/pdca/p/4454558.html
Copyright © 2020-2023  润新知