python请求dubbo接口

991 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

Dubbo是一款高性能、轻量级的开源Java RPC框架。目前Dubbo技术栈广泛运用于各种企业级项目中。

在工作中,我们通常需要针对Dubbo接口进行测试,而测试同学更多的使用的python技术栈,如何使用python去测试dubbo接口呢?

telnet命令

dubbo官方文档中有提到:

从 2.0.5 版本开始,dubbo 开始支持通过 telnet 命令来进行服务治理。

也就是说我们可以通过telnet远程连接已经部署dubbo的服务器,执行shell命令,通过Invoke的方式来调用dubbo接口。

代码实现

代码中使用的server_host 一般是ip地址,像这种分布式的服务一般是通过docker部署,每次部署ip都会变化。这时可以通过zk的后台管理服务,将每次部署的ip动态获取出来,再调用以下的方法进行请求

import re
import telnetlib
import time
import requests


class TelnetClient(object):
    """通过telnet连接dubbo服务, 执行shell命令, 可用来调用dubbo接口
    """

    def __init__(self, server_host, server_post):
        self.tn = telnetlib.Telnet()
        self.server_host = server_host
        self.server_port = server_post

    # 此函数实现telnet登录主机
    def connect_dubbo(self):
        try:
            print("telent连接dubbo服务端: telnet {} {} ……".format(self.server_host, self.server_port))
            self.tn.open(self.server_host, port=self.server_port)
            return True
        except Exception as e:
            print('连接失败, 原因是: {}'.format(str(e)))
            return False


    # 此函数实现执行传过来的命令,并输出其执行结果
    def execute_some_command(self, command):
        # 执行命令
        cmd = (command + '\n').encode("gbk")
        self.tn.write(cmd)

        # 获取命令结果,字符串类型
        retry_count = 0
        # 如果响应未及时返回,则等待后重新读取,并记录重试次数
        result = self.tn.read_very_eager().decode(encoding='gbk')
        while result == '':
            time.sleep(1)
            result = self.tn.read_very_eager().decode(encoding='gbk')
            retry_count += 1
        return result

    # 退出telnet
    def logout_host(self):
        self.tn.write(b"exit\n")
        print("登出成功")


class InvokeDubboApi(object):

    def __init__(self, server_host, server_post):
        try:
            self.telnet_client = TelnetClient(server_host, server_post)
            self.login_flag = self.telnet_client.connect_dubbo()
        except Exception as e:
            print("invokedubboapi init error" + str(e))

    def get_all_dubbo_apis(self):
        """ 获取指定服务的接口数量及接口明细
        """

        dubbo_apis = []

        try:
            if self.login_flag:
                services = self.telnet_client.execute_some_command("ls")
                print(f'获取服务列表:{services}')
                services = services.split("\r\n")
                services.pop()

                for service in services:
                    resp = self.telnet_client.execute_some_command("ls {}".format(service))
                    resp = resp.split("\r\n")
                    resp.pop()
                    for j in range(len(resp)):
                        resp[j] = service + '.' + resp[j]
                        dubbo_apis.append(resp[j])
                new_dubbo_api_list = list(set(dubbo_apis))
                print("rpc接口 数量是: {}".format(new_dubbo_api_list.__len__()))
                return new_dubbo_api_list
        except Exception as e:
            raise ("获取dubbo接口失败,原因是{}".format(str(e)))

    def invoke_dubbo_api(self, dubbo_service, dubbor_method, *args):
        api_name = dubbo_service + "." + dubbor_method + "{}"
        cmd = "invoke " + api_name.format(args)
        print("调用命令是:{}".format(cmd))
        resp0 = None
        try:
            if self.login_flag:
                resp0 = self.telnet_client.execute_some_command(cmd)
                print("接口响应是,resp={}".format(resp0))
                return resp0
            else:
                print("登陆失败!")
        except Exception as e:
            raise Exception("调用接口异常, 接口响应是resp={}, 异常信息为:{}".format(resp0, str(e)))

    def logout(self):
        self.telnet_client.logout_host()

请求示例

java代码中,入参的方式通常为实体类DTO,list,以及单参数,多参数等情况,这里列举几种请求dubbo接口的时候常见的一些入参情况

1、枚举类请求

枚举类的请求格式为: 枚举类sex 中,包含man和woman

{"name":"MAN","class":"com.zl.enums.sex"}

2、实体类请求

实体类需要先将实体类全名写出,然后再写实体类对应的值

{"class":"com.zl.entity.student","name":"zl","sex":"man","age":"18"}

3、map对象请求

public class UserMap {
    private Map<String, Integer> UserMap;
}

调用方式:

{"UserMap":{"age":18}}

4、java变量

如果是通常使用的string,int等,直接传入{"string"},{int} 即可