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
一個通用的agent框架,提供編程接口,並內置通用的功能。
3. 主要功能
1) 自動上報心跳
2) 支持以域名方式指定center或者IP列表方式指定center
3) 與center斷開後自動重連接
4) 支持多種重連接center策略,如輪詢方式
5) 自動上報數據到center
6) 可選多種心跳方式,簡單心跳不附帶數據,富心跳可攜帶系統狀態數據,如CPU使用率、內存使用情況等
7) 提供獲取CPU使用率、內存使用情況和流量等接口
8) 內置配置等CommandProessor,常用需求不用編程直接使用
9) 非單例,單個進程可創建多個agent實例
5. 資源接口
暫略。
暫略。
除宏外,所以內容均位於agent名字空間內。
- 7.1. agent.h
- /***
- * 常量定義
- */
- enum
- {
- REPORT_MAX = 10240 /** 一次report的最大字節數 */
- };
- class IAgent
- {
- public:
- virtual ~IAgent() {}
- virtual void set_center(const std::string& domainname_or_iplist, uint16_t port) = 0;
- /***
- * 上報數據給center,report調用只是將數據存放上報隊列中,由agent異步上報
- * @data 需要上報的數據
- * @data_size 需要上報的數據字節數
- * @timeout_millisecond 超時毫秒數,
- * 當隊列滿時,如果超時毫秒數爲0,則直接返回,數據不會被放入上報隊列中;
- * 當隊列滿時,如果timeout_millisecond不爲0,則等待指定的時長,如果在指定的時長內,
- * 上報隊列一直是滿的,則返回,並且數據不會被放入上報隊列中
- */
- virtual bool report(const char* data, size_t data_size, uint32_t timeout_millisecond=0) = 0;
- virtual bool report(uint32_t timeout_millisecond, const char* format, ...) = 0;
- virtual bool register_command_processor(ICommandProcessor* processor) = 0;
- virtual void deregister_command_processor(ICommandProcessor* processor) = 0;
- };
- /***
- * 日誌器,所以分發器實例共享
- * 如需要記錄日誌,則在調用create之前,應當先設置好日誌器
- */
- extern sys::ILogger* logger;
- /***
- * 用來創建agent實例,注意agent不是單例,允許一個進程內有多個實例
- * @queue_size 上報隊列大小,如果隊列滿,會導致消息丟失或report調用阻塞
- * @connect_timeout_milliseconds 與center連接的超時毫秒數,如果在這個時間內沒有數據上報,
- * 則會自動發送心跳消息,否則不會發送心跳消息
- */
- extern IAgent* create(uint32_t queue_size, uint32_t connect_timeout_milliseconds);
- /** 銷燬一個agent實例 */
- extern void destroy(IAgent* agent);
- 7.2. message.h
- #pragma pack(4) // 網絡消息按4字節對齊
- /***
- * Agent消息頭
- */
- typedef struct TAgentMessageHeader
- {
- NUInt32 size; /** 消息包字節數 */
- NUInt32 command; /** 消息的命令字 */
- }agent_message_header_t;
- /***
- * 簡單的心跳消息,僅一個消息頭
- */
- typedef struct TSimpleHeartbeatMessage
- {
- agent_message_header_t header;
- }simple_heartbeat_message_t;
- /***
- * 上報消息
- */
- typedef struct TReportMessage
- {
- agent_message_header_t header;
- char data[0]; /** 需要上報的內容 */
- }report_message_t;
- #pragma pack()
- 7.3. message_command.h
- /***
- * 上行消息命令字
- */
- typedef enum TUplinkMessageCommand
- {
- U_SIMPLE_HEARTBEAT_MESSAGE = 1, /** 簡單心跳消息 */
- U_REPORT_MESSAGE = 2 /** 上報消息 */
- }uplink_message_command_t;
- /***
- * 下行消息命令字,由ICommandProcessor處理
- */
- typedef enum TDownlinkMessageCommand
- {
- }downlink_message_command_t;
- 7.4. command_processor.h
- /***
- * 消息上下文結構
- * 由於是異步接收消息的,所以需要一個上下文結構來保存最新狀態
- */
- typedef struct TMessageContext
- {
- size_t total_size; /** 消息體的字節數 */
- size_t finished_size; /** 已經收到的消息體字節數 */
- TMessageContext(size_t total_size_, size_t finished_size_)
- :total_size(total_size_)
- ,finished_size(finished_size_)
- {
- }
- }message_context_t;
- class ICommandProcessor
- {
- public:
- virtual ~ICommandProcessor() {}
- /***
- * 返回該CommandProcessor處理的命令字
- */
- virtual uint32_t get_command() const = 0;
- /***
- * 有消息需要處理時的回調函數
- * 請注意消息的接收是異步的,每收到一點消息數據,都會回調on_message
- * 整個消息包接收完成的條件是msg_ctx.total_size和msg_ctx.finished_size+buffer_size兩者相等
- * @buffer 當前收到的消息體數據
- * @buffer_size 當前收到的消息體數據字節數
- * @return 如果消息處理成功,則返回true,否則返回false,當返回false時,會導致連接被斷開進行重連接
- */
- virtual bool on_message(const TMessageContext& msg_ctx, const char* buffer, size_t buffer_size) = 0;
- };
- 8. 編程示例
- // 命令字1的CommandProcessor
- class CCommandProcessor1: public ICommandProcessor
- {
- private:
- virtual uint32_t get_command() const
- {
- return 1;
- }
- virtual bool on_message(const TMessageContext& msg_ctx, const char* buffer, size_t buffer_size)
- {
- fprintf(stdout, "[%zu:%zu] %.*s\n", msg_ctx.total_size, msg_ctx.finished_size, (int)buffer_size, buffer);
- return true;
- }
- };
- // 命令字2的CommandProcessor
- class CCommandProcessor2: public CCommandProcessor1
- {
- private:
- virtual uint32_t get_command() const
- {
- return 2;
- }
- };
- // 命令字3的CommandProcessor
- class CCommandProcessor3: public CCommandProcessor1
- {
- private:
- virtual uint32_t get_command() const
- {
- return 3;
- }
- };
- class CMainHelper: public sys::IMainHelper
- {
- public:
- CMainHelper()
- :_agent(NULL)
- {
- }
- private:
- virtual bool init(int argc, char* argv[])
- {
- uint32_t queue_size = 100;
- uint32_t connect_timeout_milliseconds = 2000;
- _agent = agent::create(queue_size, connect_timeout_milliseconds);
- if (NULL == _agent)
- {
- return false;
- }
- _agent->register_command_processor(&_command_processor1);
- _agent->register_command_processor(&_command_processor2);
- _agent->register_command_processor(&_command_processor3);
- _agent->set_center(ArgsParser::center_ip->get_value(),
- ArgsParser::center_port->get_value());
- std::string report("test");
- while (true)
- {
- sys::CUtil::millisleep(3000);
- _agent->report(report.data(), report.size());
- }
- return true;
- }
- virtual void fini()
- {
- agent::destroy(_agent);
- _agent = NULL;
- }
- virtual int get_exit_signal() const
- {
- return SIGTERM;
- }
- private:
- agent::IAgent* _agent;
- CCommandProcessor1 _command_processor1;
- CCommandProcessor2 _command_processor2;
- CCommandProcessor3 _command_processor3;
- };
- // 入口函數
- extern "C" int main(int argc, char* argv[])
- {
- if (!ArgsParser::parse(argc, argv))
- {
- fprintf(stderr, "Args error: %s.\n", ArgsParser::g_error_message.c_str());
- exit(1);
- }
- CMainHelper main_helper;
- return sys::main_template(&main_helper, argc, argv);
- }