RPC远程协议之Thrift入门
在上一篇文章《RPC远程协议之原理分析》中,我介绍了RPC的工作原理及欲实现RPC框架功能应该做哪些事情,因为要做的事情太多,完全由开发人员研发实现,不是很现实,所以市面上出现了诸多RPC快捷框架,目前主流的有Facebook的Thrift、谷歌的gRPC,以及Dubbo,但就性能角度考虑,Thrift相对好些,并且是跨语言的,所以这里先以Thrift的介绍开始。对于Facebook,我们现阶段只需要知道它是一个高性能的、支持跨语言平台的远程服务调用框架,并且作为很多企业实现分布式系统架构的服务调用实现的基础,以及该怎样去使用它来快速搭建服务调用功能。
l 数据类型
l 准备条件
l 例子验证
一、数据类型
我们知道,Thrift是跨语言的RPC开源框架,那么它应该有自己的消息数据类型,而不是其它任何一门语言的数据类型,否则就不能支持其它语言,那么就看下它支持的几种定制类型,具体如下:
1、基础类型
为什么Thrift的数据类型都是有符号?因为很多语言都不支持无符号的数据类型,所以Thrift为了满足大部分语言特征,所以没必要加入无符号的数据类型。
2、特殊类型
binary,未经编码的字节流类型,主要针对字符串类型的字节流化,提供与java语言更好的互操作性。
3、结构类型
struct,定义普通的OOP类型,但不支持继承特性。
4、容器类型
list,一种有序的列表集合类型,如:对应java的List
set,一种无序的唯一值集合类型,如:对应java的Set
map,一种离散的键值对集合类型,如:对应java的Map
5、服务类型
service,定义对外提供的服务,如:供客户端使用的服务接口。
6、异常类型
exception,一种Thrift本身定制异常,与其它语言无缝结合的异常类型。
在下面的例子会演示基础类型、容器类型、结构类型,以及服务类型的使用,供读者参考。
二、准备条件
1、C/S双端
这里的C/S双端指的是客户端和服务端,实际使用时,客户端与服务端进程往往不在同一个节点中,比如:分布式环境,所以客户端和服务端一般是分离的,客户端需要引用由服务端所生成的服务代码,来完成远程调用。但在这里,我们将客户端与服务端代码均放在同一个项目中,所以客户端不需要额外引入即可使用调用,当然两端也分别在不同的进程中运行通信。
2、编译环境
下载地址:
http://thrift.apache.org/download
如果是mac osx则可以使用brew install thrift自动安装;
如果是linux系统,则可使用apt-get install thrift-compiler安装均可。
安装后,可以使用thrift –version查看版本,如果正常显示,则安装完成。
3、依赖添加
我这里采用maven来加载和管理thrift依赖包,并且使用最新版本0.11.0,具体配置如下:
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.11.0</version>
</dependency>
三、例子验证
在这里,我就不以典型的helloworld为例,而是以根据用户ID获取用户基本信息和该用户的订单为例,详细介绍下Thrift的几种数据类的使用方法。
1、编写IDL文件(user.thrift)
# defaine the namespace
namespace java com.cwteam
# define the struct
struct User {
1:i32 uid,
2:string name,
3:i16 sex,
4:list<Order> orderList
}
struct Order {
1:string oid,
2:string oname,
3:double price,
4:i32 number,
5:string createAt
}
# define the service
service UserService {
# Get the user's order list by uid
User getUserOrders(1:i32 uid)
# Other operation follow here
# ...
}
2、生成语言文件(UserService.java)
使用Thrift提供的编辑工具生成,切换到user.thrift文件所在目录,我的结构如下:

也就是user.thrift存放在main下,切换到main下,使用thrift命令编译生成语言文件,如下所示:
#thrift--gen java user.thrift
生成后的stub文件如下样子:
3、业务接口实现(UserHandler.java)
/**
* 用户服务接口,由服务端负责实现
*/
public class UserHandler implements UserService.Iface {
public User getUserOrders(int uid) throws TException {
User user = new User(); // 模拟实现用户及订单查询
user.setUid(uid);
user.setName("David Lang");
user.setSex((short)1);
List<Order> orders = new ArrayList<Order>();
Order order = new Order();
order.setOid("NO1112321");
order.setOname("《Thrift进阶与提高》");
order.setPrice(99.99);
order.setNumber(1);
order.setCreateAt("2017-04-04");
orders.add(order);
Order order2 = new Order();
order2.setOid("NO1112322");
order2.setOname("《RPC进阶与提高》");
order2.setPrice(88.88);
order2.setNumber(2);
order2.setCreateAt("2017-04-05");
orders.add(order2);
user.setOrderList(orders);
return user;
}
}
4、服务端实例(UserServer.java)
/**
* 将业务处理逻辑UserHandler作为具体的业务
* 处理器,传递给Thrift服务器,执行处理逻辑.
*/
public class UserServer {
private static final int port = 9081;
private static UserHandler handler;
private static UserService.Processor processor;
/**
* 启动服务端
* processor为控制调用逻辑
*/
public static void start(UserService.Processor processor) {
try {
// 阻塞方式,基于ServerSocket
TServerTransport serverTransport = new TServerSocket(port);
TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor));
System.out.println("Starting simple server ...");
// 启动服务
server.serve();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
handler = new UserHandler();
processor = new UserService.Processor(handler);
start(processor);
}
}
5、客户端实例(UserClient.java)
/**
* 远程调用服务接口,获取用户信息及订单列表
*/
public class UserClient {
private static final int port = 9081;
private static final String addr = "localhost";
private static UserService.Client client;
private static TTransport transport;
/**
* 创建TTransport
*/
private static TTransport createTTransport() {
TTransport transport = new TSocket(addr,port);
return transport;
}
/**
* 开启TTransport
*/
private static void openTTransport(TTransport transport) throws TTransportException {
if(null == transport) {
return;
}
transport.open();
}
/**
* 关闭TTransport
*/
private static void closeTTransport(TTransport transport) {
if(null == transport) {
return;
}
transport.close();
}
/**
* 创建客户端实体
*/
private static UserService.Client createClient(TTransport transport) {
if(null == transport) {
return null;
}
// 编码协议指定(这里是二进制方式传递)
TProtocol protocol = new TBinaryProtocol(transport);
if(null == protocol) {
return null;
}
// 设定编码协议
UserService.Client client = new UserService.Client(protocol);
return client;
}
public static void main(String[] args) {
try {
transport = createTTransport();
openTTransport(transport);
client = createClient(transport);
// 调用远程服务
if(null == client) {
System.out.println("客户端生成失败,不能调用服务 ...");
return;
}
User user = client.getUserOrders(10000021);
System.out.println(user);
} catch(TException e1) {
e1.printStackTrace();
}
}
}
6、例子运行结果
启动服务端:
启动客户端:
好了,Thrift入门就介绍到这里,读者也会发现这里所实现的服务调用方式为阻塞的,并且是非多线程的。
原文:https://blog.csdn.net/why_2012_gogo/article/details/79432630
RPC远程协议之Thrift入门的更多相关文章
- RPC远程协议之原理分析
在近几年工作中发现,功能服务化或微服务化越来越流行,逐渐成为实现中大型分布式系统架构的主要方式,而在分布式系统中的不同节点应用间的通信中,RPC远程协议扮演关键作用.实际上,在日常工作中,我们也多多少 ...
- Thrift入门初探--thrift安装及java入门实例
什么是thrift? 简单来说,是Facebook公布的一款开源跨语言的RPC框架. 那么问题来了. 什么是RPC框架? RPC全称为Remote Procedure Call,意为远程过程调用. 假 ...
- Thrift入门及Java实例演示<转载备用>
Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...
- 从0到1:全面理解RPC远程调用
上一篇关于 WSGI 的硬核长文,不知道有多少同学,能够从头看到尾的,不管你们有没有看得很过瘾,反正我是写得很爽,总有一种将一样知识吃透了的错觉. 今天我又给自己挖坑了,打算将 rpc 远程调用的知识 ...
- Thrift入门初探(2)--thrift基础知识详解
昨天总结了thrift的安装和入门实例,Thrift入门初探--thrift安装及java入门实例,今天开始总结一下thrift的相关基础知识. Thrift使用一种中间语言IDL,来进行接口的定义, ...
- Java自带RPC实现,RMI框架入门
Java自带RPC实现,RMI框架入门 首先RMI(Remote Method Invocation)是Java特有的一种RPC实现,它能够使部署在不同主机上的Java对象进行通信与方法调用,它是一种 ...
- 2016windows(10) wamp 最简单30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world
2016最简单windows(10) wamp 30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world thrift是什么 最简单解释 thrift是用来帮助各个编程语 ...
- Thrift入门 (一)
Install Go to thrift page download thrift. 1 2 3 4 brew install boost ./configure --without-python s ...
- 測试JSON RPC远程调用(JSONclient)
#include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...
随机推荐
- Keil MDK5 安装教程(附安装包百度云)
关注微信公众号"龙行单片机",后台回复"安装包"获取最新安装包百度云链接. 1.MDK5.11a 安装 双击 mdk511a.exe,进行安装.这里我们将其安装 ...
- 十四、.net core(.NET 6)搭建ElasticSearch(ES)系列之给ElasticSearch添加SQL插件和浏览器插件
给ES添加SQL插件的方法: 下载SQL插件地址:https://github.com/NLPchina/elasticsearch-sql 当前最新的是7.12版本,我的ES是7.13版本,暂且将 ...
- 三色标记法与读写屏障, G1工作过程
https://www.jianshu.com/p/12544c0ad5c1 https://www.cnblogs.com/GrimMjx/p/12234564.html 自我总结和记忆: 为了解决 ...
- halcon——缺陷检测常用方法总结(模板匹配(定位)+差分)
引言 机器视觉中缺陷检测分为一下几种: blob分析+特征 模板匹配(定位)+差分 光度立体:halcon--缺陷检测常用方法总结(光度立体) - 唯有自己强大 - 博客园 (cnblogs.com) ...
- 狂神说redis笔记(二)
四.三种特殊数据类型 Geospatial(地理位置) 使用经纬度定位地理坐标并用一个有序集合zset保存,所以zset命令也可以使用 geoadd key longitud(经度) latitude ...
- 【NX二次开发】Block UI 目录
Block UI 目录 基本 标签/位图 切换开关 枚举 字符串 多行字符串 操作按钮 列表框 分割线 对象颜色选择器 RGB颜色选择器 绘图区 图层 ...
- 每天凌晨 2:00 将 mysql 数据库 testdb ,备份到文件中。
步骤:1, 首先编写一个 脚本 backupdb.sh#!/bin/bash #备份路径 BACKUP=/data/backup/sql/dy #当前时间 DATETIME=$(date +%Y-%m ...
- Spring Boot WebFlux-03——WebFlux 整合 MongoDB
第03课:WebFlux 整合 MongoDB 前言 上一课的内容讲解了用 Map 数据结构内存式存储了数据,这样数据就不会持久化,本文我们用 MongoDB 来实现 WebFlux 对数据源的操作. ...
- 代码生成器:IDEA 强大的 Live Templates
前言 Java 开发过程经常需要编写有固定格式的代码,例如说声明一个私有变量,logger或者bean等等.对于这种小范围的代码生成,我们可以利用 IDEA 提供的 Live Templates功能. ...
- 【题解】Luogu p3478 [POI2008]STA-Station 动态规划
题目描述 给出一个$N$个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大 输入输出格式 输入格式 第一行一个数$n$,表示树上共有$n$个点接下来$n-1$行,表示$n-1$条边;每行 ...