MOOON-agent系統設計與使用說明

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. 應用場景

 

3. 主要功能

1) 自動上報心跳

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

3) center斷開後自動重連接

4) 支持多種重連接center策略,如輪詢方式

5) 自動上報數據到center

6) 可選多種心跳方式,簡單心跳不附帶數據,富心跳可攜帶系統狀態數據,如CPU使用率、內存使用情況等

7) 提供獲取CPU使用率、內存使用情況和流量等接口

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

9) 非單例,單個進程可創建多個agent實例

4. 系統骨架

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. }  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章