Code : DubboTester/dubbo_tester.py at master · WeekL/DubboTester · GitHub
Dubbo和telnet
简介
Dubbo是阿里巴巴开源的一款RPC(Remote Procedure Call,远程过程调用)框架,用于实现分布式服务的跨服务调用,具有远程通讯、动态配置、地址路由等功能。
Dubbo基于dubbo协议,dubbo协议是TCP协议之上的协议,采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
Telnet协议是TCP/IP协议族中的一员,是Internet远程登录服务的标准协议和主要方式。Telnet是常用的远程控制Web服务器的方法,具体介绍可以查看百度百科:Telnet_百度百科
Dubbo 2.0.5版本以上开始支持telnet命令调用,本文正是基于telnet命令来实现对Dubbo接口的调用。
使用telnet命令调用dubbo服务
编写代码之前,先简单了解一下如何使用telnet命令调用dubbo服务。
首先打开cmd,使用telnet命令连接服务器(如果提示指令不存在的话,在设置-启用或关闭Windows功能里勾选“Telnet客户端“并保存)
telnet 172.16.51.4 20885
其中172.16.51.4
是dubbo服务所在的服务器地址,20885
是dubbo服务指定的端口。
telnet连接服务器
连接后按回车,出现dubbo>输入提示符表示已经连上了dubbo服务
连接dubbo服务器
telnet命令
- 输入
ls
并回车,列出所有可用的服务 - 输入
ls 服务名
,列出服务下所有的方法 - 输入
ls -l 服务名
,列出服务下的所有方法和参数 - 输入
invoke 服务名.方法名(调用参数)
,调用对应服务的dubbo接口 - 其它Telnet命令参考
telnet调用示例
调用UserInfoRpcService服务的getUserState方法,参数是一个Long类型数值
如下图,接口成功响应并返回了一个json字符串(默认不是utf-8编码,所以中文会乱码)
调用接口
终上所述,使用telnet命令的方式调用dubbo接口最少需要三步:
1、查找服务的ip和端口(通常是在dubbo-admin或zookeeper查找)
2、telnet连接服务器
3、invoke命令调用接口
如果一次两次还好,如果用的多了,就会感觉很不方便:
1、每次都要查找对应服务的ip端口并手动连接
2、连接一段时间不操作,就会自动断开连接
3、invoke命令纯手输,输错了不能用光标移动到错误处修改,只能删除重新输入
4、响应不支持中文,且没有格式化,需要复制出来手动格式化才具有易读性
使用Python实现
既然手动输入telnet命令很不方便,那么使用代码实现可以做到哪些改进呢?
重复几次命令操作之后就会发现,除了调用时需要填写的服务名、方法名和参数之外,其余如查找ip端口、连接服务器、格式化响应都是重复性很高的操作,完全可以简化。
所以我们用Python实现的目标就是:只输入服务名
、方法名
、参数
并执行,就得到一个易读的返回结果。
通过服务名自动查找ip端口
首先人工查找服务的ip端口的步骤是可以省略的。
系统通过dubbo提供服务,需要将服务注册到指定的注册中心(通常是使用Zookeeper作为Dubbo的注册中心),并暴露其服务器ip和端口,既然如此,就可以通过注册中心查找对应服务的注册信息,来自动获取其ip和端口了。
在Python中,可以通过kazoo库来连接Zookeeper,代码如下:
from urllib.parse import unquote
from kazoo.client import KazooClient
# zookeeper的ip和端口
zk = {
'host': '172.16.253.21',
'port': 2181
}
class Zookeeper:
client = None
service_dict = {}
class ServiceNotAvailableError(ValueError):
pass
def __init__(self, timeout=100):
# 连接zookeeper
self.client = KazooClient('%s:%s' % (zk['host'], zk['port']), timeout=timeout)
self.client.start()
# 查找所有注册的dubbo服务
service_list = self.client.get_children('dubbo')
for service in service_list:
name = str(service).split('.')[-1] # 去掉包名,剩下的服务名作为key