监控
Overview
在本指南中,您可以了解如何在 MongoDB Java 驱动程序中设置和配置监控。
监控是获取运行程序所执行活动的信息,供应用程序或应用程序性能管理库使用的过程。
通过监控 MongoDB Java 驱动程序,您可以了解驱动程序的资源使用情况和性能,并帮助您在设计和调试应用程序时做出明智的决策。
在本指南中,您将了解如何执行这些任务:
本指南介绍如何在代码中使用有关驾驶员活动的信息。 如果您想学习;了解如何在驾驶员中记录事件,请阅读我们的日志记录指南。
监控事件
如需监控事件,必须在 MongoClient
实例上注册监听器。
事件是运行程序时发生的任何操作。驱动程序包括监听驱动程序运行时发生的事件子集的功能。
监听器是在某些事件发生时执行某些操作的类。监听器的 API 定义了其可以响应的事件。
监听器类的每个方法都代表对某个事件的响应。每个方法接收一个参数:代表该方法所响应事件的对象。
MongoDB Java 驱动程序将其定义的事件分为三类:
命令事件
服务器发现和监控事件
连接池事件
以下部分将介绍如何监控每个事件类别。
有关可以监控的事件的完整列表, 请参阅 MongoDB Java 驱动程序的事件包。
命令事件
命令事件是与 MongoDB 数据库命令相关的事件。生成命令事件的数据库命令的一些示例包括 find
、insert
、delete
和 count
。
如需监控命令事件,请编写实现 CommandListener
接口的类,并用 MongoClient
实例注册该类的实例。
有关MongoDB 数据库命令的更多信息,请参阅MongoDB手册中有关数据库命令的条目。
注意
内部命令
此驱动程序不会为其内部调用的命令发布事件。其中包括该驱动程序用于监控群集的数据库命令,以及与连接建立相关的命令(例如初始 hello
命令)。
例子
此示例演示了如何为数据库命令创建计数器。计数器跟踪驱动程序成功执行每个数据库命令的次数,并在每次数据库命令完成时打印此信息。
如需制作计数器,请执行以下操作:
创建具有计数器功能的类,实现
CommandListener
接口。将实现
CommandListener
的新类的实例添加到MongoClientSettings
对象中。用
MongoClientSettings
对象配置MongoClient
实例。
以下代码定义了实现 CommandListener
接口的 CommandCounter
类:
class CommandCounter implements CommandListener { private Map<String, Integer> commands = new HashMap<String, Integer>(); public synchronized void commandSucceeded(final CommandSucceededEvent event) { String commandName = event.getCommandName(); int count = commands.containsKey(commandName) ? commands.get(commandName) : 0; commands.put(commandName, count + 1); System.out.println(commands.toString()); } public void commandFailed(final CommandFailedEvent event) { System.out.println(String.format("Failed execution of command '%s' with id %s", event.getCommandName(), event.getRequestId())); } }
以下代码将 CommandCounter
类的一个实例添加到 MongoClientSettings
对象中,并使用 MongoClientSettings
对象配置 MongoClient
实例。然后,该代码会运行一些数据库命令来测试计数器。
MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(URI) .addCommandListener(new CommandCounter()) .build(); MongoClient mongoClient = MongoClients.create(settings); MongoDatabase database = mongoClient.getDatabase(DATABASE); MongoCollection<Document> collection = database.getCollection(COLLECTION); // Run some commands to test the timer collection.find().first(); collection.find().first(); mongoClient.close();
前面的代码片段生成的输出类似于以下内容:
{find=1} {find=2} {find=2, endSessions=1}
有关本节中提到的类和方法的更多信息,请参阅以下 API 文档:
服务器发现和监控事件
服务器发现与监控 (SDAM) 事件是指与驱动程序连接到的 MongoDB 实例或集群的状态变化相关的事件。
驱动程序定义了 9 个 SDAM 事件。驱动程序将这 9 个事件分给 3 个独立的监听器接口,每个接口监听 9 个事件中的 3 个。以下是 3 个接口及其监听的事件:
ClusterListener
:拓扑结构相关事件ServerListener
:与mongod
或mongos
进程相关的事件ServerMonitorListener
:与心跳有关的事件
如需监控 SDAM 事件类型,请编写实现上述 3 个接口之一的类,然后将该类的实例注册到您的 MongoClient
实例中。
有关驱动程序中每个 SDAM 事件的详细说明,请参阅 MongoDB SDAM 日志记录和监控规范。
例子
此示例展示如何创建监听器类来输出消息,让您了解驱动程序是否可以写入 MongoDB 实例。
以下代码定义了实现 ClusterListener
接口的 IsWritable
类。
class IsWriteable implements ClusterListener { private boolean isWritable; public synchronized void clusterDescriptionChanged(final ClusterDescriptionChangedEvent event) { if (!isWritable) { if (event.getNewDescription().hasWritableServer()) { isWritable = true; System.out.println("Able to write to server"); } } else { if (!event.getNewDescription().hasWritableServer()) { isWritable = false; System.out.println("Unable to write to server"); } } } }
以下代码将 IsWritable
类的实例添加到 MongoClient
对象。然后代码会运行查找操作来测试 IsWritable
类。
IsWriteable clusterListener = new IsWriteable(); MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(URI) .applyToClusterSettings(builder -> builder.addClusterListener(clusterListener)) .build(); MongoClient mongoClient = MongoClients.create(settings); MongoDatabase database = mongoClient.getDatabase(DATABASE); MongoCollection<Document> collection = database.getCollection(COLLECTION); // Run a command to trigger a ClusterDescriptionChangedEvent event collection.find().first();
前面的代码片段生成的输出类似于以下内容:
Able to write to server
有关本节中提到的类和方法的更多信息,请参阅以下 API 文档:
连接池事件
连接池事件是与驱动程序持有的连接池相关的事件。连接池是驱动程序与 MongoDB 实例之间维护的一组开放的 TCP 连接。连接池有助于减少应用程序需要与 MongoDB 实例执行的网络握手次数,还能帮助应用程序更快地运行。
如需监控连接池事件,请编写实现 ConnectionPoolListener
接口的类,然后用 MongoClient
实例注册该类的实例。
例子
此示例展示了如何创建监听器类,在每次从连接池中检出连接时打印一条消息。
以下代码定义了实现 ConnectionPoolListener
接口的 ConnectionPoolLibrarian
类。
class ConnectionPoolLibrarian implements ConnectionPoolListener { public void connectionCheckedOut(final ConnectionCheckedOutEvent event) { System.out.println(String.format("Let me get you the connection with id %s...", event.getConnectionId().getLocalValue())); } public void connectionCheckOutFailed(final ConnectionCheckOutFailedEvent event) { System.out.println("Something went wrong! Failed to checkout connection."); } }
以下代码将 ConnectionPoolLibrarian
类的实例添加到 MongoClient
对象。然后代码会运行数据库命令来测试图书管理员。
ConnectionPoolLibrarian cpListener = new ConnectionPoolLibrarian(); MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(URI) .applyToConnectionPoolSettings(builder -> builder.addConnectionPoolListener(cpListener)) .build(); MongoClient mongoClient = MongoClients.create(settings); MongoDatabase database = mongoClient.getDatabase(DATABASE); MongoCollection<Document> collection = database.getCollection(COLLECTION); // Run a command to trigger connection pool events collection.find().first();
前面的代码片段生成的输出类似于以下内容:
Let me get you the connection with id 21...
有关本节中提到的类和方法的更多信息,请参阅以下 API 文档:
用 JMX 监控连接池事件
您可以使用“Java 管理扩展”(JMX) 监控连接池事件。JMX 提供了监控应用程序和设备的工具。
有关 JMX 的更多信息,请参阅 Oracle JMX 官方文档。
JMX 支持
要启用 JMX 连接池监控,请将 JMXConnectionPoolListener
类的实例添加到 MongoClient
对象。
JMXConnectionPoolListener
类执行以下操作:
为驱动程序维护连接池的每个
mongod
或mongos
进程创建 MXBean 实例。将这些 MXBean 实例注册到平台 MBean 服务器。
在平台 MBean 服务器上注册的 MXBean 具有以下属性:
属性 | 说明 |
---|---|
clusterId | 客户端生成的唯一标识符。当应用程序有多个 MongoClient 实例连接到同一 MongoDB 部署时,该标识符可确保驱动程序生成的每个 MXBean 都有唯一的名称。 |
host | 运行 mongod 或 mongos 进程的计算机的主机名。 |
port | mongod 或 mongos 进程正在侦听的端口。 |
minSize | 连接池的最小大小,包括空闲和正在使用的连接。 |
maxSize | 连接池的最大大小,包括空闲连接和使用中的连接。 |
size | 连接池的当前大小,包括空闲连接和使用中的连接。 |
checkedOutCount | 当前正在使用的连接数。 |
此驱动程序创建的所有 MXBean 实例均位于 "org.mongodb.driver"
域中。
有关本小节所讨论主题的更多信息,请参阅 Oracle 提供的以下资源:
JMX 和 JConsole 示例
本例展示了如何使用 JMX 和 JConsole 监控驱动程序的连接池。JConsole 是 Java 平台自带的与 JMX 兼容的图形界面监控工具。
提示
查阅官方 JMX 与 JConsole 文档
此示例中对 JMX 和 JConsole 的描述只是说明性的,而不是事实来源。有关保证的最新信息,请参阅以下 Oracle 官方资源:
以下代码段将 JMXConnectionPoolListener
添加到 MongoClient
实例。然后代码暂停执行,以便您可以导航到 JConsole 并检查连接池。
JMXConnectionPoolListener connectionPoolListener = new JMXConnectionPoolListener(); MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(URI) .applyToConnectionPoolSettings(builder -> builder.addConnectionPoolListener(connectionPoolListener)) .build(); // Creates a MongoClient instance that enables connection pool event monitoring with the JMX tool MongoClient mongoClient = MongoClients.create(settings); try { System.out.println("Navigate to JConsole to see your connection pools..."); // Pauses the code execution so you can navigate to JConsole and inspect your connection pools Thread.sleep(Long.MAX_VALUE); // Prints exception details if any exceptions occur during the code execution } catch (Exception e) { e.printStackTrace(); }
前面的代码片段生成的输出类似于以下内容:
Navigate to JConsole to see your connection pools...
启动服务器后,使用以下命令在终端中打开 JConsole:
jconsole
打开 JConsole 后,在图形界面中执行以下操作:
选择运行前面示例代码的 Java 进程。
在警告对话框中按 Insecure Connection(不安全连接)。
单击 MBeans 标签页。
检查
"org.mongodb.driver"
域下的连接池事件。
如果您不再希望在 JConsole 中检查连接池,请执行以下操作:
关闭 JConsole 窗口,退出 JConsole
停止运行前面代码片段的 Java 程序
有关 JMX 和 JConsole 的更多信息,请参阅 Oracle 提供的以下资源:
有关JMXConnectionPoolListener
类的更多信息,请参阅 JMXConnectionPoolListener 的 API 文档。
将驱动程序包含在分布式跟踪系统中
如果使用分布式跟踪系统,则可以包含驱动程序的事件数据。分布式跟踪系统是种应用程序,可在请求传播到面向服务架构中的不同服务时对其进行跟踪。
如果在 Spring Cloud 应用程序中使用该驱动程序,请使用 Spring Cloud Sleuth 将 MongoDB 事件数据纳入 Zipkin 分布式跟踪系统。
如果不使用 Spring Cloud 或需要在 Zipkin 以外的分布式跟踪系统中包含驱动程序事件数据,则必须编写命令事件监听器来管理所需分布式跟踪系统的范围。要查看此类监听器的实现,请参阅 Spring Cloud Sleuth 源代码中的 TraceMongoCommandListener 类。
要了解有关 Spring Cloud Sleuth 的更多信息,请参阅 Spring Cloud Sleuth 文档中的入门。
要查看分布式跟踪系统的详细说明,请参阅 Google Research 发布的 Dapper。