器→工具, 开源项目

跨语言服务的框架Apache Thrift

钱魏Way · · 271 次浏览
!文章内容如有错误或排版问题,请提交反馈,非常感谢!

Apache Thrift简介

Apache Thrift是一个用于构建可扩展且跨语言服务的框架。最初由Facebook开发,后来成为Apache软件基金会的一个项目。Thrift提供了一种高效的接口定义语言(IDL)和数据序列化机制,使得在不同编程语言之间进行通信变得简单和高效。

核心特性

  • 跨语言支持:Thrift支持多种编程语言,包括但不限于C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Node.js等。这使得Thrift非常适合构建需要跨越多种技术栈的分布式系统。
  • 接口定义语言(IDL):Thrift提供了一种强类型的接口定义语言,用于定义数据类型和服务接口。开发者可以通过Thrift IDL定义服务接口,然后生成不同语言的代码。
  • 高效的序列化机制:Thrift提供了多种序列化协议(如二进制协议、压缩协议和JSON协议),可以根据需求选择合适的协议来优化性能和数据传输。
  • 灵活的传输层:支持多种传输层,包括阻塞和非阻塞的Socket传输、HTTP传输等。这使得Thrift可以适应不同的网络环境和应用需求。
  • 支持同步和异步通信:Thrift支持同步和异步的RPC调用,允许开发者根据应用的需求选择合适的通信模式。
  • 服务扩展性:Thrift允许服务接口的版本化和扩展,使得服务可以在不破坏现有客户端的情况下演变和扩展。

Thrift的优点

  • 高效的序列化:支持紧凑的二进制协议,数据传输效率高。
  • 跨语言支持:使用IDL定义接口,支持多语言生成代码。
  • 丰富的功能:内置数据序列化和RPC支持,开发分布式服务更简单。
  • 灵活的传输和协议层:可根据需求选择不同的传输和协议。

应用场景

  • 分布式系统:Thrift非常适合用于构建分布式系统和微服务架构,特别是在需要不同语言之间通信的场景。
  • 跨语言服务通信:在一个多语言的技术栈中,Thrift可以用于实现不同语言的组件之间的高效通信。
  • 高性能RPC:Thrift的高效序列化和传输协议使其成为实现高性能远程过程调用(RPC)的理想选择。
  • 多平台应用:对于需要在不同平台(如移动设备、桌面应用和服务器)上运行的应用,Thrift提供了一种统一的接口定义和通信机制。

与其他框架的比较

特性 Thrift Protobuf Avro gRPC
开发者 Apache Software Foundation Google Apache Software Foundation Google
序列化格式 二进制 二进制 二进制 使用Protobuf作为默认序列化格式
IDL支持 是(通过Protobuf的.proto文件定义)
语言支持 多种语言,包括Java、C++、Python、Go等 多种语言,包括Java、C++、Python、Go等 多种语言,包括Java、C++、Python等 多种语言,包括Java、C++、Python、Go等
动态模式 支持 不支持 支持 不直接支持(但可以通过Protobuf的动态功能)
向后兼容性 良好 良好 优秀 良好(通过Protobuf的兼容性功能)
速度和效率 高效 高效 较高 高效(依赖于Protobuf的效率)
使用场景 服务间通信、微服务架构 数据存储、网络通信 数据存储、数据流处理 服务间通信、微服务架构,特别是需要流式通信时
RPC支持 否(仅提供序列化) 否(仅提供序列化) 是(内置支持,通过HTTP/2)
成熟度和社区 成熟,活跃社区 成熟,广泛使用 成熟,活跃社区 成熟,广泛使用
扩展性 高(通过插件机制)
传输协议 多种协议,包括HTTP、TCP 无特定传输协议 无特定传输协议 基于HTTP/2

这些技术各有优缺点,选择时应根据具体需求和使用场景来进行权衡。Thrift和gRPC适合需要完整RPC支持的场景,而Protobuf和Avro则主要用于高效的数据序列化。

Apache Thrift的实现逻辑

Thrift的架构

Thrift技术栈分层从下向上分别为:传输层(Transport Layer)协议层(Protocol Layer)处理(Processor Layer)和服务层(Server Layer)

  • 传输层(Transport Layer):传输层负责直接从网络中读取和写入数据,它定义了具体的网络传输协议;比如说TCP/IP传输等。
  • 协议层(Protocol Layer):协议层定义了数据传输格式,负责网络传输数据的序列化和反序列化;比如说JSON、XML、二进制数据等。
  • 处理层(Processor Layer):处理层是由具体的IDL(接口描述语言)生成的,封装了具体的底层网络传输和序列化方式,并委托给用户实现的Handler进行处理。
  • 服务层(Server Layer):整合上述组件,提供具体的网络IO模型(单线程/多线程/事件驱动),形成最终的服务。

