我正在参与「掘金启航方案」

如何动态的测试Thrift服务

​RPC协议与Thrift结构

RPC(Remote Procedure Call,长途过程调用)是一种通信协议,用于不同的进程或核算机之间进行通信和交互。它答应应用程序在本地或长途核算机上调用另一个应用程序中的函数或办法,就像调用本地函数相同。

RPC协议经过网络传输协议来完成不同核算机之间的通信,常见的网络传输协议有TCP、UDP等。当一个客户端需求调用长途服务器上的某个办法时,客户端会向服务器发送一个恳求(包括恳求参数),服务器接收到恳求后履行相应的办法,并回来成果(包括回来值)。客户端接收到成果后持续履行自己的逻辑。

RPC协议的长处在于它能够隐藏底层通信细节,使得开发人员能够像调用本地函数相同调用长途函数,然后简化了分布式体系的开发。此外,RPC协议还具有高效、灵敏、可扩展等长处,因此广泛应用于分布式体系、微服务架构等范畴。

RPC(Remote Procedure Call)是一种通用的长途过程调用协议,而Thrift则是根据RPC协议开发的高效、跨言语和跨渠道的服务结构。

Thrift是由Facebook开源的一个分布式服务结构,它运用IDL(Interface Definition Language)界说服务接口,然后经过自动生成代码的办法完成各种编程言语之间的互操作性。Thrift支撑多种数据序列化和传输协议,包括二进制编码、JSON、XML等,还供给了多种服务器的完成办法和客户端库。

在Thrift的内部完成中,它运用了RPC协议来完成长途过程调用,并运用不同的编程言语的反射机制来对音讯进行序列化和反序列化。经过运用RPC协议,Thrift能够在不同的核算机上运转服务,并答应客户端以本地服务的办法调用长途服务。此外,Thrift还供给了比如负载均衡、故障转移、安全认证等方面的特性,使得分布式服务开发更加方便和高效。

完成一个Thrift服务

以下是一个运用Java和Thrift结构完成的简略订单查询服务示例。该服务包括一个接口,对应着查询订单信息的操作:

  1. 界说Thrift服务的IDL文件(例如example.thrift),其中界说了服务名称、接口、办法、参数和回来值等信息:
namespace java example
struct Order {
    1: i32 orderId,
    2: string customerName,
    3: double amount
}
service OrderService {
    Order getOrder(1: i32 orderId)
}

上面的IDL文件中界说了一个结构体Order,表明订单信息,以及一个接口OrderService,包含了一个获取订单信息的办法getOrder。

  1. 运用Thrift供给的工具生成Java代码(例如在命令行中履行thrift –gen java example.thrift)。这将生成与IDL文件中界说的服务接口和办法相对应的Java类和接口。

  2. 完成服务接口的详细逻辑。例如,在服务器端完成一个订单查询服务:

public class OrderServiceImpl implements OrderService.Iface {    private Map<Integer, Order> orderMap = new HashMap<>();​    public OrderServiceImpl() {        // 初始化订单数据        for (int i = 1; i <= 10; i++) {            Order order = new Order(i, "Customer" + i, i * 100.0);            orderMap.put(order.orderId, order);        }    }​    @Override    public Order getOrder(int orderId) throws TException {        if (orderMap.containsKey(orderId)) {            return orderMap.get(orderId);        } else {            throw new TException("Order not found");        }    }​    public static void main(String[] args) throws Exception {        TServerTransport serverTransport = new TServerSocket(9090);        TProcessor processor = new OrderService.Processor<OrderService.Iface>(new OrderServiceImpl());        TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor(processor));        System.out.println("Starting the server...");        server.serve();    }}

在上述代码中,运用Thrift供给的TProcessor将服务完成类与IDL文件中界说的接口绑定起来,并创立了一个TSimpleServer目标来启动服务器。在详细的业务逻辑中,查询订单信息时会遍历已有订单数据并查找对应订单信息。

