之前详细说明了一个服务端的示例 Thrift—构建一个RPC实例(一)
今天来看一下客户端的示例流程:
1. 构建一个python客户端
在hello服务器所在的目录中编写一个Python客户端代码,以查看Apache Thrift RPC的客户端。我们的客户只需调用单独服务方法,显示结果并退出即可。示例如下:
import sys sys.path.append("gen-py") from thrift.transport import TSocket from thrift.protocol import TBinaryProtocol #A from hello import HelloSvc socket = TSocket.TSocket("localhost", 8585) socket.open() #B protocol = TBinaryProtocol.TBinaryProtocol(socket) #C client = HelloSvc.Client(protocol) #D msg = client.hello_func() #E print("[Client] received: %s" % msg)
步骤释义如下:
#A 二进制协议是几种Apache Thrift序列化协议之一 #B open命令将客户端套接字连接到本地主机上端口8585上的服务器 #C 二进制协议将读写连接的套接字 #D 编译器为HelloSvc生成的客户端存根将通过二进制协议发送其所有请求 #E Client对象使调用远程函数像调用本地函数一样容易
详细过程分析:
如上图代码所示,我们再次将gen-py目录添加到Python路径以支持hello包导入。我们的客户需要Thrift Python库中的两个类。第一个是thrift.transport包中的TSocket模块中的TSocket类。
用Apache Thrift术语来说,TSocket是一种传输类型,传输是将字节移动到目标的对象。我们准备使用要连接的主机和端口来初始化TSocket,并在准备与服务器建立连接时调用套接字的open()方法。
我们还需要thrift.protocol软件包中TBinaryProtocol模块中的TBinaryProtocol类。Thrift序列化协议将Thrift IDL类型转换为字节流。协议依赖于传输来传输字节,但与所提供的特定传输类型无关。这允许协议通过简单地切换传输就可以序列化到内存,磁盘或网络设备。
默认情况下,Apache Thrift服务器使用二进制协议。客户端和服务器必须使用相同的协议/传输堆栈才能成功通信。Apache Thrift生成的客户端代码未提供默认协议,因此我们必须显式创建一个TBinaryProtocol对象以在此处使用。
IDL编译器生成的HelloSvc.py模块包含一个Client类,该类充当远程服务的代理。在构造了客户端对象并为其提供协议对象之后,我们可以通过客户端代理对服务进行调用。在Client对象上调用hello_func()方法将使用二进制协议序列化我们的调用请求,并将其通过套接字传输到服务器。
服务器使用处理程序执行我们的请求,并返回“ Hello Thrift”字符串。客户端套接字接收字节并将其传递给二进制协议,该协议对该字符串反序列化,返回一个字符串,然后显示该字符串。
运行结果:
尽管比运行的hello world程序要有多得多的工作,但几行IDL和Python使我们能够使用有效的客户端和服务器来创建与语言无关,与操作系统无关和与平台无关的服务API。
2. 构建一个Java客户端
最后,让我们组装一个Java客户端。我们的第一步是为我们的服务生成Java存根。
#A -gen开关java参数使编译器发出指定IDL的Java代码。 #B 编译器生成单个源文件,其中包含支持IDL所需的所有代码用Java构造。
与IDL一起运行时,IDL编译器Java代码生成器仅输出一个文件。HelloSvc.java文件包含Java HelloSvc类。 客户端和服务器存根类嵌套在该类中。
import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.TException; public class HelloClient { public static void main(String[] args) throws TException { TSocket socket = new TSocket("localhost", 8585); socket.open(); TBinaryProtocol protocol = new TBinaryProtocol(socket); HelloSvc.Client client = new HelloSvc.Client(protocol); String str = client.hello_func(); System.out.println("[Client] received: " + str); } }
运行情况:
#A 编译Java源代码,将Apache Thrift和SLF4J jar添加到类路径 #B HelloSvc类文件保存在gen-java目录中 #C HelloClient类文件在当前目录中创建 #D 将gen-java和当前目录添加到类路径以运行客户端
Java客户端和python客户端整体的实现思路类似,就不再重复,可以参考python客户端的实现思路来理解Java客户端的实现过程。
3. 总结
通过前面的操作和介绍,我们便实现了由一个python服务端处理两个不同语言客户端的demo。这便是thrift分布式应用的基础。之后再继续深入介绍。欢迎关注交流~