热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

RPC框架之Thrift简单使用

前言Thrift是一个可以跨平台,跨语言的RPC(远程过程调用)框架,通过IDL(接口描述语言)来定义数据类型和接口,相当于Protobuf和gRPC的结合体。Thrift最开始由

前言

Thrift是一个可以跨平台,跨语言的RPC(远程过程调用)框架,通过IDL(接口描述语言)来定义数据类型和接口,相当于Protobuf和gRPC的结合体。Thrift最开始由Facebook开源,后来贡献给了Apache。


下载编译器

官网,这里我们下载windows版本的编译器thrift-0.16.0.exe。


定义thrift文件

namespace java com.imooc.sourcecode.java.google.thrift.test1
typedef i16 short
typedef i32 int
typedef i64 long
typedef bool boolean
typedef string String
struct Person {
1: optional String username
2: optional int age
3: optional boolean married
}
exception DataException {
1: optional String message
2: optional String callStack
3: optional String date
}
service PersonService {
Person getPersonByUsername(1: required String username) throws (1: DataException dataException),
void savePerson(1: required Person person) throws (1: DataException dataException),
}

namespace 定义包名,类似ProtoBuf的java_package。

typedef 定义类型的别名。

optional 表示当前字段可选,非必填。

1: optional String message 每个字段需要有一个唯一的号码,必须大于0。

exception 定义异常,可以看做Java中的异常。

service 定义服务,可以看做Java中的接口。

struct 可以看做一个Java类,类似ProtoBuf的message。


Java处理


添加maven依赖


org.apache.thrift
libthrift
0.16.0


根据thrift文件创建Java数据类型和接口代码

thrift -out $DST_DIR --gen java $SRC_DIR/data.proto

-out表示生成代码的路径,java表示生成Java语言的代码,实际命令为

.\thrift-0.16.0.exe -out D:\java\code_resp\github_resp\source_code\src\main\java --gen java D:\java\code_resp\github_resp\source_code\src\main\java\com\imooc\sourcecode\java\google\thrift\test1\data.thrift

-out值不要包含具体的包路径,thrift文件中已经配置了。


序列化和反序列化

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.thrift.TDeserializer;
import org.apache.thrift.TSerializer;
import org.apache.thrift.protocol.TCompactProtocol.Factory;
public class TestSerialize {
public static void main(String[] args) throws Exception {
testSerialize();
testDeserialize();
}
private static void testSerialize() throws Exception {
Person person = new Person();
person.setUsername("李四");
person.setAge(23);
person.setMarried(true);
TSerializer serializer = new TSerializer(new Factory());
byte[] bytes = serializer.serialize(person);
new ByteArrayInputStream(bytes)
.transferTo(new FileOutputStream("D:/testjar/thrift_java_serialize_person"));
}
private static void testDeserialize() throws Exception {
TDeserializer deserializer = new TDeserializer(new Factory());
Person person = new Person();
ByteArrayOutputStream output = new ByteArrayOutputStream();
new FileInputStream("D:/testjar/thrift_java_serialize_person").transferTo(output);
deserializer.deserialize(person, output.toByteArray());
System.out.println(person);
}
}

序列化和反序列化要使用相同的TProtocolFactory类型。


服务器端代码

import com.imooc.sourcecode.java.google.thrift.test1.PersonService.Processor;
import org.apache.thrift.TException;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.THsHaServer.Args;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.layered.TFramedTransport;
public class MyServer {
public static void main(String[] args) throws TTransportException {
TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8883);
THsHaServer.Args serverArgs = new Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4);
Processor

processor = new Processor<>(new PersonServiceImpl());
serverArgs.protocolFactory(new TCompactProtocol.Factory());
serverArgs.transportFactory(new TFramedTransport.Factory());
serverArgs.processorFactory(new TProcessorFactory(processor));
System.out.println("Server start");
THsHaServer server = new THsHaServer(serverArgs);
server.serve();
}
public static class PersonServiceImpl implements PersonService.Iface {
@Override
public Person getPersonByUsername(String username) throws DataException, TException {
System.out.println("param: " + username);
Person person = new Person();
person.setUsername(username);
person.setAge(23);
person.setMarried(true);
return person;
}
@Override
public void savePerson(Person person) throws DataException, TException {
System.out.println("param: " + person);
System.out.println(person);
}
}
}

