跳到主要内容

RabbitMQ Java 客户端指标,使用 Micrometer 和 Datadog

·6 分钟阅读

在这篇文章中,我们将介绍 RabbitMQ Java 客户端库如何收集运行时指标,并将它们发送到监控系统,如 JMX 和 Datadog。

RabbitMQ Java 客户端中的 Micrometer

Java 客户端从 4.6.0 和 5.2.0 版本开始提供对 Micrometer 的支持。这带来了什么好处?Micrometer 是一个指标外观:应用程序可以使用 Micrometer API 进行指标收集,并选择将这些指标发送到不同的后端,如 JMX、Prometheus、Netflix Atlas、CloudWatch、Datadog、Graphite、Ganglia 等。接下来,让我们看看 RabbitMQ Java 客户端的用户如何从 Micrometer 中获益。

我们可以从收集 Java 客户端指标开始,并使用 Micrometer 在 JMX 上公开它们

MeterRegistry jmxRegistry = new JmxMeterRegistry(JmxConfig.DEFAULT, Clock.SYSTEM);
ConnectionFactory connectionFactory = new ConnectionFactory();
MicrometerMetricsCollector metricsCollector = new MicrometerMetricsCollector(
jmxRegistry, "rabbitmq.client"
);
connectionFactory.setMetricsCollector(metricsCollector);

Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
String queue = channel.queueDeclare().getQueue();
channel.basicConsume(queue, true, (ctag, msg) -> { }, (ctag) -> { });
executor.submit(() -> {
Random random = new Random();
while (true) {
Thread.sleep(random.nextInt(100));
channel.basicPublish("", queue, null, "".getBytes());
}
});

然后可以在 VisualVM 中检查这些指标

Java Client Metrics on JMX
JMX 上的 Java 客户端指标

与我们在 之前的文章中使用 Dropwizard Metrics 所做的相比,并没有太多新内容。

但是 Micrometer 可以轻松地为与 JVM 进程相关的指标带来价值。我们只需将适当的 MeterBinder 绑定到 JMX meter registry

MeterRegistry jmxRegistry = new JmxMeterRegistry(JmxConfig.DEFAULT, Clock.SYSTEM);
// JVM and system metrics:
new ClassLoaderMetrics().bindTo(jmxRegistry);
new JvmMemoryMetrics().bindTo(jmxRegistry);
new JvmGcMetrics().bindTo(jmxRegistry);
new ProcessorMetrics().bindTo(jmxRegistry);
new JvmThreadMetrics().bindTo(jmxRegistry);
ConnectionFactory connectionFactory = new ConnectionFactory();
MicrometerMetricsCollector metricsCollector = new MicrometerMetricsCollector(
jmxRegistry, "rabbitmq.client"
);
connectionFactory.setMetricsCollector(metricsCollector);

Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
String queue = channel.queueDeclare().getQueue();
channel.basicConsume(queue, true, (ctag, msg) -> { }, (ctag) -> { });
executor.submit(() -> {
Random random = new Random();
while (true) {
Thread.sleep(random.nextInt(100));
channel.basicPublish("", queue, null, "".getBytes());
}
});

然后新的指标就会显示在 JVisualVM 中,有很多指标

Java Client,JVM, and System Metrics on JMX
JMX 上的 Java 客户端、JVM 和系统指标

在实践中,应用程序通常有多个实例同时运行,有时分布在不同的数据中心。我们如何识别在给定数据中心运行的实例,并使监控系统意识到此信息?Micrometer 提供了指标标签:只需将数据中心信息添加到指标收集器即可。我们可以调整我们的示例程序,并迭代数据中心列表来模拟分布式实例。我们使用 dc 标签来表示数据中心信息,并添加一个 host 标签

for (String dc : new String[] {"us", "europe", "asia"}) {
Tags tags = Tags.of("host", hostname, "dc", dc);
MeterRegistry jmxRegistry = new JmxMeterRegistry(JmxConfig.DEFAULT, Clock.SYSTEM);
new ClassLoaderMetrics(tags).bindTo(jmxRegistry);
new JvmMemoryMetrics(tags).bindTo(jmxRegistry);
new JvmGcMetrics(tags).bindTo(jmxRegistry);
new ProcessorMetrics(tags).bindTo(jmxRegistry);
new JvmThreadMetrics(tags).bindTo(jmxRegistry);
ConnectionFactory connectionFactory = new ConnectionFactory();
MicrometerMetricsCollector metricsCollector = new MicrometerMetricsCollector(
jmxRegistry, "rabbitmq.client", tags
);
connectionFactory.setMetricsCollector(metricsCollector);

Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
String queue = channel.queueDeclare().getQueue();
channel.basicConsume(queue, true, (ctag, msg) -> { }, (ctag) -> { });
executor.submit(() -> {
Random random = new Random();
int offset = dc.length() * 10;
while (true) {
Thread.sleep(random.nextInt(100) + offset);
channel.basicPublish("", queue, null, "".getBytes());
}
});
}

让我们看看现在在 VisualVM 中是什么样子

Java Client Metrics for Different Datacenters on JMX
JMX 上不同数据中心的 Java 客户端指标

现在指标列表变得非常长,因为 Micrometer 将标签/键值对集合扁平化,并将它们添加到名称中。这是因为 JMX 是一个分层监控系统,它不支持维度。这使得我们很难作为一个整体来推理我们的指标,跨越我们所有的实例和数据中心。在现实生活中情况会更糟:这里我们在同一个 JVM 进程中模拟应用程序的不同实例,但在实际系统中,我们每个进程都会有一个标签页,更难推理。

幸运的是,Micrometer 利用了维度监控系统。想象一下,我们可以看到不同实例的聚合指标,并深入到特定的数据中心或给定的主机。

Datadog 就是这样一个系统,Micrometer 开箱即用地支持它。我们可以使用 DatadogMeterRegistry 并继续使用 JMX,这要归功于 CompositeMeterRegistry

for (String dc : new String[] {"us", "europe", "asia"}) {
CompositeMeterRegistry compositeMeterRegistry = new CompositeMeterRegistry();
MeterRegistry datadogRegistry = new DatadogMeterRegistry(config, Clock.SYSTEM);
MeterRegistry jmxRegistry = new JmxMeterRegistry(JmxConfig.DEFAULT, Clock.SYSTEM);

Tags tags = Tags.of("host", hostname, "dc", dc);
new ClassLoaderMetrics(tags).bindTo(compositeMeterRegistry);
new JvmMemoryMetrics(tags).bindTo(compositeMeterRegistry);
new JvmGcMetrics(tags).bindTo(compositeMeterRegistry);
new ProcessorMetrics(tags).bindTo(compositeMeterRegistry);
new JvmThreadMetrics(tags).bindTo(compositeMeterRegistry);

compositeMeterRegistry.add(datadogRegistry);
compositeMeterRegistry.add(jmxRegistry);

ConnectionFactory connectionFactory = new ConnectionFactory();
MicrometerMetricsCollector metricsCollector = new MicrometerMetricsCollector(
compositeMeterRegistry, "rabbitmq.client", tags
);
connectionFactory.setMetricsCollector(metricsCollector);

Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
String queue = channel.queueDeclare().getQueue();
channel.basicConsume(queue, true, (ctag, msg) -> { }, (ctag) -> { });
executor.submit(() -> {
Random random = new Random();
int offset = dc.length() * 10;
while (true) {
Thread.sleep(random.nextInt(100) + offset);
channel.basicPublish("", queue, null, "".getBytes());
}
});
}

底层发生了什么?Micrometer 收集指标,并每 10 秒通过 HTTPS 将它们发送到 Datadog 服务。请注意,您需要一个 Datadog API 密钥才能使其工作,它用于 Datadog registry 配置中。主机和指标应该会显示在您的 Datadog Web UI 中,您可以轻松地为您的 RabbitMQ Java 客户端实例构建一个仪表板

RabbitMQ Java Client Metrics Datadog Dashboard
RabbitMQ Java 客户端指标 Datadog 仪表板

很棒,不是吗?

更进一步

在单一级别(例如,特定的库,如 RabbitMQ Java 客户端)收集指标只是深入了解整个面向服务的系统的第一步。

Datadog 还提供 对 RabbitMQ 节点和集群的支持。节点需要安装 Datadog 代理,该代理将连接到 RabbitMQ 管理插件以收集指标。Datadog 工程师撰写了 一系列 博客文章,涵盖了 如何监控 RabbitMQ。对于任何对 RabbitMQ 运维感兴趣的人来说,这是一篇推荐阅读的文章。

回到客户端级别,Spring Boot 是用 Java 编写 RabbitMQ 应用程序的一种流行方式。Micrometer 是支持 Spring Boot 2.0 指标系统的库。RabbitMQ Java 客户端指标收集是 自动配置的,开发人员甚至不需要注册任何 MetricsCollector

在微服务和 IoT 工作负载的世界中,应用程序实例像雨后春笋般涌现,我们希望这能让您更容易了解使用 RabbitMQ 进行消息传递的基于 Java 的应用程序的运行情况,这要归功于这些指标!

源代码

© . All rights reserved.