Thrift教程

PRC:远程服务调用,也是一种网络协议,使用TCP连接实现,类似HTTP。

Thrift是一种RPC框架,开发人员通过编写IDL定义两个服务之间的接口,然后通过Thrift自动生成代码(包括网络服务端和客户端,通信对象),即开发人员只需要编写业务相关代码,无需关心数据的通信的过程。

Thrift的底层数据序列化使用的是Google的Protobuf。

结构

Thrift的客户端和服务端需要配置相关参数:

  • Transport:对网络的抽象,服务器端需要传入Socket对象,客户端需要知道服务端的ip+端口号
  • Protocol:客户端和服务端相互通信的协议类型
  • Processor:业务处理逻辑,即RPC调用方法的内部实现,只有服务端需要。
    Thrift教程_第1张图片

语法

基本数据类型

thrift不支持无符号类型,因为很多编程语言不存在无符号类型

  • byte:有符号字节
  • i16:16位有符号整数
  • i32:32位有符号整数
  • i64:64位有符号整数
  • double:64位浮点数
  • string:字符串类型
容器类型

集合黄总的元素可以是除了service之外的任何类型

  • list:一系列由T类型的数据组成的有序列表,元素可以重复
  • set:一系列由T类型的数据组成的无序集合,元素不可重复
  • map:一个字典结构,key为K类型,value为V类型

结构体

结构体对应Java中的对象

struct LoginRequest {  
    1: string name;
    2: string password="thrifty"; // 可以设置参数默认值
}  

枚举

enum Sex {
    RED,
    BLUE
}

异常

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

服务

RPC调用的服务,服务中的方法就是RPC调用的方法

service HelloWordService {
	// 传入参数可以是基本数据类型,或者是自定义的对象struct
	// 返回值可以是基本数据类型,或者是自定义的对象struct
    // 可以抛出异常
     LoginResponse login(1: LoginRequest request) throws (1:RequestException qe); 
 }

类型定义

typedef i32 Integer
typedef i64 Long

全局常量

thrift的常量是全局常量,即thrift会生成 一个常量类,包含所有常量

const i32 MAX_RETRIES_TIME = 10;
// 生成结果
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked", "unused"})
public class Constants {
  public static final int MAX_RETRIES_TIME = 10;
}

命名空间

命名空间即java中的包

namespace <语言> <包的位置>
namespace java com.shine.thrift 

文件包含

文件包含,即导入另外一个thrift文件,在当前thrift文件中可以使用另外一个文件中的变量

include "global.thrift"

注释

thrift支持多种语言的注释

#
//
/* */

可选与必选

thrift提供两个关键字required,optional,表示序列化传输的时候是否进行未设置值字段的序列化。

  • required:不管有没有设置字段,序列化的时候都会将字段序列化。(如果没有设置字段,会序列化字段的初值)
  • optional:如果没有设置字段,序列化的时候不会将字段序列化,对方访问该字段时,会获得字段的初值。
    • 可以缩短报文的长度,提高效率
    • 可以使用isSetXXX()的方法判断对方是否设置了字段
struct People {
    1: required string name;
    2: optional i32 age;
}

示例

  1. windows端直接下载thrift的exe文件

  2. 编写login.thrift文件

    • thrift文件是IDL(接口定义语言)文件,通过thrift可以自动生成不同编程语言的代码
namespace java com.shine.thrift  // 包名

// 消息对象
struct LoginRequest {  
    1: string name;
    2: string password="thrifty";
}  

struct LoginResponse{
    1: string response;
}

// 异常
exception RequestException {  
    1: required i32 code;  
    2: optional string reason;  
}  
  
// 服务  
service Service {  
    LoginResponse login(1: LoginRequest request) throws (1:RequestException qe); // 可能抛出异常。  
    double query(1: i32 request) throws (1:RequestException qe); // 可能抛出异常。 
}
  1. 使用thrift编译生成java代码
thrift -gen java test.thrift
  1. 将java代码放入工程目录中
  2. 使用maven导入thrift相关包

    
        org.apache.thrift
        libthrift
    0.13.0

  1. 实现业务代码
package thrift.impl;

import org.apache.thrift.TException;
import thrift.*;

public class ServiceImpl implements Service.Iface {
    @Override
    public LoginResponse login(LoginRequest request) throws RequestException, TException {
        String name = request.getName();
        String password = request.getPassword();
        if (name.equals("admin") && password.equals("1234")) {
            return new LoginResponse("成功登陆");
        }
        return new LoginResponse("默认账号:admin, 默认密码:1234");
    }

    @Override
    public double query(int number) throws RequestException, TException {
        return number * 1.1;
    }
}
  1. 编写服务端代码
package thrift.main;

import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TTransportException;
import thrift.Service;
import thrift.impl.ServiceImpl;

import java.io.IOException;
import java.net.ServerSocket;

/**
 * 服务端
 */
public class ServerMain {
    public static void main(String[] args) throws IOException, TTransportException {
        // socket编程
        ServerSocket socket = new ServerSocket(8888);

        // thrift Server 传输层
        TServerSocket serverTransport = new TServerSocket(socket);

        // Processor封装了从输入数据流中读数据和向数据流中写数据的操作
        Service.Processor processor = new Service.Processor(new ServiceImpl());

        // 服务器参数 包含传输socket 业务处理器
        TServer.Args tServerArgs = new TServer.Args(serverTransport);
        tServerArgs.processor(processor);

        // 服务器
        TServer server = new TSimpleServer(tServerArgs);
        System.out.println("Starting the simple server...");
        server.serve(); // 开始运行
    }
}
  1. 编写客户端代码
package thrift.main;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import thrift.LoginRequest;
import thrift.LoginResponse;
import thrift.Service;

public class ClientMain {
    public static void main(String[] args) {
        TTransport transport = null;
        try {
            transport = new TSocket("localhost", 8888);

            TProtocol protocol = new TBinaryProtocol(transport);

            // 一个服务对应一个客户端
            Service.Client client = new Service.Client(protocol);
            transport.open();

            // 访问login方法
            LoginRequest request = new LoginRequest()
                    .setName("shine")
                    .setPassword("1234");
            LoginResponse loginResponse = client.login(request);// 传输请求
            System.out.println(loginResponse.toString());

            // 访问Query方法
            System.out.println(client.query(11));
        } catch (TException e) {
            e.printStackTrace();
        } finally {
            assert transport != null;
            transport.close();
        }
    }
}

你可能感兴趣的:(thrift,rpc)