  1. 在客户端编写代码调用服务。例如:
public class OrderServiceClient {
    public static void main(String[] args) throws Exception {
        TTransport transport = new TSocket("localhost", 9090);
        transport.open();
        TProtocol protocol = new TBinaryProtocol(transport);
        OrderService.Client client = new OrderService.Client(protocol);
​
        int orderId = 5;
        try {
            Order order = client.getOrder(orderId);
            System.out.printf("Order #%d: %s, %.2f\n", order.orderId, order.customerName, order.amount);
        } catch (TException e) {
            System.out.println("Failed to get order: " + e.getMessage());
        }
​
        transport.close();
    }
}

在客户端代码中,创立一个与服务器通信的TSocket目标,然后运用该目标创立TProtocol目标,并运用其创立OrderService.Client客户端署理目标。经过客户端署理目标调用服务器供给的服务接口和办法,并获取服务成果。

如何测验thrift服务

下面是一个根据TestNG的Thrift自动化测验结构规划思路,并给出对应的Java代码完成。

1. 模块划分

该结构能够划分为以下几个模块:

  • 测验套件模块:界说测验用例,包括测验办法、输入参数和预期成果等。

  • 测验数据模块:供给测验所需的数据,例如订单信息、客户信息等。这些数据能够从文件、数据库或其他来历中读取。

  • 测验环境模块:创立并初始化测验环境,包括启动测验服务器和创立Thrift客户端署理目标等。

  • 测验履行模块:履行测验用例,并进行成果断言和记载。能够运用Mock目标模拟测验环境,然后防止对真实环境造成影响。

  • 测验报告模块:生成测验报告,展现测验的成果和计算信息等。

2. 完成办法

在Java中,能够经过以下办法来完成上述模块:

  • 运用TestNG注解界说测验用例(例如@Test)和测验套件(例如@Suite)。

  • 创立POJO类,表明订单信息、客户信息等测验数据。

  • 运用@BeforeSuite、@AfterSuite、@BeforeTest、@AfterTest等注解,在适当的机遇创立和铲除测验环境。

  • 在测验办法中,经过Thrift客户端署理目标调用服务接口和办法,并对回来成果进行断言和记载。

  • 运用TestNG供给的Reporter API来生成测验报告。

下面是一个根据TestNG的Thrift自动化测验结构示例代码,假设服务接口为example.OrderService:

import example.Order;
import example.OrderService;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.transport.TSocket;
import org.testng.annotations.*;
​
import java.util.Random;
​
public class OrderServiceTest {
    private static final int PORT = 9090;
    private static OrderService.Client client;
​
    @BeforeSuite
    public void setUp() throws Exception {
        // 创立Thrift客户端署理目标
        TSocket socket = new TSocket("localhost", PORT);
        socket.open();
        client = new OrderService.Client(new TBinaryProtocol(socket));
    }
​
    @AfterSuite
    public void tearDown() throws Exception {
        // 封闭Thrift客户端
        if (client != null) {
            client.getInputProtocol().getTransport().close();
        }
    }
​
    @DataProvider(name = "orderData")
    public Object[][] createOrderData() {
        // 创立订单数据
        return new Object[][]{
                {new Order(1, "Customer1", 100)},
                {new Order(2, "Customer2", 200)},
                {new Order(3, "Customer3", 300)}
        };
    }
​
    @Test(dataProvider = "orderData")
    public void testGetOrder(Order order) throws Exception {
        // 测验用例1:查询已有订单信息
        Order result = client.getOrder(order.orderId);
        assertOrderEquals(order, result);
​
        // 测验用例2:查询不存在的订单信息
        try {
            client.getOrder(0);
        } catch (Exception e) {
            assertErrorMessageEquals("Order not found", e.getMessage());
        }
    }
​
    // 增加更多测验用例...private void assertOrderEquals(Order expected, Order actual) {
        // 比较订单信息是否持平
    }
​
    private void assertErrorMessageEquals(String expected, String actual) {
        // 比较过错音讯是否持平
    }
}

在上述代码中,运用TestNG供给的注解@BeforeSuite和@AfterSuite分别创立和封闭Thrift客户端署理目标,并运用@DataProvider注解界说测验数据。在@Test注解的测验办法中,经过Thrift客户端署理目标调用服务办法,并对回来成果进行断言。此外,还能够结合持续集成工具(例如Jenkins)和自动化测验结构(例如Selenium或Appium)来完成布置、测验和反应的自动化流程。

往期推荐

聊聊工作中的自我管理和向上管理

经验共享|测验工程师转型测验开发进程

聊聊UI自动化的PageObject规划形式

细读《阿里测验之道》

我在阿里做测开