本次測試了下面幾個 api
consul_ip="10.0.26.104"
service_name="base-gateway"
檢視consul叢集所有 node :
curl "http://${consul_ip}:8500/v1/catalog/nodes" | jq
檢視consul叢集所有 service:
curl "http://${consul_ip}:8500/v1/internal/ui/services?dc=dc1" | jq
檢視consul叢集内某個service下的服務詳情(服務下的ID可以從這裡檢視):
curl "http://${consul_ip}:8500/v1/health/service/${service_name}?dc=dc1" | jq
删除consul叢集内某個ID:
curl -XPUT "http://${consul_ip}:8500/v1/agent/service/deregister/${service_id}"
檢視consul叢集内所有 critical (失效)狀态的
ID: "http://${consul_ip}:8500/v1/health/state/critical" | jq
檢視consul叢集内所有 passing (有效)狀态的
ID: "http://${consul_ip}:8500/v1/health/state/critical" | jq
=============================================
現在可以通過這些API拿到這些資訊,那麼接下來撸一段兒代碼,來利用起來。目前碰到了這種情況,某些地方的 consul 管理頁面不在一個内網,且對面沒有windows,不給代理。于是就突發奇想,研究一個linux端的管理工具。
使用python寫的,為了直接可以放在 centos 上執行,不安裝任何依賴包,于是下面代碼使用了 python2 ,子產品用了已經接近淘汰的 urllib和 urllib2 , 代碼如下:
vim manage_consul.py
# -*- coding: utf-8 -*-
import sys
import json
import urllib,urllib2
class ManageConsulServiceNode(object):
"""使用 consul 接口管理服務注冊情況"""
def __init__(self, consul_ip):
"""基本資料"""
self.consul_ip = consul_ip
self.get_consul_nodes_url = "http://{consul_ip}:8500/v1/catalog/nodes"
self.get_consul_service_url = "http://{consul_ip}:8500/v1/internal/ui/services?dc=dc1"
self.get_consul_service_name_url = "http://{consul_ip}:8500/v1/health/service/{service_name}?dc=dc1"
self.put_consul_service_id_url = "http://{consul_ip}:8500/v1/agent/service/deregister/{service_id}"
self.query_consul_critical_url = "http://{consul_ip}:8500/v1/health/state/critical"
def consul_ip_list(self):
"""擷取consul叢集節點ip"""
ip_list = []
get_consul_nodes_url = self.get_consul_nodes_url.format(consul_ip=self.consul_ip)
request = urllib2.Request(get_consul_nodes_url)
response = urllib2.urlopen(request)
json_data = json.loads(response.read())
for data_dict in json_data:
consul_ip = data_dict["Address"]
ip_list.append(consul_ip)
return ip_list
def get_consul_service_status(self):
"""擷取consul内所有服務"""
service_list = []
service_dict = {}
get_consul_service_url = self.get_consul_service_url.format(consul_ip=self.consul_ip)
request = urllib2.Request(get_consul_service_url)
response = urllib2.urlopen(request)
json_data = json.loads(response.read())
for service_dict in json_data:
service_dict["service_name"] = service_dict["Name"]
service_dict["service_critical"] = service_dict["ChecksCritical"]
service_dict["service_passing"] = service_dict["ChecksPassing"]/2
service_list.append(service_dict)
return service_list
def get_consul_service_info(self):
"""擷取各服務内節點狀态,并列印"""
print("")
print("--- consul 叢集中目前服務如下: ---")
print("\t目前 consul 叢集節點: {0}\n".format(self.consul_ip_list()))
for service_name_dict in self.get_consul_service_status():
service_name = service_name_dict["service_name"]
if "consul" in service_name:
continue
head_mess = "\t\033[1;32m服務名: {0:^20} -存活的節點數: {1}, -失效的節點數: {2}\033[0m".format(
service_name_dict["service_name"],
service_name_dict["service_critical"],
service_name_dict["service_passing"],
chr(250)
)
print(head_mess)
get_consul_service_url = self.get_consul_service_name_url.format(consul_ip=self.consul_ip,service_name=service_name)
request = urllib2.Request(get_consul_service_url)
response = urllib2.urlopen(request)
json_data = json.loads(response.read())
for service_info in json_data:
service_id = service_info["Service"]["ID"]
service_ipaddr = service_info["Service"]["Address"]
service_port = service_info["Service"]["Port"]
service_status = service_info["Checks"][1]["Status"]
boday_mess = "\t\t服務ID: {0:^60} 服務位址: {1}:{2} 狀态: {3}".format(
service_id,
service_ipaddr,
service_port,
service_status,
chr(250)
)
print boday_mess
print("")
def deregister_consul_service_id(self, service_id):
"""發送 PUT 請求登出 consul 中服務 id"""
for consul_ip in self.consul_ip_list():
print("--- 清理{0}節點的: {1}".format(consul_ip, service_id))
put_consul_service_id_url = self.put_consul_service_id_url.format(consul_ip=consul_ip,service_id=service_id)
request = urllib2.Request(put_consul_service_id_url)
request.get_method = lambda: 'PUT'
ret = urllib2.urlopen(request).read()
print(ret)
def deregister_consul_all_critical_id(self, deregister_service=None):
"""登出 consul 内所有 critical 狀态的服務 ID"""
query_consul_critical_url = self.query_consul_critical_url.format(consul_ip=self.consul_ip)
request = urllib2.Request(query_consul_critical_url)
response = urllib2.urlopen(request)
json_data = json.loads(response.read())
for critical_id_dict in json_data:
if deregister_service is None:
critical_id = critical_id_dict["ServiceID"]
self.deregister_consul_service_id(critical_id)
else:
critical_service_name = critical_id_dict["ServiceName"]
if deregister_service == critical_service_name:
critical_id = critical_id_dict["ServiceID"]
self.deregister_consul_service_id(critical_id)
if __name__ == "__main__":
"""按參數做相應處理"""
parameter_sum = len(sys.argv)
self_name = sys.argv[0]
if parameter_sum < 2 or parameter_sum == 1:
query_mess = "列出consul内所有服務和節點: {0} {1}".format(self_name, "[consul ip]")
deregister_mess = "登出某個服務ID: {0} {1} {2}".format(self_name, "[consul ip]", "[service id]")
deregister_critical_all_mess = "登出所有服務下的失效ID: {0} {1} {2}".format(self_name, "[consul ip]", "[critical]")
deregister_critical_service_mess = "登出某個服務下的失效ID: {0} {1} {2} {3}".format(self_name, "[consul ip]", "[critical]", "[service name]")
print(query_mess)
print(deregister_mess)
print(deregister_critical_all_mess)
print(deregister_critical_service_mess)
sys.exit(deregister_mess)
### 調用 consul api
ip_parameter = sys.argv[1]
manage_consul_service = ManageConsulServiceNode(ip_parameter)
# 帶一個參數,直接列出所有服務的節點
if parameter_sum == 2:
manage_consul_service.get_consul_service_info()
# 帶兩個參數時,第二個參數為 critical 時清理所有失效ID,第二個參數為服務 ID 時隻登出目前 ID
if parameter_sum == 3:
service_id = sys.argv[2]
if service_id == "critical":
manage_consul_service.deregister_consul_all_critical_id()
else:
manage_consul_service.deregister_consul_service_id(service_id)
# 帶三個參數時,第二個參數為 critical, 第三個參數為對應的 service 名稱,即可登出對應 service 下的所有失效節點
if parameter_sum == 4:
service_name = sys.argv[3]
manage_consul_service.deregister_consul_all_critical_id(service_name)
執行效果如下圖
空的執行腳本,列印使用方式
列出所有服務和下面的 ID
清理所有已經失效的ID
清理某個沒有節點(沒有失效的節點也可被清理):
清理某個服務下的失效節點: