将数据发送到 Zabbix 服务器或 proxy
zabbix_utils 允许你将监控项值发送到 Zabbix 服务器或 proxy 上的 trapper 监控项(类似于 Zabbix sender)。
你可以发送单个值、多个值,甚至将数据发送到多个 Zabbix 集群。
数据可以通过同步或异步模式发送:
- 在同步模式下,Python 脚本会发送值并在继续执行前等待响应;这适用于简单、顺序且可预测的操作。
- 在异步模式下,脚本发送值后不会等待每个响应,从而允许其他操作并行进行;这对于较慢的请求或大批量数据更高效。
本页中的示例主要聚焦于同步模式,不过 异步模式 采用类似的模式。 更多示例可在 zabbix_utils GitHub 仓库中找到。
导入
要使用 zabbix_utils 发送监控项值,请在脚本中导入 Sender 类:
from zabbix_utils import Sender
如需发送多个值,您也可以导入 ItemValue 类:
from zabbix_utils import Sender, ItemValue
发送单个值
要发送一个监控项值:
- 创建一个
Sender实例,指定 Zabbix 服务器或 proxy 的 IP 地址和端口。 - 使用以下格式在
Sender实例上调用send_value()方法:
sender_instance.send_value('host', 'item.key', 'value', optional_timestamp, optional_nanoseconds)
例如,要向 Linux server 主机上的 service.status trapper 监控项发送 1:
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send_value('Linux server', 'service.status', 1)
使用非默认 IP
如果运行脚本的服务器有多个 IP 地址,您可以为 Sender 指定一个 source_ip,以便在向 Zabbix 服务器或 proxy 发送值时使用:
sender = Sender(
server='127.0.0.1',
port=10051,
source_ip='10.10.7.1'
)
使用超时
您可以为 Sender 设置响应 timeout,以控制脚本在放弃之前应等待 Zabbix 服务器或 proxy 响应的时长:
sender = Sender(
server='127.0.0.1',
port=10051,
timeout=30
)
使用 agent 配置文件
您可以让 zabbix_utils 从本地 Zabbix agent 或 agent 2 配置文件中读取 Server 或 ServerActive 参数。
在这种情况下,创建 Sender 实例时无需指定连接参数:
sender = Sender(
use_config=True,
config_path='/etc/zabbix/zabbix_agent2.conf'
)
如果 ServerActive 包含一个或多个具有多个服务器实例的 Zabbix 集群,Sender 会将数据发送到每个集群中第一个可用的服务器。
如果未设置 ServerActive,则使用 Server 中的地址以及默认端口(10051)。
使用加密
Sender 不包含内置加密支持,但你可以通过使用第三方库创建一个包装器来提供它:
def psk_wrapper(sock, tls):
# ...
# socket 的 TLS PSK 包装器实现
# ...
sender = Sender(
server='127.0.0.1',
port=10051,
socket_wrapper=psk_wrapper
)
单个值的响应
Zabbix 服务器或 proxy 返回的响应会由库进行处理,并作为 TrapperResponse 对象返回:
print(response)
# {"processed": 1, "failed": 0, "total": 1, "time": "0.000123", "chunk": 1}
print(response.processed)
# 1
print(response.failed)
# 0
print(response.total)
# 1
异步模式
异步模式允许你的 Python 脚本在不等待 Zabbix 服务器或 proxy 响应的情况下发送值。 当脚本需要发送大量值,或者某些值发送耗时较长时,这可以提高脚本的效率。
使用异步模式时,与同步模式相比有一些重要区别:
- 导入 Python 的
asyncio模块(你必须先安装所需的依赖项)。 - 导入
AsyncSender,而不是Sender。 - 将代码写在
async函数中。 - 调用
send_value()方法时使用await。
例如,使用异步模式发送单个值:
# 1. 导入 asyncio 以使用异步模式,并从 zabbix_utils 导入 AsyncSender:
import asyncio
from zabbix_utils import AsyncSender
# 2. 定义主 async 函数,所有数据发送操作(必须使用 await)都将在其中执行:
async def main():
sender = AsyncSender(server='127.0.0.1', port=10051)
response = await sender.send_value('Linux server', 'service.status', 1)
# 3. 打印 Zabbix 服务器或 proxy 返回的响应:
print(response)
# 4. 使用 asyncio 的事件循环运行 async main() 函数:
asyncio.run(main())
发送多个值
要发送多个值:
- 准备一个
ItemValue对象数组,每个对象都使用与send_value()方法相同的格式。 - 创建一个
Sender实例,指定 Zabbix 服务器或 proxy 的 IP 地址和端口。 - 在
Sender实例上调用send()方法(而不是send_value()),并指定要发送值的对象数组。
例如,要向不同的主机发送五个值:
items = [
ItemValue('server-de', 'service.status', 'up', 1770887205, 100),
ItemValue('server-fr', 'service.status', 'up', 1770887205, 100),
ItemValue('server-uk', 'service.status', 'up', 1770887205, 100),
ItemValue('server-nl', 'service.status', 'up', 1770887205, 100),
ItemValue('server-pl', 'service.status', 'up', 1770887205, 100),
]
sender = Sender(server='127.0.0.1', port=10051)
response = sender.send(items)
使用自定义块大小
如果你需要发送的值数量超过单个请求中 trapper 监控项可接受的数量,可以将它们拆分为多个块。
默认情况下,块大小为 250 个值。
你可以在创建 Sender 实例时设置 chunk_size 参数来更改它。
例如,要将 5 个值分成 3 个块发送(2-2-1),请将 chunk_size 参数设置为 2:
items = [
ItemValue('server-de', 'service.status', 'up'),
ItemValue('server-fr', 'service.status', 'up'),
ItemValue('server-uk', 'service.status', 'up'),
ItemValue('server-nl', 'service.status', 'up'),
ItemValue('server-pl', 'service.status', 'up'),
]
sender = Sender(server='127.0.0.1', port=10051, chunk_size=2)
response = sender.send(items)
向多个 Zabbix 集群发送值
要向多个 Zabbix 集群发送值:
- 准备一个 Zabbix 集群数组。如果某个集群包含多个节点,则该值将发送到每个集群中第一个可用的节点。
- 创建一个
Sender,并指定您的 Zabbix 集群数组。 - 使用与
send_value()方法相同的格式,在Sender实例上调用send_value()方法。
例如,要向每个集群中第一个可用的节点发送一个值:
zabbix_clusters = [
['zabbix.cluster1.node1', 'zabbix.cluster1.node2:10051'],
['zabbix.cluster2.node1:10051', 'zabbix.cluster2.node2', 'zabbix.cluster2.node3']
]
sender = Sender(clusters=zabbix_clusters)
response = sender.send_value('Linux server', 'service.status', 1)
多个值的响应
默认情况下,Sender 会返回跨所有主机或集群发送值的汇总结果:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
如果您需要更详细的信息,可以使用 response.details 属性查看每个集群和每个分块的结果:
print(response)
# {"processed": 2, "failed": 0, "total": 2, "time": "0.000108", "chunk": 2}
if response.failed == 0:
print(f"Value sent successfully in {response.time}")
else:
print(response.details)
# {
# 127.0.0.1:10051: [
# {
# "processed": 1,
# "failed": 0,
# "total": 1,
# "time": "0.000051",
# "chunk": 1
# }
# ],
# zabbix.example.local:10051: [
# {
# "processed": 1,
# "failed": 0,
# "total": 1,
# "time": "0.000057",
# "chunk": 1
# }
# ]
# }
for node, chunks in response.details.items():
for resp in chunks:
print(f"Processed {resp.processed} of {resp.total} at {node.address}:{node.port}")
# Processed 1 of 1 at 127.0.0.1:10051
# Processed 1 of 1 at zabbix.example.local:10051