定义PersonServiceImpl实现类,来处理客户端请求。


客户端代码

import com.imooc.sourcecode.java.google.thrift.test1.PersonService.Client;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.layered.TFramedTransport;
public class MyClient {
public static void main(String[] args) throws TException {
TFramedTransport transport = new TFramedTransport(new TSocket("localhost", 8883));
TCompactProtocol protocol = new TCompactProtocol(transport);
Client client = new Client(protocol);
transport.open();
Person queryPerson = client.getPersonByUsername("张三");
System.out.println(queryPerson);
Person savePerson = new Person();
savePerson.setUsername("李四");
savePerson.setAge(21);
savePerson.setMarried(false);
client.savePerson(savePerson);
transport.close();
}
}

可以看到,客户端调用服务器端接口就像调用本地方法一样简单。


Python处理


安装依赖

pip install thrift

PyCharm中可以这样安装



根据thrift文件创建Python数据类型和接口代码

thrift -out $DST_DIR --gen py $SRC_DIR/data.proto

-out表示生成代码的路径,py表示生成Python语言的代码,实际命令为

.\thrift-0.16.0.exe -out D:\java\code_resp\PycharmProjects\test_protobuf\testthrift --gen py D:\java\code_resp\PycharmProjects\test_protobuf\testthrift\data.thrift

代码结构如下,data目录为生成的目录,包含数据类型和服务接口。



序列化和反序列化

from data import ttypes
from thrift import TSerialization
from thrift.protocol import TCompactProtocol
def test_serialize():
p = ttypes.Person()
p.username = "小明"
p.age = 27
p.married = False
bytes = TSerialization.serialize(p,TCompactProtocol.TCompactProtocolFactory())
with open("D:/testjar/thrift_python_serialize_person", "wb") as f:
f.write(bytes)
return
def test_deserialize():
with open("D:/testjar/thrift_python_serialize_person", "rb") as rf:
bytes_read = rf.read()
p = ttypes.Person()
TSerialization.deserialize(p, bytes_read, TCompactProtocol.TCompactProtocolFactory())
print(p)
return
if __name__ == '__main__':
test_deserialize()
pass

服务器端代码

from PersonServiceImpl import PersonServiceImpl
from data import PersonService
from thrift.protocol import TCompactProtocol
from thrift.server import TServer
from thrift.transport import TSocket
from thrift.transport import TTransport
def test():
# Make socket
persOnServiceImpl= PersonServiceImpl()
processor = PersonService.Processor(personServiceImpl)
serverSocket = TSocket.TServerSocket(port=8883)
transportFactory = TTransport.TFramedTransportFactory()
protocolFactory = TCompactProtocol.TCompactProtocolFactory()
server = TServer.TThreadPoolServer(processor, serverSocket, transportFactory, protocolFactory)
server.serve()
pass
if __name__ == '__main__':
test()
pass

客户端代码

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TCompactProtocol
from data import PersonService
def test():
# Make socket
transport = TSocket.TSocket('localhost', 8883)
# Buffering is critical. Raw sockets are very slow
transport = TTransport.TFramedTransport(transport)
# Wrap in a protocol
protocol = TCompactProtocol.TCompactProtocol(transport)
# Create a client to use the protocol encoder
client = PersonService.Client(protocol)
# Connect!
transport.open()
p = client.getPersonByUsername("李四")
print(p)
pass
if __name__ == '__main__':
test()
pass

总结

更多Thrift相关用法,请查看官方文档。


参考

Apache Thrift

如何给老婆解释什么是RPC

Thrift 简易入门与实战

【Thrift】Thrift的那些服务模型

Thrift(一):快速入门



推荐阅读
  • Linux服务器密码过期策略、登录次数限制、私钥登录等配置方法
    本文介绍了在Linux服务器上进行密码过期策略、登录次数限制、私钥登录等配置的方法。通过修改配置文件中的参数,可以设置密码的有效期、最小间隔时间、最小长度,并在密码过期前进行提示。同时还介绍了如何进行公钥登录和修改默认账户用户名的操作。详细步骤和注意事项可参考本文内容。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
author-avatar
我是阿冫轶
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有