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 编译器。此命令将创建一个 Python 模块,其中包含基于 IDL 定义的类和方法 -

thrift --gen py service.thrift

生成 Java 代码

同样,您可以使用--gen选项生成 Java 代码。此命令将创建一个 Java 包,其中包含基于 IDL 定义的类和方法 -

thrift --gen java service.thrift

在不同的语言中实现服务

使用生成的代码,您现在可以在不同的语言中实现服务。我们将逐步介绍如何在 Python 和 Java 中实现ExampleService

Python 实现

以下是使用 Python 实现“ExampleService”的分步说明 -

导入必要的模块

  • TServer:用于设置服务器。
  • TSocket, TTransport:用于处理网络通信。
  • TBinaryProtocol:用于数据序列化。
  • ExampleService:生成的 service 接口。

定义服务处理程序

  • 创建一个类“ExampleServiceHandler”,该类实现“ExampleService.Iface”接口。
  • 实现“sayHello”方法以打印问候消息。

设置服务器

  • 为处理程序和处理器创建实例。
  • 使用“TSocket.TServerSocket”在端口 9090 上设置传输。
  • 使用缓冲传输和二进制协议进行通信。
  • 使用传输、协议和处理程序初始化服务器。

启动服务器

  • 打印一条消息,指示服务器正在启动。
  • 调用“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 客户端

以下是一个 Python 客户端,它连接到在 Java 服务器上运行的 Thrift 服务 -

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();
      }
   }
}
广告