zabbix sender协议的研究

时间2013-12-22

作者 itnihao

邮箱 itnihao@qq.com

博客 http://www.itnihao.com

如需引用,请注明以上信息,谢谢合作

      阅读本文的前提条件,对zabbix熟悉,对zabbix的trapper监控方式熟悉,对zabbix_sender的命令使用熟悉,当然也得熟悉python(非必要,可以用其他语言实现,用bash也是可以实现的,不过会很麻烦)。所以这篇文章不会教你怎么配置zabbix trapper的监控,而是让你从实现的协议底层去深入了解实现的过程,从而学习如何去扩展zabbix sender,用于自己的程序环境中

121615354.jpg

121617447.jpg

121620500.jpg

121621907.jpg

zabbix_sender的实际例子


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
import struct
import simplejson
class ZabbixSender:
        zbx_header = 'ZBXD'
        zbx_version = 1
        zbx_sender_data = {u'request': u'sender data', u'data': []}
        send_data = ''
        def __init__(self, server_host, server_port = 10051):
                self.server_ip = socket.gethostbyname(server_host)
                self.server_port = server_port
        def AddData(self, host, key, value, clock = None):
                add_data = {u'host': host, u'key': key, u'value': value}
                if clock != None:
                        add_data[u'clock'] = clock
                self.zbx_sender_data['data'].append(add_data)
                return self.zbx_sender_data
        def ClearData(self):
                self.zbx_sender_data['data'] = []
                return self.zbx_sender_data
        def __MakeSendData(self):
                zbx_sender_json = simplejson.dumps(self.zbx_sender_data, separators=(',', ':'), ensure_ascii=False).encode('utf-8')
                json_byte = len(zbx_sender_json)
                self.send_data = struct.pack("<4sBq" + str(json_byte) + "s", self.zbx_header, self.zbx_version, json_byte, zbx_sender_json)
        def Send(self):
                self.__MakeSendData()
                so = socket.socket()
                so.connect((self.server_ip, self.server_port))
                wobj = so.makefile(u'wb')
                wobj.write(self.send_data)
                wobj.close()
                robj = so.makefile(u'rb')
                recv_data = robj.read()
                robj.close()
                so.close()
                tmp_data = struct.unpack("<4sBq" + str(len(recv_data) - struct.calcsize("<4sBq")) + "s", recv_data)
                recv_json = simplejson.loads(tmp_data[3])
                return recv_data
if __name__ == '__main__':
        sender = ZabbixSender(u'127.0.0.1')
        for num in range(0,2):           
                sender.AddData(u'Zabbix server', u'test', u'sent data' + str(num))
        res = sender.Send()
        print sender.send_data
        print res

上面的代码中

sender.AddData(u'Zabbix server', u'test', u'sent data' + str(num))

Zabbix Serverhost

testkey

sent data value

当然,大家应该很想知道以上代码运行的结果吧,看下面

122545107.jpg

   这样就用python写了一个zabbix_sender的程序,以上的代码,只要稍作改变,即可用于我们的运维系统,如果有实际的需要。

主要步骤是和Zabbix server建立socket连接,发送zabbix的数据,注意头部信息的正确性,最后就是发送实际的数据,Zabbix server对数据进行处理响应。

官方文档为https://www.zabbix.org/wiki/Docs/protocols

下面是官方文档中java的例子

               String report = buildJSonString(...);

               writeMessage(stream, report.getBytes());

...

   private String buildJSonString(String host, String item, String value)

   {

       return           "{"

       + "\"request\":\"sender data\",\n"

       + "\"data\":[\n"

       +        "{\n"

       +                "\"host\":\"" + host + "\",\n"

       +                "\"key\":\"" + item + "\",\n"

       +                "\"value\":\"" + value.replace("\\", "\\\\") + "\"}]}\n" ;

   }

   protected void writeMessage(OutputStream out, byte[] data) throws IOException {

       int length = data.length;

       out.write(new byte[] {

               'Z', 'B', 'X', 'D',

               '\1',

               (byte)(length & 0xFF),

               (byte)((length >> 8) & 0x00FF),

               (byte)((length >> 16) & 0x0000FF),

               (byte)((length >> 24) & 0x000000FF),

               '\0','\0','\0','\0'});

       out.write(data);

   }


   能自己写zabbix sender有什么好处,当然就是可以用自己的程序来发送数据给zabbix server,将极大的扩展了zabbix应用的范围和可编程性。