当前位置:网站首页>漏了监控:Zabbix对Eureka instance状态监控

漏了监控:Zabbix对Eureka instance状态监控

2022-07-06 06:47:00 木讷大叔爱运维

背景

在正式开始介绍监控之前,我们先来了解下我们微服务架构使用的两个组件。

Eureka

Eureka作为Spring Cloud的注册中心,主要提供服务注册与发现的能力。

Eureka 采用 CS(Client/Server,客户端/服务器) 架构,它包括以下两大组件:

  • Eureka Server
    Eureka服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。

  • Eureka Client
    Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。

Apollo

Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

而Spring Cloud配置中心集成git仓库、svn仓库等配置源统一获取系统配置参数,由Spring Cloud Config Client消费。其配置文件必须遵循严格的语法格式,即使多余的空格都会造成Client 无法读取相应的配置参数,一旦出问题很容易被忽视。

基于Spring Cloud配置中心这种缺陷,我们使用Apollo进行了逐步的替换,使运维、开发对于不同环境之间的配置文件管理更加方便。

问题

借助Apollo可以实现配置修改实时生效(热发布),即用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序。

Apollo热发布功能满足了我们在更改配置属性需求时,应用可以实时感知。但在使用过程中,如果Eureka Client 自动更新配置时,进行全量更新,则会导致Eureka Server在心跳周期内的健康检查状态如下:

  • client服务发现状态“UNKNOWN”
  • client后台仍然正常运行,无法向Eureka Server发送正常心跳

由于Eureka Server服务发现状态异常,此时是无法正常对外提供服务的。如果运维不及时检查Eureka管理界面每个client状态时,那么就会差生一起生产事故。

注意:每个client对应一个instance,下面我们统一将其称为instance。

需求

针对以上情况,虽然我们已经对instance接入了健康检查,但由于instance正常运行并没有产生告警,看来我们的监控还是有漏洞,因此我们需要通过Zabbix对Eureka instance状态监控来实现应用监控的全覆盖。。

思路

Eureka Server注册的服务以application维度进行分组,每个application下有多个instance。因此我们借助Zabbix的自动发现,通过Eureka API 可以获取所有的分组信息,而不必每次都手动再次添加监控项。

由于Zabbix监控项是不能重复的,因此我们通过application名/Instance ip地址进行命名,区分不同的instance,这就要求我们的应用不能在一台服务器上部署多个应用,否则会导致监控项重复。

注意: 其实我们可以通过InstanceId作为区分更合理,但是InstanceId的使用往往不规范,如包含ip、主机名等等,由于字符过长可能导致不必要的麻烦。

Eureka API

# 获取Eureka 所有的application
http://192.168.3.123:1180/eureka/apps

# 获取某个application下所有的instance
http://192.168.3.123:1180/eureka/apps/application名/

具体实现

因为需要解析Eureka API返回的数据,所以我们使用python来解析json数据。

instance自动发现

# 执行脚本自动发现application名和Instance ip地址
python eureka-instance.py discovery
{
    "data":[
        {
            "{#APP}":"TEST1",
            "{#HOSTNAME}":"192.168.3.10"
        },
        {
            "{#APP}":"TEST1",
            "{#HOSTNAME}":"192.168.3.11"
        }
    ]
}

通过获取{#APP}{#HOSTNAME},我们就可以组合成对应命名规则的监控项。

# 监控项组合
TEST1/192.168.3.10
TEST1/192.168.3.11

获取监控项状态

经过自动发现后的数据,我们可以进一步获取监控项的状态。

# 1.获取instance 10状态
python eureka-instance.py status TEST1 192.168.3.10
# 执行结果
UP

# 2.获取instance 11状态
python eureka-instance.py status TEST1 192.168.3.11
# 执行结果
UP

根据不同Instance的状态,只要结果非“UP”则进行告警。

最终脚本

#!/usr/local/miniconda/bin/python
#-*- coding:utf-8 -*-
#comment:
#1.zabbix自动发现eureka instance
#2.对instance的状态进行监控告警

import requests
import json
import sys
from copy import deepcopy

# 返回json格式数据,否则返回xml格式数据
headers = {'Accept':'text/html, application/xhtml+xml, application/json;q=0.9, */*;q=0.8'}

def instance_discovery():
    app_list = []
    url="http://192.168.3.123:1180/eureka/apps/" 
    try:
       response=requests.get(url, headers=headers)
       if response.status_code == 200:
           instance_dic = {}
           #for app in response.json()["applications"]["application"][1:2]:
           for app in response.json()["applications"]["application"]:
               for instance in app['instance']:
                   instance_dic['{#APP}'] = instance['app']
                   instance_dic['{#HOSTNAME}'] = instance['hostName']
                   # 深copy
                   app_list.append(deepcopy(instance_dic))
           #print(app_list)
           #json序列化
           discovery_app_info = {"data":app_list}
           print(json.dumps(discovery_app_info, sort_keys=True, indent=4, separators=(',', ':')))
    except Exception as e:
       print(e)

def instance_status():
    if len(sys.argv) == 4:
        try:
            url="http://192.168.3.123:1180/eureka/apps/%s/" % (sys.argv[2])
            response=requests.get(url, headers=headers)
            if response.status_code == 200:
                instance_dic = {}
                for instance in response.json()["application"]["instance"]:
                    if sys.argv[3] == instance["hostName"]:
                        print(instance["status"])
        except Exception as e:
            print(e)
            
    else:
        print("Usage: python eureka-instance.py status app hostName")


if __name__ == '__main__':
    if sys.argv[1] == 'discovery':
        instance_discovery()
    elif sys.argv[1] == 'status':
        instance_status()
    else:
        print("Usage: python eureka-instance.py [discovery]|[status app hostName]")

接入Zabbix

1.配置文件

vim eureka.conf
UserParameter=instance_discovery,/usr/local/miniconda/bin/python /etc/zabbix/monitor_scripts/eureka-instance.py discovery
UserParameter=instance_status[*],/usr/local/miniconda/bin/python /etc/zabbix/monitor_scripts/eureka-instance.py status "$1" "$2"

2.自动发现

在这里插入图片描述

3.监控项配置

在这里插入图片描述

4.告警信息

# 1.状态为DOWN,发生告警
告警主机:中间件_eureka_192.168.3.123
主机IP: 192.168.3.123
主机组: 中间件_eureka
告警时间:2022.06.01 14:58:23
恢复时间:2022.06.01 15:13:24
告警等级:High
告警信息:Eureka/TEST1/192.168.3.10:状态为DOWN
告警项目:instance_status[TEST1,192.168.3.10]
问题详情:
TEST1/192.168.3.10: DOWN

当前状态:
发生告警


# 2.状态为UP,恢复告警
告警主机:中间件_eureka_192.168.3.123
主机IP: 192.168.3.123
主机组: 中间件_eureka
告警时间:2022.06.01 14:58:23
恢复时间:2022.06.01 15:13:24
告警等级:High
告警信息:Eureka/TEST1/192.168.3.10:状态为DOWN
告警项目:instance_status[TEST1,192.168.3.10]
问题详情:
TEST1/192.168.3.10: UP

当前状态:
告警恢复: UP

原网站

版权声明
本文为[木讷大叔爱运维]所创,转载请带上原文链接,感谢
https://blog.csdn.net/yanggd1987/article/details/125609736