功能:用python的kazoo工具包,检测 dubbo在zookeeper上是否活跃。
情况:dubbo部署在机器上,端口是存在的,但在zookeeper上缺没有dubbo提供者了。
所以写个脚本,利用kazoo链接到zookeeper来检测指定的服务是否存在。
检测项目:
- 需要自己指定相应的检测service
- 可以检测提供服务的机器,是否是线上机器。
- 可以检测版本号是否正确。
调用方式:可以在linux上的crontab来定时执行。例如2分钟检测一次。
#checkzookeeper.py
import sys
import time
from kazoo.client import KazooClient
from kazoo.client import ChildrenWatch
from kazoo.client import DataWatch
from checkNode import watcherNode
def zkWatcher(host, port):
"""
查看zookeeper的链接
:param host:
:param port:
:return:
"""
# 最终的报错信息
error_info = ""
addr = host + ":" + port
zk = KazooClient(hosts=addr)
try:
zk.start()
node_list = zk.get_children('/dubbo') # 查看dubbo根节点有多少个子节点
if node_list and len(node_list) > 0:
# 调用检测函数,如果有问题就会返回错误字符串
error_info = watcherNode(zk, node_list)
else:
# 没有提供任何的服务列表,发送报警短信
error_info = "zk中没有提供任何服务!!!"
except BaseException as e:
# 如果kazoo是打开的状态,就需要关闭
print(e)
# 没有提供任何的服务列表,发送报警短信
error_info = "连接zookeeper错误!!!" + str(e);
zk.stop()
# 发送报警短信
if len(error_info) > 0:
print(error_info)
if __name__ == "__main__":
# 调用检测函数
zkWatcher(host="192.168.80.221", port="2181")
sys.exit()
#checkNode.py
import sys
import time
from urllib import parse
from kazoo.client import KazooClient
def needCheckNode():
"""
需要检测的服务节点
:return: ['provide名称': ['provider服务1', 'provider服务2']]
"""
need_check_node_dict = {}
need_check_node_dict['pay'] = ['com.yuedooli.pay.service.BillServiceEx',
'com.yuedooli.pay.service.PayArrearServiceEx',
'com.yuedooli.pay.service.bill.Bill2ServiceEx',
'com.yuedooli.pay.service.bill.Bill2Service333Ex']
return need_check_node_dict
def watcherNode(kazoo, node_list):
"""
查看dubbo下的node数据:
关键的服务进行抽样检查
:param kazoo: kazoo的回话对象
:param node_list: 等同于"ls /dubbo"命令
:return: result_error_info.如果有服务没有提供者,返回错误信息。
"""
# print(node_list)
# 存储每一个节点的键值对: com.yuedooli.found.service.CityServiceEx : com.yuedooli.found.service.CityServiceEx
node_dict = {}
for node in node_list:
print(node)
node_dict[node] = node
# 打印所有的字典
# print(node_dict)
# 获取要检测的数据
need_check_node_dict = needCheckNode()
# 错误的信息记录:zookeeper中有该节点,但没有提供者
result_error_info = ""
# 错误的信息记录:zookeeper上未找到的节点
result_error_info2 = ""
# 错误的信息记录:zookeeper中有该节点,有提供者,但版本号不对
result_error_info3 = ""
# 错误的信息记录:zookeeper中有该节点,有提供者,但IP地址不对
result_error_info4 = ""
# 线上的版本
version_prefix = "version=2.0"
# 线上提供机器IP的前缀
ip_prefix = "172.16"
for check_node in need_check_node_dict.keys():
for check_node_son in need_check_node_dict[check_node]:
try:
print("检测provider:" + check_node + ", 检测的服务为:" + check_node_son)
key_service = check_node_son.split(".")
key_str = check_node + ":" + key_service[key_service.__len__() - 1]
# 获取提供服务的列表
provider_list = kazoo.get_children("/dubbo/" + check_node_son + "/providers")
# 如果是提供服务的列表不为空,就是正常,否则记录错误
if provider_list and len(provider_list) > 0:
for dubbo_item in provider_list:
dubbo_item_uncode = parse.unquote(dubbo_item) # 解码url
# print(dubbo_item_uncode)
# 是否有必要继续检测下去,如果有报错,就没有必要继续检测了,因为每个服务有4个节点,都会轮询则错误就会重复
need_next_check_state = True
# 检测IP地址
if dubbo_item_uncode.find(ip_prefix, 0, len(dubbo_item_uncode)) == -1:
result_error_info4 += key_str + ","
need_next_check_state = False
# 检测版本号
if dubbo_item_uncode.find(version_prefix, 0, len(version_prefix)) == -1:
result_error_info3 += key_str + ","
need_next_check_state = False
# 已经有报错了,没有必要再继续检测下去了
if not need_next_check_state:
break;
else:
# 报错,没有提供服务
result_error_info += key_str + ", "
except BaseException as e:
print(str(e))
# 获取节点报错,没有提供服务
result_error_info2 += key_str + ", "
pass
# 最终返回的字符串
result_info = ""
if len(result_error_info) > 0:
result_error_info = ", Dubbo中有服务但没有提供者:(" + result_error_info + ")"
result_info += result_error_info
if len(result_error_info2) > 0:
result_error_info2 = ", Dubbo中无此服务:(" + result_error_info2 + ")"
result_info += result_error_info2
if len(result_error_info3) > 0:
result_error_info3 = ", 版本号错误:(" + result_error_info3 + ")"
result_info += result_error_info3
if len(result_error_info4) > 0:
result_error_info4 = ", 线下机器提供了线上服务:(" + result_error_info4 + ")"
result_info += result_error_info4
return result_info