dubbo官方文档中有提到:
从 2.0.5 版本开始,dubbo 开始支持通过 telnet 命令来进行服务治理。
也就是说我们可以通过telnet远程连接已经部署dubbo的服务器,执行shell命令, 可用来调用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()
通过invoke请求dubbo接口的时候,除了integer,string还会有枚举类,实体类等入参。
枚举类请求
枚举类的请求格式为:
枚举类sex 中,包含man和woman
{"name":"MAN","class":"com.zl.enums.sex"}
实体类请求
实体类需要先将实体类全名写出,然后再写实体类对应的值
{"class":"com.zl.entity.student","name":"zl","sex":"man","age":"18"}
map对象请求
public class UserMap {
private Map<String, Integer> UserMap;
}
调用方式:
{"UserMap":{"age":18}}