系统环境
ZABBIX服务器:centos7,zabbix6.4,jq,zabbix-sender-3.0.5
EMQX服务器:centos7, emqx4.4.3
监控思路
通过 EMQX 的 API 获取实时监控数据(包括统计信息和指标),然后将这些数据发送到 Zabbix 服务器进行监控。具体来说,脚本执行了以下操作:
- 从 EMQX API 获取统计信息(stats)、指标(metrics)和节点信息(nodes)。
- 解析这些 JSON 数据,并提取出所需的监控指标。
- 通过 Zabbix Sender 将提取的指标发送到 Zabbix 服务器。
实施过程
数据获取
脚本使用 curl 命令向 EMQX 服务器的 API 发送请求,获取以下三类数据,当然,也可以自行添加更多的需求指标:
Stats: 包含有关主题、订阅、连接等的统计信息。
Metrics: 包含有关消息传递、连接数、数据包等的详细指标。
Nodes: 包含节点的状态信息,如版本、运行时间、内存使用情况等。
可参考官方接口文档:https://docs.emqx.com/zh/emqx/v4.4/advanced/http-api.html#get-api-v4
请求示例,"$2:$3"是账号密码,$4是EMQX服务器IP
脚本内的命令示例
stats=$(curl --basic -u "$2:$3" -k -s "http://$4:8081/api/v4/stats/")
metrics=$(curl --basic -u "$2:$3" -k -s "http://$4:8081/api/v4/metrics/")
nodes=$(curl --basic -u "$2:$3" -k -s "http://$4:8081/api/v4/nodes/")
手动执行的命令示例
curl --basic -u "admin:password" -k -s "http://192.168.1.1:8081/api/v4/nodes"
数据解析和处理,发送
使用 jq 工具,脚本从获取的 JSON 数据中提取出特定的键值对。这些键值对由 STATS_KEYS、METRICS_KEYS 和 NODE_METRICS_KEYS 数组定义。脚本遍历这些数组,提取相应的值。使用 zabbix_sender 工具将提取的数据发送到 Zabbix 服务器。每个数据项都通过指定的 Zabbix 主机名、键名和数据值进行发送。例如:
例如,处理 stats 数据的代码如下,$key对应相关接口指标也是是监控项的键名,$1是zabbix服务器IP,$out 是从 EMQX API 返回的数据值:
for key in "${STATS_KEYS[@]}"; do
out="$(jq -r --arg arg "$key" '.data[0].stats[$arg]' <<< "$stats")"
zabbix_sender -z 127.0.0.1 -s "$1" -k "emqtt[$key]" -o "$out" > /dev/null 2>&1
done
完整的监控脚本如下
放在zabbix服务器的 /usr/local/zabbix/share/zabbix/externalscripts 路径下,需要赋予执行权限chmod +x 脚本名
以及加到zabbix用户组chown zabbix:zabbix 脚本名
#!/bin/bash
#set -x
# 更新 STATS_KEYS 以匹配 EMQX API 返回的 stats 数据
STATS_KEYS=(
"topics.count"
"topics.max"
"subscriptions.shared.count"
"subscriptions.shared.max"
"subscriptions.count"
"subscriptions.max"
"subscribers.count"
"subscribers.max"
"sessions.count"
"sessions.max"
"routes.count"
"routes.max"
"retained.count"
"retained.max"
"live_connections.count"
"live_connections.max"
"connections.count"
"connections.max"
"channels.count"
"channels.max"
)
# 更新 METRICS_KEYS 以匹配 EMQX API 返回的 metrics 数据
METRICS_KEYS=(
"messages.acked"
"packets.publish.received"
"messages.dropped.no_subscribers"
"packets.publish.sent"
"delivery.dropped.qos0_msg"
"packets.connect.received"
"packets.pubcomp.received"
"delivery.dropped.queue_full"
"session.resumed"
"packets.received"
"packets.unsubscribe.received"
"delivery.dropped"
"messages.retained"
"packets.pubrel.missed"
"packets.pubrec.sent"
"packets.pubrec.received"
"bytes.sent"
"messages.dropped.await_pubrel_timeout"
"packets.auth.sent"
"packets.pubrec.inuse"
"packets.puback.received"
"messages.qos1.sent"
"session.created"
"messages.qos2.sent"
"session.terminated"
"client.connect"
"packets.unsuback.sent"
"packets.puback.missed"
"client.subscribe"
"bytes.received"
"packets.disconnect.sent"
"packets.publish.auth_error"
"packets.pingresp.sent"
"packets.pubrel.sent"
"client.acl.deny"
"session.discarded"
"messages.received"
"packets.subscribe.auth_error"
"packets.publish.error"
"packets.publish.dropped"
"messages.delayed"
"messages.delivered"
"messages.qos2.received"
"client.connack"
"messages.sent"
"packets.pubrel.received"
"client.unsubscribe"
"packets.puback.inuse"
"client.authenticate"
"packets.connack.error"
"client.acl.cache_hit"
"delivery.dropped.expired"
"client.auth.anonymous"
"messages.forward"
"packets.pingreq.received"
"packets.pubrec.missed"
"packets.pubcomp.inuse"
"messages.qos1.received"
"client.check_acl"
"messages.publish"
"packets.publish.inuse"
"packets.unsubscribe.error"
"packets.disconnect.received"
"packets.subscribe.error"
"packets.auth.received"
"packets.connack.sent"
"packets.puback.sent"
"client.disconnected"