clickhouse-watchdog 实现监控是否挂掉,挂掉自动重启

自动重启实现原理

  1. 官方的clickhouse-watchdog经常失效,不能自动重启
  2. 通过python脚本定时执行service clickhouse-server status命令检查clickhouse的状态。
  3. 当检查到进程死亡时执行service clickhouse-server start启动

python脚本代码

  1. Java程序员写的,代码优点烂,不过能用
  2. webhook_url配置飞书的机器人实现告警。
import requests
import subprocess
import sys
import time

# 要监控的进程名(通常只是进程名的一部分)
env = "线上环境"
webhook_url = 'https://open.feishu.cn/open-apis/bot/v2/hook/********************'
# 限流器
limit = False


def send_alert(message):
    from datetime import datetime

    # 获取当前时间
    now = datetime.now()

    # 格式化时间为字符串
    formatted_time = now.strftime("%Y-%m-%d %H:%M:%S")
    message_content = {
        "content": {
            "text": f"告警环境:{env}\n告警级别:严重\n告警时间:{formatted_time}\n告警内容:{message}"
        },
        "msg_type": "text"
    }

    if limit:
        print(f"消息发送失败,被限流,{message_content}")
    else:
        send_message_to_feishu(webhook_url, message_content)
        print(f"消息发送成功,{message_content}")


def send_message_to_feishu(webhook_url, message_content):
    """
    向Feishu机器人发送消息

    :param webhook_url: Feishu机器人的Webhook URL
    :param message_content: 要发送的消息内容(字典)
    :return: 响应对象
    """
    # 构造请求头,指定内容类型为JSON
    headers = {'Content-Type': 'application/json'}

    # 使用requests库发送POST请求
    try:
        response = requests.post(webhook_url, headers=headers, json=message_content)
        # 检查响应状态码,确保请求成功
        response.raise_for_status()
        #print(f"消息发送成功: {message_content}")
        return response
    except requests.RequestException as e:
        print(f"消息发送失败: {e}")
        return None


def check_clickhouse_status():
    # 执行service命令并获取输出
    result = subprocess.run(['service', 'clickhouse-server', 'status'], stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE, universal_newlines=True)

    # 如果结果中没有'active (running)'字样,则认为进程已停止
    if 'running' not in result.stdout:
        return False
    return True


def restart_clickhouse_server():
    # 定义重启ClickHouse的命令
    command = ['service', 'clickhouse-server', 'restart']

    # 使用subprocess.run执行命令
    # 注意:这里使用了check=True,如果命令执行失败会抛出CalledProcessError异常
    try:
        result = subprocess.run(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                universal_newlines=True)

        # 如果需要,可以打印命令的输出
        #print(f"Restart command output:\n{result.stdout}")
        send_alert("clickhouse重启结果")
        send_alert(result.stdout)
        # 通常情况下,重启命令没有输出,或者输出只包含状态信息
        # 这里只是示例,你可以根据实际情况处理输出

    except subprocess.CalledProcessError as e:
        # 如果命令执行失败,打印错误信息
        print(f"Error restarting ClickHouse server: {e}")
        print(f"Error output:\n{e.stderr}")
        send_alert("clickhouse重启报错")
        send_alert(e.stderr)


def monitor_clickhouse():
    global limit
    limitTime = None
    # 600s发送一次
    delay_seconds = 600
    while True:
        # if limitTime is None:
        #     limit = False
        # else:
        #     #
        #     seconds = time.time() - limitTime
        #     print(f"发送告警delay_seconds:{seconds}")
        #     if limit:
        #         if seconds >= delay_seconds:
        #             print(f"发送告警已接触限制delay_seconds:{seconds}")
        #             limit = False
        #         else:
        #             print(f"发送告警未接触限制delay_seconds:{seconds}")
        #
        #     print(f"发送告警limit:{limit}")

        try:
            if not check_clickhouse_status():
                send_alert("clickhouse进程死亡,将自动重启clickhouse")
                # 重启clickhouse
                restart_clickhouse_server()
                time.sleep(30)  # 休眠5秒
                # 重新监控检查
                if not check_clickhouse_status():
                    send_alert("clickhouse重启失败,将于1分钟后重试")
                    time.sleep(60)  # 休眠5秒

                else:
                    send_alert("clickhouse重启成功,请及时关注数据是否正常")
        except Exception as e:
            send_alert("clickhouse监控报错,监控即将停止")
            break

        # 休眠一段时间再检查
        print("ClickHouse server is health")
        time.sleep(5)  # 休眠5秒


def checkParam(argv):
    # 设置默认值
    # 检查是否提供了至少一个参数(除了脚本名本身)
    global env
    if len(argv) > 1:
        # 检查参数是否为空字符串
        if argv[1] != '':
            env = argv[1]
    print(f"环境为: {env}")


if __name__ == '__main__':
    checkParam(sys.argv)
    monitor_clickhouse()



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值