MOOON-agent系统设计与使用说明

易剑 2012/6/16

 

目录

1. 设计目标 1

2. 应用场景 2

3. 主要功能 2

4. 系统骨架 3

5. 资源接口 3

6. 内置CommandProcessor 3

7. 编程接口 3

7.1. agent.h 4

7.2. message.h 5

7.3. message_command.h 5

7.4. command_processor.h 6

8. 编程示例 7

 

1. 设计目标

一个通用的agent框架,提供编程接口,并内置通用的功能。

2. 应用场景

MOOON-agent系统设计与使用说明_第1张图片 

3. 主要功能

1) 自动上报心跳

2) 支持以域名方式指定center或者IP列表方式指定center

3) center断开后自动重连接

4) 支持多种重连接center策略,如轮询方式

5) 自动上报数据到center

6) 可选多种心跳方式,简单心跳不附带数据,富心跳可携带系统状态数据,如CPU使用率、内存使用情况等

7) 提供获取CPU使用率、内存使用情况和流量等接口

8) 内置配置等CommandProessor,常用需求不用编程直接使用

9) 非单例,单个进程可创建多个agent实例

4. 系统骨架

MOOON-agent系统设计与使用说明_第2张图片

5. 资源接口

暂略。

6. 内置CommandProcessor

暂略。

7. 编程接口

