CMDB系统一直使用json 格式作为API接口进行数据的收集和渲染。当数据量比较大时,使用http协议对json数据传输时,传输比较耗时。无意间发现google有一款开源软件protocol buffer,通过测试发现的确性能比json提高不少。

 

  1. protobuf

           Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。           

          Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。

     

  2. protobuf 优点

    > 跨平台、跨语言

    > 向下兼容性好,易于扩展

    > 自动生成解析代码

    > 序列化后占用空间小

    > 特别方便用于RPC和消息存储的场合

  3. RPC通讯模型和ZeroRpc

       RPC通讯模型:

       一种通过网络从远程计算机程序服务,而不需要了解底层网络技术的协议。

       RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。

        wKioL1ODS3-BqTNBAADqwNKnOPo495.jpg

        ZeroRPC:

            ZeroRPC 是基于zeromq、gevent和msgpack 开发的分布式RPC框架zerorpc-python。这个框架简单、易用。

  4. protobuf 安装和配置

I. 下载源码包     wget http://protobuf.googlecode.com/files/protobuf-2.3.0.zip       II.安装软件包     unzip protobuf-2.3.0.zip     cd protobuf-2.3.0     ./configure     make     make install       III. 编写hostinfo.proto 描述文件     package hostinfo;     message HostInfo {         required string factername = 1;         optional string hostname = 2;         optional string serverhardtype = 3;         optional string servertag = 4;         optional string servertype = 5;         optional string gatewayIP = 6;         optional string serverproduct = 7;         optional Ram rams = 8;         repeated cpuinfo cpus = 9;                  message cpuinfo {             optional string cpuCoreNum = 1;             optional string cpuBit = 2;             optional string cpuClockSpeed = 3;             optional string cpupynum = 4;             optional string cpuName = 5;             optional string band = 6;             optional string model = 7;         }                  message Ram {             repeated memory mem = 1;         }                  message memory {             optional string Serial_Number = 1;             optional string Manufacturer = 2;             optional string Speed = 3;             optional string Size = 4;         }     }     VI. 用protoc生成访问代码  protoc hostinfo.proto --python_out=./              生成访问代码如下(hostinfo_pb2.py):# Generated by the protocol buffer compiler.  DO NOT EDIT!from google.protobuf import descriptorfrom google.protobuf import messagefrom google.protobuf import reflectionfrom google.protobuf import descriptor_pb2# @@protoc_insertion_point(imports)DESCRIPTOR = descriptor.FileDescriptor(  name='hostinfo.proto',  package='info',  serialized_pb='\n\x0ehostinfo.proto\x12\x04info\"\xd3\x03\n\x08HostInfo\x12\x10\n\x08hostname\x18\x02 \x01(\t\x12\x16\n\x0eserverhardtype\x18\x03 \x01(\t\x12\x11\n\tservertag\x18\x04 \x01(\t\x12\x12\n\nservertype\x18\x05 \x01(\t\x12\x11\n\tgatewayIP\x18\x06 \x01(\t\x12\x15\n\rserverproduct\x18\x07 \x01(\t\x12 \n\x04rams\x18\x08 \x01(\x0b\x32\x12.info.HostInfo.Ram\x12$\n\x04\x63pus\x18\x01 \x03(\x0b\x32\x16.info.HostInfo.cpuinfo\x1a\x84\x01\n\x07\x63puinfo\x12\x12\n\ncpuCoreNum\x18\x01 \x01(\t\x12\x0e\n\x06\x63puBit\x18\x02 \x01(\t\x12\x15\n\rcpuClockSpeed\x18\x03 \x01(\t\x12\x10\n\x08\x63pupynum\x18\x04 \x01(\t\x12\x0f\n\x07\x63puName\x18\x05 \x01(\t\x12\x0c\n\x04\x62\x61nd\x18\x06 \x01(\t\x12\r\n\x05model\x18\x07 \x01(\t\x1a)\n\x03Ram\x12\"\n\x03mem\x18\x01 \x03(\x0b\x32\x15.info.HostInfo.memory\x1aR\n\x06memory\x12\x15\n\rSerial_Number\x18\x01 \x01(\t\x12\x14\n\x0cManufacturer\x18\x02 \x01(\t\x12\r\n\x05Speed\x18\x03 \x01(\t\x12\x0c\n\x04Size\x18\x04 \x01(\t')_HOSTINFO_CPUINFO = descriptor.Descriptor(  name='cpuinfo',  full_name='info.HostInfo.cpuinfo',  filename=None,  file=DESCRIPTOR,  containing_type=None,  fields=[    descriptor.FieldDescriptor(      name='cpuCoreNum', full_name='info.HostInfo.cpuinfo.cpuCoreNum', index=0,      number=1, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='cpuBit', full_name='info.HostInfo.cpuinfo.cpuBit', index=1,      number=2, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='cpuClockSpeed', full_name='info.HostInfo.cpuinfo.cpuClockSpeed', index=2,      number=3, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='cpupynum', full_name='info.HostInfo.cpuinfo.cpupynum', index=3,      number=4, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='cpuName', full_name='info.HostInfo.cpuinfo.cpuName', index=4,      number=5, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='band', full_name='info.HostInfo.cpuinfo.band', index=5,      number=6, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='model', full_name='info.HostInfo.cpuinfo.model', index=6,      number=7, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),  ],  extensions=[  ],  nested_types=[],  enum_types=[  ],  options=None,  is_extendable=False,  extension_ranges=[],  serialized_start=233,  serialized_end=365,)_HOSTINFO_RAM = descriptor.Descriptor(  name='Ram',  full_name='info.HostInfo.Ram',  filename=None,  file=DESCRIPTOR,  containing_type=None,  fields=[    descriptor.FieldDescriptor(      name='mem', full_name='info.HostInfo.Ram.mem', index=0,      number=1, type=11, cpp_type=10, label=3,      has_default_value=False, default_value=[],      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),  ],  extensions=[  ],  nested_types=[],  enum_types=[  ],  options=None,  is_extendable=False,  extension_ranges=[],  serialized_start=367,  serialized_end=408,)_HOSTINFO_MEMORY = descriptor.Descriptor(  name='memory',  full_name='info.HostInfo.memory',  filename=None,  file=DESCRIPTOR,  containing_type=None,  fields=[    descriptor.FieldDescriptor(      name='Serial_Number', full_name='info.HostInfo.memory.Serial_Number', index=0,      number=1, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='Manufacturer', full_name='info.HostInfo.memory.Manufacturer', index=1,      number=2, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='Speed', full_name='info.HostInfo.memory.Speed', index=2,      number=3, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='Size', full_name='info.HostInfo.memory.Size', index=3,      number=4, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),  ],  extensions=[  ],  nested_types=[],  enum_types=[  ],  options=None,  is_extendable=False,  extension_ranges=[],  serialized_start=410,  serialized_end=492,)_HOSTINFO = descriptor.Descriptor(  name='HostInfo',  full_name='info.HostInfo',  filename=None,  file=DESCRIPTOR,  containing_type=None,  fields=[    descriptor.FieldDescriptor(      name='hostname', full_name='info.HostInfo.hostname', index=0,      number=2, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='serverhardtype', full_name='info.HostInfo.serverhardtype', index=1,      number=3, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='servertag', full_name='info.HostInfo.servertag', index=2,      number=4, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='servertype', full_name='info.HostInfo.servertype', index=3,      number=5, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='gatewayIP', full_name='info.HostInfo.gatewayIP', index=4,      number=6, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='serverproduct', full_name='info.HostInfo.serverproduct', index=5,      number=7, type=9, cpp_type=9, label=1,      has_default_value=False, default_value=unicode("", "utf-8"),      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='rams', full_name='info.HostInfo.rams', index=6,      number=8, type=11, cpp_type=10, label=1,      has_default_value=False, default_value=None,      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),    descriptor.FieldDescriptor(      name='cpus', full_name='info.HostInfo.cpus', index=7,      number=1, type=11, cpp_type=10, label=3,      has_default_value=False, default_value=[],      message_type=None, enum_type=None, containing_type=None,      is_extension=False, extension_scope=None,      options=None),  ],  extensions=[  ],  nested_types=[_HOSTINFO_CPUINFO, _HOSTINFO_RAM, _HOSTINFO_MEMORY, ],  enum_types=[  ],  options=None,  is_extendable=False,  extension_ranges=[],  serialized_start=25,  serialized_end=492,)_HOSTINFO_CPUINFO.containing_type = _HOSTINFO;_HOSTINFO_RAM.fields_by_name['mem'].message_type = _HOSTINFO_MEMORY_HOSTINFO_RAM.containing_type = _HOSTINFO;_HOSTINFO_MEMORY.containing_type = _HOSTINFO;_HOSTINFO.fields_by_name['rams'].message_type = _HOSTINFO_RAM_HOSTINFO.fields_by_name['cpus'].message_type = _HOSTINFO_CPUINFODESCRIPTOR.message_types_by_name['HostInfo'] = _HOSTINFOclass HostInfo(message.Message):  __metaclass__ = reflection.GeneratedProtocolMessageType    class cpuinfo(message.Message):    __metaclass__ = reflection.GeneratedProtocolMessageType    DESCRIPTOR = _HOSTINFO_CPUINFO        # @@protoc_insertion_point(class_scope:info.HostInfo.cpuinfo)    class Ram(message.Message):    __metaclass__ = reflection.GeneratedProtocolMessageType    DESCRIPTOR = _HOSTINFO_RAM        # @@protoc_insertion_point(class_scope:info.HostInfo.Ram)    class memory(message.Message):    __metaclass__ = reflection.GeneratedProtocolMessageType    DESCRIPTOR = _HOSTINFO_MEMORY        # @@protoc_insertion_point(class_scope:info.HostInfo.memory)  DESCRIPTOR = _HOSTINFO    # @@protoc_insertion_point(class_scope:info.HostInfo)  # @@protoc_insertion_point(module_scope)V.编写应用代码(RPC client端)#!/usr/bin/env pythonimport hostinfo_pb2import zerorpcimport syshostinfo = hostinfo_pb2.HostInfo()def ServerInfo(hostinfo):    '''这些信息可以通过脚本进行收集'''    hostinfo.hostname = 'cdn.oss.david.com'    hostinfo.serverhardtype = 'IBM System x3550 M2 -[7946I1M]-'    hostinfo.servertag = '99G0665'    hostinfo.servertype = 'physical'    hostinfo.gatewayIP = '113.207.61.1'    hostinfo.serverproduct = 'IBM'    cpu = hostinfo.cpus.add()    cpu.cpuCoreNum = '1'    cpu.cpuBit = '64'    cpu.cpuClockSpeed = '2.00GHz'    cpu.cpupynum = '1'    cpu.cpuName = 'Intel Xeon'    cpu.band = 'Intel'    cpu.model = 'E5504'    memory = hostinfo.rams.mem.add()    memory.Serial_Number = '5F787C83'    memory.Manufacturer = 'Samsung'    memory.Speed = '800 MHz'    memory.Size = '4096 MB'if __name__ == "__main__":    ServerInfo(hostinfo)    c = zerorpc.Client()    c.connect("tcp://127.0.0.1:4242")            #连接RPC 服务端    print c.info(hostinfo.SerializeToString())    #向服务端发送数据   VI. protobuf 基础    字段约束:       required:必须赋值字段,禁止为空       optional:可选字段,可以为空       repeated:集合,可以填充零到多个对象

