Apache Thrift - 跨语言兼容性
Thrift 中的跨语言兼容性
Apache Thrift 旨在实现跨语言兼容,从而实现用不同编程语言编写的服务之间的无缝通信。
Apache Thrift 提供了一个框架,用于以独立于语言的方式定义数据类型和服务接口。然后,它会生成多种编程语言的代码,从而允许用不同语言编写的服务进行有效通信。
此功能对于构建分布式系统非常重要,因为分布式系统中的不同组件可能以不同的语言实现。
定义 Thrift IDL
Thrift IDL 允许您以独立于语言的方式定义数据类型和服务方法。然后,此定义用于生成各种编程语言的代码。
示例
在以下示例中,定义了"User"结构和"UserService"服务。 Thrift IDL抽象了这些定义,以便可以用不同的语言实现它们 −
namespace py example struct User { 1: string username, 2: i32 age } service UserService { User getUser(1: string username), void updateUser(1: User user) }
为不同语言生成代码
Thrift 工具可以从 IDL 文件生成各种语言的源代码。此过程可确保数据结构和服务方法在不同语言之间保持一致。以下是生成代码的步骤 −
- 定义您的 IDL 文件: 使用您的数据结构和服务定义创建一个".thrift"文件。
- 为目标语言生成代码: 使用 Thrift 编译器生成所需语言的源代码。
- 实现和使用生成的代码: 在生成的类中实现服务逻辑并在您的应用程序中使用它们。
生成 Python 代码
要生成 Python 代码,请使用带有 --gen 选项的 Thrift 编译器。此命令根据 IDL 定义创建一个包含类和方法的 Python 模块 −
thrift --gen py service.thrift
生成 Java 代码
同样,您可以使用 --gen 选项生成 Java 代码。此命令根据 IDL 定义创建一个包含类和方法的 Java 包 −
thrift --gen java service.thrift
使用不同的语言实现服务
使用生成的代码,您现在可以用不同的语言实现服务。我们将介绍如何在 Python 和 Java 中实现 ExampleService。
Python 实现
以下是在 Python 中实现"ExampleService"的分步说明 −
导入必要的模块:
- TServer:用于设置服务器。
- TSocket、TTransport:用于处理网络通信。
- TBinaryProtocol:用于序列化数据。
- ExampleService:生成的服务接口。
定义服务处理程序:
- 创建一个实现"ExampleService.Iface"接口的类"ExampleServiceHandler"。
- 实现"sayHello"方法以打印问候消息。
设置服务器:
- 为处理程序和处理器。
- 使用端口 9090 上的"TSocket.TServerSocket"设置传输。
- 使用缓冲传输和二进制协议进行通信。
- 使用传输、协议和处理程序初始化服务器。
启动服务器:
- 打印一条指示服务器正在启动的消息。
- 调用"server.serve()"开始监听客户端请求。
from thrift.server import TServer from thrift.transport import TSocket, TTransport from thrift.protocol import TBinaryProtocol from example import ExampleService class ExampleServiceHandler(ExampleService.Iface): def sayHello(self, person): print(f"Hello {person.name}, age {person.age}") handler = ExampleServiceHandler() processor = ExampleService.Processor(handler) transport = TSocket.TServerSocket(port=9090) tfactory = TTransport.TBufferedTransportFactory() pfactory = TBinaryProtocol.TBinaryProtocolFactory() server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) print("Starting the Python server...") server.serve()
在此示例中,我们用 Python 设置了一个简单的 Thrift 服务器,该服务器监听端口 9090。"ExampleServiceHandler"通过实现"sayHello"方法来处理传入请求。
Java 实现
同样,我们在这里用 Java 设置了一个简单的 Thrift 服务器,该服务器监听端口 9090。"ExampleServiceHandler"通过实现"sayHello"方法来处理传入请求 −
import example.ExampleService; import example.Person; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.server.TServer; import org.apache.thrift.server.TSimpleServer; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TServerTransport; public class ExampleServiceHandler implements ExampleService.Iface { @Override public void sayHello(Person person) throws TException { System.out.println("Hello " + person.getName() + ", age " + person.getAge()); } public static void main(String[] args) { try { ExampleServiceHandler handler = new ExampleServiceHandler(); ExampleService.Processor<ExampleServiceHandler> processor = new ExampleService.Processor<>(handler); TServerTransport serverTransport = new TServerSocket(9090); TBinaryProtocol.Factory protocolFactory = new TBinaryProtocol.Factory(); TSimpleServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor).protocolFactory(protocolFactory)); System.out.println("Starting the Java server..."); server.serve(); } catch (Exception e) { e.printStackTrace(); } } }
跨语言通信
使用不同语言实现的服务,您现在可以测试跨语言通信。这意味着您可以让用一种语言编写的客户端与用另一种语言编写的服务器进行通信。 工作原理如下 −
- Python 客户端调用 Java 服务:编写一个与 Java 服务器通信的 Python 客户端。
- Java 客户端调用 Python 服务:编写一个与 Python 服务器通信的 Java 客户端。
示例:Python 客户端
以下是连接到 Java 服务器上运行的 Thrift 服务的 Python 客户端 −
from thrift.transport import TSocket, TTransport from thrift.protocol import TBinaryProtocol from example import ExampleService transport = TSocket.TSocket('localhost', 9090) transport = TTransport.TBufferedTransport(transport) protocol = TBinaryProtocol.TBinaryProtocol(transport) client = ExampleService.Client(protocol) transport.open() person = ExampleService.Person(name="Alice", age=30) client.sayHello(person) transport.close()
示例:Java 客户端
同样,我们编写一个 Java 客户端,与在 Python 服务器上运行的 Thrift 服务进行通信 −
import example.ExampleService; import example.Person; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; public class ExampleClient { public static void main(String[] args) { try { TTransport transport = new TSocket("localhost", 9090); TBinaryProtocol protocol = new TBinaryProtocol(transport); ExampleService.Client client = new ExampleService.Client(protocol); transport.open(); Person person = new Person("Bob", 25); client.sayHello(person); transport.close(); } catch (Exception e) { e.printStackTrace(); } } }