Apache Thrift 是一个用于跨语言服务开发的框架,其核心组件主要包括以下几个部分:

  • 接口定义语言(IDL):Thrift 使用 IDL 来定义服务的接口和数据结构。开发者通过编写 .thrift 文件来描述服务的接口、方法及其参数和返回类型。
  • Thrift 编译器:Thrift 编译器是一个命令行工具,用于将 .thrift 文件编译成目标语言的代码。编译器生成客户端和服务器端的存根代码,以及用于数据序列化和反序列化的代码。
  • 协议(Protocol):协议定义了数据的编码格式。Thrift 提供了多种协议实现,包括:
    • TBinaryProtocol:一种高效的二进制编码协议。
    • TCompactProtocol:一种更紧凑的二进制编码协议,适合对带宽敏感的场景。
    • TJSONProtocol:基于 JSON 的文本协议,便于调试和人类可读。
    • TSimpleJSONProtocol:仅支持 JSON 格式的输出,用于日志记录。
  • 传输(Transport):传输层负责数据在客户端和服务器之间的传输方式。Thrift 提供了多种传输实现,包括:
    • TSocket:基于阻塞的 TCP 传输。
    • TFramedTransport:用于无阻塞服务器的帧传输。
    • TMemoryTransport:用于内存中的数据传输,通常用于测试。
    • TZlibTransport:提供数据压缩功能。
  • 服务器(Server):服务器组件负责监听客户端请求并调用相应的服务处理方法。Thrift 提供了多种服务器模型以满足不同的并发和性能需求,包括:
    • TSimpleServer:简单的单线程服务器,适用于测试。
    • TThreadPoolServer:使用线程池的多线程服务器,适合生产环境。
    • TNonblockingServer:基于非阻塞 I/O 的服务器,适合高并发场景。
    • THsHaServer:半同步半异步服务器,结合了线程池和非阻塞 I/O。
  • 服务处理器(Processor):服务处理器负责将接收到的请求路由到具体的服务实现中。开发者需要实现由 Thrift 编译器生成的接口,以定义具体的业务逻辑。
  • 客户端(Client):客户端使用由 Thrift 编译器生成的客户端存根代码来与服务器进行交互。客户端代码负责将方法调用转换为网络请求,并处理服务器的响应。
  • 异步支持:Thrift 支持异步调用模式,允许客户端在不阻塞的情况下发出请求,这在需要高并发和低延迟的应用场景中非常有用。

通过这些核心组件,Apache Thrift 提供了一个强大且灵活的框架,用于构建跨语言的分布式服务。

Apache Thrift 的使用

在 Python 环境下使用 Apache Thrift 进行服务开发通常包括以下几个步骤。以下是一个简单的教程,帮助你快速入门:

安装 Apache Thrift

首先,你需要安装 Apache Thrift。可以通过包管理工具进行安装:pip install thrift定义 Thrift 接口

创建一个 .thrift 文件,定义服务接口和数据结构。例如,创建一个名为 calculator.thrift 的文件:

namespace py tutorial

service Calculator {
i32 add(1:i32 num1, 2:i32 num2),
i32 subtract(1:i32 num1, 2:i32 num2),
}

生成 Python 代码

使用 Thrift 编译器生成 Python 代码。假设你的 Thrift 文件位于当前目录:

thrift --gen py calculator.thrift

这将在当前目录下生成一个 gen-py 文件夹,包含生成的 Python 代码。

实现服务器

创建一个 Python 脚本 server.py,实现服务器逻辑:

from thrift import Thrift
from thrift.protocol import TBinaryProtocol
from thrift.server import TSimpleServer
from thrift.transport import TSocket, TTransport

from gen-py.tutorial import Calculator


class CalculatorHandler:
def add(self, num1, num2):
print(f"Adding {num1} and {num2}")
return num1 + num2

def subtract(self, num1, num2):
print(f"Subtracting {num2} from {num1}")
return num1 - num2


if __name__ == "__main__":
handler = CalculatorHandler()
processor = Calculator.Processor(handler)
transport = TSocket.TServerSocket(host='127.0.0.1', port=9090)
tfactory = TTransport.TBufferedTransportFactory()
pfactory = TBinaryProtocol.TBinaryProtocolFactory()

server = TSimpleServer.TSimpleServer(processor, transport, tfactory, pfactory)
print("Starting server...")
server.serve()
print("done.")

实现客户端

创建一个 Python 脚本 client.py,实现客户端逻辑:

from thrift import Thrift
from thrift.protocol import TBinaryProtocol
from thrift.transport import TSocket, TTransport

from gen-py.tutorial import Calculator


if __name__ == "__main__":
    try:
        # Make socket
        transport = TSocket.TSocket('127.0.0.1', 9090)

        # Buffering is critical. Raw sockets are very slow
        transport = TTransport.TBufferedTransport(transport)

        # Wrap in a protocol
        protocol = TBinaryProtocol.TBinaryProtocol(transport)

        # Create a client to use the protocol encoder
        client = Calculator.Client(protocol)

        # Connect!
        transport.open()

        sum_result = client.add(10, 20)
        print(f"10+20={sum_result}")

        diff_result = client.subtract(30, 10)
        print(f"30-10={diff_result}")

        # Close!
        transport.close()

    except Thrift.TException as tx:
        print(f"Thrift exception: {tx.message}")

运行服务器和客户端

  • 在终端中,首先启动服务器:python server.py
  • 然后在另一个终端中运行客户端:python client.py

你应该会看到客户端输出加法和减法的结果,同时服务器端会打印出接收到的请求信息。

通过以上步骤,你可以在Python环境中使用Apache Thrift实现简单的RPC服务。根据需要,你可以扩展服务的功能,或者使用其他传输协议和服务器类型。

参考链接:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注