除宏外,所以内容均位于agent名字空间内。

 

   
   
   
   
  1. 7.1. agent.h  
  2. /***  
  3.  
  4.   * 常量定义  
  5.  
  6.   */  
  7.  
  8. enum  
  9.  
  10. {  
  11.  
  12. REPORT_MAX = 10240 /** 一次report的最大字节数 */  
  13.  
  14. };  
  15.  
  16.  
  17.  
  18. class IAgent  
  19.  
  20. {  
  21.  
  22. public:  
  23.  
  24.     virtual ~IAgent() {}  
  25.  
  26.     virtual void set_center(const std::string& domainname_or_iplist, uint16_t port) = 0;    
  27.  
  28.  
  29.  
  30.  
  31.     /***  
  32.  
  33.       * 上报数据给center,report调用只是将数据存放上报队列中,由agent异步上报  
  34.  
  35.       * @data 需要上报的数据  
  36.  
  37.       * @data_size 需要上报的数据字节数  
  38.  
  39.       * @timeout_millisecond 超时毫秒数,  
  40.  
  41.       *  当队列满时,如果超时毫秒数为0,则直接返回,数据不会被放入上报队列中;  
  42.  
  43.       *  当队列满时,如果timeout_millisecond不为0,则等待指定的时长,如果在指定的时长内,  
  44.  
  45.       *  上报队列一直是满的,则返回,并且数据不会被放入上报队列中  
  46.  
  47.       */  
  48.  
  49.     virtual bool report(const char* data, size_t data_size, uint32_t timeout_millisecond=0) = 0;  
  50.  
  51.     virtual bool report(uint32_t timeout_millisecond, const char* format, ...) = 0;  
  52.  
  53.  
  54.  
  55.  
  56.     virtual bool register_command_processor(ICommandProcessor* processor) = 0;  
  57.  
  58.     virtual void deregister_command_processor(ICommandProcessor* processor) = 0;  
  59.  
  60. };  
  61.  
  62.  
  63.  
  64. /***  
  65.  
  66.   * 日志器,所以分发器实例共享  
  67.  
  68.   * 如需要记录日志,则在调用create之前,应当先设置好日志器  
  69.  
  70.   */  
  71.  
  72. extern sys::ILogger* logger;  
  73.  
  74.  
  75. /***  
  76.  
  77.   * 用来创建agent实例,注意agent不是单例,允许一个进程内有多个实例  
  78.  
  79.   * @queue_size 上报队列大小,如果队列满,会导致消息丢失或report调用阻塞  
  80.  
  81.   * @connect_timeout_milliseconds 与center连接的超时毫秒数,如果在这个时间内没有数据上报,  
  82.  
  83.   *                               则会自动发送心跳消息,否则不会发送心跳消息  
  84.  
  85.   */  
  86.  
  87. extern IAgent* create(uint32_t queue_size, uint32_t connect_timeout_milliseconds);  
  88.  
  89.  
  90. /** 销毁一个agent实例 */  
  91.  
  92. extern void destroy(IAgent* agent);  
  93.  
  94. 7.2. message.h  
  95. #pragma pack(4) // 网络消息按4字节对齐  
  96.  
  97.  
  98. /***  
  99.  
  100.   * Agent消息头  
  101.  
  102.   */  
  103.  
  104. typedef struct TAgentMessageHeader  
  105.  
  106. {  
  107.  
  108.     NUInt32 size;     /** 消息包字节数 */  
  109.  
  110.     NUInt32 command;  /** 消息的命令字 */  
  111.  
  112. }agent_message_header_t;  
  113.  
  114.  
  115. /***  
  116.  
  117.   * 简单的心跳消息,仅一个消息头  
  118.  
  119.   */  
  120.  
  121. typedef struct TSimpleHeartbeatMessage  
  122.  
  123. {  
  124.  
  125.     agent_message_header_t header;  
  126.  
  127. }simple_heartbeat_message_t;  
  128.  
  129.  
  130. /***  
  131.  
  132.   * 上报消息  
  133.  
  134.   */  
  135.  
  136. typedef struct TReportMessage  
  137.  
  138. {  
  139.  
  140.     agent_message_header_t header;  
  141.  
  142.     char data[0]; /** 需要上报的内容 */  
  143.  
  144. }report_message_t;  
  145.  
  146.  
  147. #pragma pack()  
  148.  
  149. 7.3. message_command.h  
  150. /***  
  151.  
  152.   * 上行消息命令字  
  153.  
  154.   */  
  155.  
  156. typedef enum TUplinkMessageCommand  
  157.  
  158. {  
  159.  
  160.     U_SIMPLE_HEARTBEAT_MESSAGE = 1, /** 简单心跳消息 */  
  161.  
  162.     U_REPORT_MESSAGE           = 2  /** 上报消息 */  
  163.  
  164. }uplink_message_command_t;  
  165.  
  166.  
  167. /***  
  168.  
  169.   * 下行消息命令字,由ICommandProcessor处理  
  170.  
  171.   */  
  172.  
  173. typedef enum TDownlinkMessageCommand  
  174.  
  175. {  
  176.  
  177.  
  178. }downlink_message_command_t;  
  179.  
  180. 7.4. command_processor.h  
  181. /***  
  182.  
  183.   * 消息上下文结构  
  184.  
  185.   * 由于是异步接收消息的,所以需要一个上下文结构来保存最新状态  
  186.  
  187.   */  
  188.  
  189. typedef struct TMessageContext  
  190.  
  191. {  
  192.  
  193.     size_t total_size;   /** 消息体的字节数 */  
  194.  
  195.     size_t finished_size; /** 已经收到的消息体字节数 */  
  196.  
  197.       
  198.  
  199.     TMessageContext(size_t total_size_, size_t finished_size_)  
  200.  
  201.      :total_size(total_size_)  
  202.  
  203.      ,finished_size(finished_size_)  
  204.  
  205.     {  
  206.  
  207.     }  
  208.  
  209. }message_context_t;  
  210.  
  211.  
  212. class ICommandProcessor  
  213.  
  214. {   
  215.  
  216. public:  
  217.  
  218.     virtual ~ICommandProcessor() {}  
  219.  
  220.  
  221.     /***  
  222.  
  223.       * 返回该CommandProcessor处理的命令字  
  224.  
  225.       */  
  226.  
  227.     virtual uint32_t get_command() const = 0;  
  228.  
  229.  
  230.     /***  
  231.  
  232.   * 有消息需要处理时的回调函数  
  233.  
  234.   * 请注意消息的接收是异步的,每收到一点消息数据,都会回调on_message  
  235.  
  236.   * 整个消息包接收完成的条件是msg_ctx.total_size和msg_ctx.finished_size+buffer_size两者相等  
  237.  
  238.   * @buffer 当前收到的消息体数据  
  239.  
  240.   * @buffer_size 当前收到的消息体数据字节数  
  241.  
  242.   * @return 如果消息处理成功,则返回true,否则返回false,当返回false时,会导致连接被断开进行重连接  
  243.  
  244.   */  
  245.  
  246.     virtual bool on_message(const TMessageContext& msg_ctx, const char* buffer, size_t buffer_size) = 0;  
  247.  
  248. };  
  249.  
  250. 8. 编程示例  
  251. // 命令字1的CommandProcessor  
  252.  
  253. class CCommandProcessor1: public ICommandProcessor  
  254.  
  255. {   
  256.  
  257. private:  
  258.  
  259.     virtual uint32_t get_command() const  
  260.  
  261.     {  
  262.  
  263.         return 1;  
  264.  
  265.     }  
  266.  
  267.       
  268.  
  269.     virtual bool on_message(const TMessageContext& msg_ctx, const char* buffer, size_t buffer_size)  
  270.  
  271.     {  
  272.  
  273.         fprintf(stdout, "[%zu:%zu] %.*s\n", msg_ctx.total_size, msg_ctx.finished_size, (int)buffer_size, buffer);  
  274.  
  275.         return true;  
  276.  
  277.     }  
  278.  
  279. };  
  280.  
  281.  
  282. // 命令字2的CommandProcessor  
  283.  
  284. class CCommandProcessor2: public CCommandProcessor1  
  285.  
  286. {  
  287.  
  288. private:  
  289.  
  290.     virtual uint32_t get_command() const  
  291.  
  292.     {  
  293.  
  294.         return 2;  
  295.  
  296.     }  
  297.  
  298. };  
  299.  
  300.  
  301. // 命令字3的CommandProcessor  
  302.  
  303. class CCommandProcessor3: public CCommandProcessor1  
  304.  
  305. {  
  306.  
  307. private:  
  308.  
  309.     virtual uint32_t get_command() const  
  310.  
  311.     {  
  312.  
  313.         return 3;  
  314.  
  315.     }  
  316.  
  317. };  
  318.  
  319.  
  320. class CMainHelper: public sys::IMainHelper  
  321.  
  322. {  
  323.  
  324. public:  
  325.  
  326.     CMainHelper()  
  327.  
  328.      :_agent(NULL)  
  329.  
  330.     {  
  331.  
  332.     }  
  333.  
  334.       
  335.  
  336. private:  
  337.  
  338.     virtual bool init(int argc, char* argv[])  
  339.  
  340.     {  
  341.  
  342.         uint32_t queue_size = 100;  
  343.  
  344.         uint32_t connect_timeout_milliseconds = 2000;  
  345.  
  346.           
  347.  
  348.         _agent = agent::create(queue_size, connect_timeout_milliseconds);  
  349.  
  350.         if (NULL == _agent)  
  351.  
  352.         {  
  353.  
  354.             return false;  
  355.  
  356.         }  
  357.  
  358.           
  359.  
  360.         _agent->register_command_processor(&_command_processor1);  
  361.  
  362.         _agent->register_command_processor(&_command_processor2);  
  363.  
  364.         _agent->register_command_processor(&_command_processor3);  
  365.  
  366.  
  367.         _agent->set_center(ArgsParser::center_ip->get_value(),   
  368.  
  369.                            ArgsParser::center_port->get_value());  
  370.  
  371.  
  372.         std::string report("test");  
  373.  
  374.         while (true)  
  375.  
  376.         {  
  377.  
  378.             sys::CUtil::millisleep(3000);  
  379.  
  380.             _agent->report(report.data(), report.size());  
  381.  
  382.         }  
  383.  
  384.           
  385.  
  386.         return true;  
  387.  
  388.     }  
  389.  
  390.       
  391.  
  392.     virtual void fini()  
  393.  
  394.     {  
  395.  
  396.         agent::destroy(_agent);  
  397.  
  398.         _agent = NULL;  
  399.  
  400.     }  
  401.  
  402.       
  403.  
  404.     virtual int get_exit_signal() const  
  405.  
  406. {  
  407.  
  408. return SIGTERM;  
  409.  
  410. }  
  411.  
  412.  
  413. private:  
  414.  
  415.     agent::IAgent* _agent;  
  416.  
  417.     CCommandProcessor1 _command_processor1;  
  418.  
  419.     CCommandProcessor2 _command_processor2;  
  420.  
  421.     CCommandProcessor3 _command_processor3;  
  422.  
  423. };  
  424.  
  425.  
  426. // 入口函数  
  427.  
  428. extern "C" int main(int argc, char* argv[])  
  429.  
  430. {  
  431.  
  432.     if (!ArgsParser::parse(argc, argv))  
  433.  
  434.     {  
  435.  
  436.         fprintf(stderr, "Args error: %s.\n", ArgsParser::g_error_message.c_str());  
  437.  
  438.         exit(1);  
  439.  
  440.     }  
  441.  
  442.       
  443.  
  444.     CMainHelper main_helper;  
  445.  
  446.     return sys::main_template(&main_helper, argc, argv);  
  447.  
  448. }