如何在Java中通过JMX/Metrics获取Cassandra实时监控指标?求示例
Hey there! Let's walk through everything you need to know about accessing Cassandra's monitoring metrics via JMX—whether you're using command-line tools or building a Java application to collect real-time data. I've included concrete examples to make this straightforward.
First, a quick check: Cassandra enables JMX by default on port 7199. If you're connecting remotely, make sure your cassandra-env.sh (or cassandra-env.ps1 on Windows) has the necessary JMX remote access settings configured. For production, always enable JMX authentication and SSL to avoid unauthorized access.
The easiest way to query Cassandra's JMX metrics from the command line is using jmxterm (a lightweight JMX client). Here's how to use it:
Step 1: Connect to Cassandra's JMX Service
java -jar jmxterm-1.0.2.jar -l service:jmx:rmi:///jndi/rmi://<your-cassandra-host>:7199/jmxrmi
(Replace <your-cassandra-host> with your node's IP or hostname; use localhost for local instances.)
Step 2: Explore Available Metrics
- List all JMX domains:
domains - Focus on Cassandra's core metrics domain:
domain org.apache.cassandra.metrics - View all available MBeans in this domain:
beans
Step 3: Query Specific Metrics
- Get average read request latency:
get -b org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency Mean - Get total write request count:
get -b org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Count Count - Check disk space used by Cassandra:
get -b org.apache.cassandra.metrics:type=Storage,name=UsedSpace Value
Alternative: Use jcmd (Local Instances)
If you're running Cassandra locally, you can use jcmd (included with the JDK) to query metrics without extra tools:
# Replace <cassandra-pid> with your Cassandra process ID jcmd <cassandra-pid> JMX.query org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency
Here's a complete Java example to programmatically connect to Cassandra's JMX endpoint and fetch metrics. No extra dependencies are needed—all classes are part of the standard JDK.
import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import java.util.HashMap; import java.util.Map; public class CassandraJmxReader { public static void main(String[] args) throws Exception { // Configure your Cassandra JMX endpoint String jmxServiceUrl = "service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi"; // Add credentials if JMX authentication is enabled Map<String, Object> jmxEnv = new HashMap<>(); // jmxEnv.put(JMXConnector.CREDENTIALS, new String[]{"your-jmx-username", "your-jmx-password"}); // Establish JMX connection JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(jmxServiceUrl), jmxEnv); MBeanServerConnection connection = connector.getMBeanServerConnection(); // Example 1: Fetch average read latency ObjectName readLatencyMBean = new ObjectName("org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency"); Double avgReadLatency = (Double) connection.getAttribute(readLatencyMBean, "Mean"); System.out.printf("Average Read Latency: %.2f ms%n", avgReadLatency); // Example 2: Fetch total write requests ObjectName writeCountMBean = new ObjectName("org.apache.cassandra.metrics:type=ClientRequest,scope=Write,name=Count"); Long totalWrites = (Long) connection.getAttribute(writeCountMBean, "Count"); System.out.printf("Total Write Requests: %d%n", totalWrites); // Example 3: Fetch cluster load ObjectName clusterLoadMBean = new ObjectName("org.apache.cassandra.metrics:type=Cluster,name=Load"); Double clusterLoad = (Double) connection.getAttribute(clusterLoadMBean, "Value"); System.out.printf("Cluster Load: %.2f GB%n", clusterLoad / (1024 * 1024 * 1024)); // Clean up connection connector.close(); } }
Compile & Run
javac CassandraJmxReader.java java CassandraJmxReader
To collect real-time metrics, you can add a scheduled task to poll JMX at regular intervals. Here's how to modify the Java code to fetch metrics every 5 seconds:
import java.util.Timer; import java.util.TimerTask; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; public class RealTimeCassandraMetrics { public static void main(String[] args) { Timer metricsTimer = new Timer(); // Schedule task to run every 5 seconds (immediate first execution) metricsTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { try { String jmxUrl = "service:jmx:rmi:///jndi/rmi://localhost:7199/jmxrmi"; JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(jmxUrl)); MBeanServerConnection connection = connector.getMBeanServerConnection(); ObjectName readLatencyMBean = new ObjectName("org.apache.cassandra.metrics:type=ClientRequest,scope=Read,name=Latency"); Double avgLatency = (Double) connection.getAttribute(readLatencyMBean, "Mean"); // Print timestamped metric System.out.printf("[%d] Real-Time Read Latency: %.2f ms%n", System.currentTimeMillis(), avgLatency); connector.close(); } catch (Exception e) { System.err.println("Error fetching metrics: " + e.getMessage()); } } }, 0, 5000); // 0ms delay before first run, 5000ms interval } }
- Security: Always enable JMX authentication and SSL in production to prevent unauthorized access. Update
cassandra-env.shwith the necessary JVM flags. - MBean Naming: Cassandra's metrics follow the pattern
org.apache.cassandra.metrics:type=<Category>,scope=<Scope>,name=<MetricName>. Usejmxtermto explore all available MBeans. - Performance: Avoid overly frequent polling (e.g., <1 second intervals) as it can add minor overhead to your Cassandra nodes.
内容的提问来源于stack exchange,提问作者Manish Kumar

