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

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

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

易剑 2012/6/16

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名字空间内。

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);

}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏主机笔记

使用windows10自带邮件系统设置显示通知

在初次使用windows10的邮件系统确实很简洁,但是遇到了一个系统收不到通知的问题,只能是开启软件才会看到新邮件,今天就介绍下windows10邮件设置开启横...

26950
来自专栏信安之路

为Nmap添砖加瓦

Nmap作为一款优秀的端口扫描器,被所有渗透测试人员当作工作中必不可少的辅助工具,它不仅支持多种扫描方式,还支持添加漏洞测试脚本,在强大的lua脚本支持下,使得...

9400
来自专栏Youngxj

emlog媒体范修改首页显示文章是否收录

24920
来自专栏别先生

JSP连接mysql数据库的重点

1:用mysql驱动把mysql与tomcat的连接起来。把mysql驱动包(不用解压)放到Tomcat安装目录中lib文件夹下即可。 ? 2:然后在自己的新...

37580
来自专栏云计算教程系列

如何在Ubuntu 16.04上将Redis服务器设置为PHP的会话处理程序

Redis是一个开源键值缓存和存储系统,由于其对多种数据类型(如散列,列表,集合和位图等)的高级支持,也称为数据结构服务器。它还支持群集,使其在高度可用和可扩展...

15830
来自专栏Android干货

Android项目实战(四十八):架构之组件化开发

12130
来自专栏代码GG之家

Scoops android app多主题架构(一)

简要说明 Scoops是一个android应用库,主要解决的是多主题实现方案。通过配置多个R.style.Theme ,代码进行动态设置主题,重启当前界面实现...

269100
来自专栏互动直播问题

互动直播登录提示6012,各种方法无解,寻求帮助

使用https://github.com/zhaoyang21cn/iLiveSDK_Android_LiveDemo     iLiveLogin登录一直提示...

28700
来自专栏黑泽君的专栏

【MyEclipse】我们导入的jar包后, 一般没有关联源码, 需要手动进行关联!推荐这种方式。

12350
来自专栏奇梦博客

运行网站出现Too many open files,CentOS 6.x和CentOS 7.x解决方法 Linux 面板

16030

扫码关注云+社区

领取腾讯云代金券