您的位置:首页 > 运维架构

RabbitMQ监控(一):使用AMQP模拟检测来确认RabbitMQ是否运行

2017-05-04 14:09 253 查看
#RabbitMQ 监控(一)

  本RabbitMQ监控博文内容均来自于《RabbitMQ实战高效部署分布式消息队列》一书。书籍上的代码是使用Python实现的,我用Java尝试了一下,该系列代码都在我的github上。

  监控RabbitMQ并不只是确保端口5672是开启的并能接收TCP连接而已,对于这样复杂的系统,需要能够模拟AMQP客户端来确保连接之后获取信道、使用REST API来找出所有构成Rabbit的Erlang部件都正常运行,并且它们之间能正确通信的话才能算是一个完整的健康检测程序。
  

##1.为Nagios编写健康检测
  我对监控框架不是很了解,只知道我司使用的是Zabbix,Zabbix也支持多语言、自定义监控脚本等。Nagios健康检测是一个独立的程序,它在运行时监控服务并在程序终止运行时退出代码来指示服务的健康状况。Nagios健康检测可以用任何语言编写,检测程序需要将可读状态打印到STDOUT上,并且返回下列四种整形退出代码之一:

  

  * 0——OK——接收检测的服务工作正常,并且各项指标都处于通过命令行参数设定的阀值之内。

  * 1——WARNING——服务运行处于退化状态(或者说是遇到了问题),但是这个问题并不紧急。

  * 2——CRITICAL——服务关闭了,无响应,并且/或者超过了受监控的临界度量阀值。

  * 3——UNKNOWN——从技术上来讲,这意味着服务的状态或者监控的度量值无法确定。

  在理解Nagios期望从健康检测程序中获得的值之后,首先需要编写一个返回Nagios状态代码的健康检测程序。
###清单1.1 返回Nagios状态代码的健康检测程序

1.状态码枚举 ExitType.java

/**
* 健康检测程序的几种状态
*/
public enum ExitType {

WARN("warning"),

CRITICAL("critical"),

UNKNOWN("unknown"),

OK("ok");

private String value;

ExitType(String value) {
this.value = value;
}

public String getValue() {
return this.value;
}
}

2.返回Nagios状态码 ExitUtil.java

/**
* 接收状态码,并以Nagios状态码退出
*/
public class ExitUtil {

private final static Logger log = LoggerFactory.getLogger(ExitUtil.class);

public static void exit(String type) {
if (type.equalsIgnoreCase("warning")) {
log.info("Status is WARN");
System.exit(1);
} else if (type.equalsIgnoreCase("critical")) {
log.info("Status is CRITICAL");
System.exit(2);
} else if (type.equalsIgnoreCase("unknown")) {
log.info("Status is UNKNOWN");
System.exit(3);
} else if (type.equalsIgnoreCase("ok")) {
log.info("Status is OK");
System.exit(0);
} else {
log.error("Unknown exit type");
System.exit(-1);
}
}
}

##2.使用AMQP模拟检测来确认RabbitMQ是否运行
  不用编写代码,大多数监控系统附带的TCP健康检测程序都能通过TCP连接测试RabbitMQ是否能在端口上响应。虽然这会告诉你RabbitMQ守护进程是否在运行,但却不能知道它是否正常运作。为了能够真正的判断RabbitMQ是否有能力来服务请求,你需要真实地发送AMQP命令,在这里构造一个AMQP ping健康检测,当下列任何条件之一为真时,该检测程序会返回一个critical状态。仅当这些状态检测都为false时,健康检测程序才会返回OK状态。

  * RabbitMQ没有响应TCP连接

  * 当发送AMQP命令时,在接收到响应之前超时了。

  * 当构造AMQP信道时,遇到了协议错误

###清单2.1 模拟AMQP检测RabbitMQ是否运行

1.RabbitMQ配置文件 rabbitmq-cfg.properties

host=127.0.0.1
port=5672
username=guest
password=guest
rmq_url=http://127.0.0.1:15672

2.读取配置文件 RMQConfig.java

public class RMQConfig {

private final String host;

private final int port;

private final String username;

private final String password;

//RabbitMQ REST API URL
private final String rmqUrl;

private RMQConfig() throws IOException {
Properties properties = new Properties();
//读取resources下的properties文件
properties.load(getClass().getClassLoader().getResourceAsStream("rabbitmq-cfg.properties"));
host = properties.getProperty("host");
port = Integer.valueOf(properties.getProperty("port"));
username = properties.getProperty("username");
password = properties.getProperty("password");
rmqUrl = properties.getProperty("rmq_url");
}

public String getHost() {
return host;
}

public int getPort() {
return port;
}

public String getUsername() {
return username;
}

public String getPassword() {
return password;
}

public String getRmqUrl() {
return rmqUrl;
}

public enum Singleton {

INSTANCE;

private RMQConfig rmqConfig;

Singleton() {
try {
rmqConfig = new RMQConfig();
} catch (IOException e) {
e.printStackTrace();
}

}

public RMQConfig getRmqConfig() {
return rmqConfig;
}
}
}

3.创建RabbitMQ连接 ConnectionUtil.java

/**
* 获取RabbitMQ连接
*/
public class ConnectionUtil {

public static Connection getConnection() throws IOException, TimeoutException {
RMQConfig config = RMQConfig.Singleton.INSTANCE.getRmqConfig();
String host = config.getHost();
int port = config.getPort();
String username = config.getUsername();
String password = config.getPassword();
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(host);
factory.setPort(port);
factory.setUsername(username);
factory.setPassword(password);
return factory.newConnection();
}

public static Connection getConnection(String host, int port, String username, String password) throws IOException, TimeoutException {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(host);
factory.setPort(port);
factory.setUsername(username);
factory.setPassword(password);
return factory.newConnection();
}
}

4.检测RabbitMQ状态 AMQPPingCheck.java

/**
* 检测能否创建RabbitMQ连接
*/
public class AMQPPingCheck {

private final static Logger log = LoggerFactory.getLogger(AMQPPingCheck.class);

public static void checkAMQPPing() {
RMQConfig config = RMQConfig.Singleton.INSTANCE.getRmqConfig();
String host = config.getHost();
int port = config.getPort();
String username = config.getUsername();
String password = config.getPassword();
Connection connection = null;
try {
connection = ConnectionUtil.getConnection(host, port, username, password);
} catch (IOException | TimeoutException e) {
log.error("Critical : Could not connect to {}, cause {}", host, e.getMessage());
ExitUtil.exit(ExitType.CRITICAL.getValue());
}
log.info("OK: Connect to {} successful.", host);
ExitUtil.exit(ExitType.OK.getValue());
}
}

5.运行检测程序

[@Test](https://my.oschina.net/azibug)
public void pingCheck() {
AMQPPingCheck.checkAMQPPing();
}

可以看到健康检测程序正常工作:

16:12:57.912 [main] INFO com.lanxiang.rabbitmqmonitor.check.AMQPPingCheck - OK: Connect to 127.0.0.1 successful.

16:12:57.914 [main] INFO com.lanxiang.rabbitmqmonitor.terminate.ExitUtil - Status is OK

##下一章将介绍使用REST API构造一个健康检测程序来进行完整的生产/消费测试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RabbitMQ Java