5.Zero RPC安装和配置  

I.Zero RPC 安装  yum -y install zeromq  yum install gcc gcc-c++ libuuid-devel python-uuid uuid  wget  http://download.zeromq.org/zeromq-2.1.9.tar.gz     ./configure  make  make installII. 安装gevent   pip install gevent  III. 安装zerorpc   pip install zerorpcVI. 编写ZeroRPC ServerPRC 服务端:#!/usr/bin/env pythonimport zerorpcimport hostinfo_pb2    class HostRpc(object):    def info(self, name):        data = hostinfo_pb2.HostInfo()        data.ParseFromString(name)        print data.hostname        print data.serverhardtype        print data.servertag        print data.gatewayIP        print data.serverproduct        return 'success's = zerorpc.Server(HostRpc())s.bind("tcp://0.0.0.0:4242")s.run()

启动RPC Server:

wKiom1ODUw6z4OCcAAA2LjQUQ9k406.jpg

查看RPC 状态:

wKiom1ODU17SziMWAAByH_Hz7OI764.jpg

客户端向服务端传输数据:

客户端:

wKioL1ODVJLAQlGUAAOHQqwAG_o143.jpg

服务端:

wKiom1ODVEvTVBezAAQdhClJt3o866.jpg

    通过以上服务端的输出信息可以看出,客户端可以成功将信息发送至服务端。这只是为测试效果,可以将传输过来的数据通过Mysqldb写入到数据库。