PRC:远程服务调用,也是一种网络协议,使用TCP连接实现,类似HTTP。
Thrift是一种RPC框架,开发人员通过编写IDL定义两个服务之间的接口,然后通过Thrift自动生成代码(包括网络服务端和客户端,通信对象),即开发人员只需要编写业务相关代码,无需关心数据的通信的过程。
Thrift的底层数据序列化使用的是Google的Protobuf。
Thrift的客户端和服务端需要配置相关参数:
基本数据类型
thrift不支持无符号类型,因为很多编程语言不存在无符号类型
集合黄总的元素可以是除了service之外的任何类型
结构体
结构体对应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,表示序列化传输的时候是否进行未设置值字段的序列化。
isSetXXX()
的方法判断对方是否设置了字段struct People {
1: required string name;
2: optional i32 age;
}
windows端直接下载thrift的exe文件
编写login.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); // 可能抛出异常。
}
thrift -gen java test.thrift
org.apache.thrift
libthrift
0.13.0
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;
}
}
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(); // 开始运行
}
}
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();
}
}
}