WildFlyからJMXを取得する

WildFlyのJMXをzabbixで取得できなくて、何が原因か探るため検証用コードを作って試してみた。

試した構成

・wildfly-17.0.1.Final
・java11

前提

managementのjboss.bind.address.managementが0.0.0.0となっていること。これで外部からWildFlyのデフォルト9990ポートにアクセス可能。

//wildfly-17.0.1.Final/standalone/configuration/standalone.xml
<interfaces>
    <interface name="management">
        <inet-address value="${jboss.bind.address.management:0.0.0.0}"/>
    </interface>
    <interface name="public">
        <inet-address value="${jboss.bind.address:127.0.0.1}"/>
    </interface>
</interfaces>

WildFlyのJMXを取得するサンプルソース

WildFlyのJMXを取得するためには
wildfly-17.0.1.Final/bin/client/jboss-cli-client.jar
をクラスパスに追加する必要があります。

package mbeantest;

import java.io.IOException;
import java.util.HashMap;

import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.CompositeData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class MbeanTest {
	
	private final static String HOST = "localhost";
	private final static int JMX_PORT = 9990;
	private final static String USER = "";
	private final static String PASSWORD = "";
	
	public static void main(String[] args) throws Exception {
		String urlString = System.getProperty("jmx.service.url",
				"service:jmx:remote+http://" + HOST + ":" + JMX_PORT);
		HashMap<String, String[]> map = new HashMap<>();
		String[] credentials = new String[2];
		credentials[0] = USER;
		credentials[1] = PASSWORD;
		map.put("jmx.remote.credentials", credentials);
		
		JMXServiceURL serviceURL = new JMXServiceURL(urlString);
		JMXConnector jmxConnector= null;
		if( !USER.equals("")) {
			jmxConnector = JMXConnectorFactory.connect(serviceURL, map);
		}else {
			jmxConnector = JMXConnectorFactory.connect(serviceURL);
		}
		
		MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
		
		getMbeanData(connection, "java.lang:type=Memory", "HeapMemoryUsage");
		getMbeanData(connection, "java.lang:name=Eden Space,type=MemoryPool", "Usage");
		getMbeanData(connection, "jboss.as:subsystem=datasources,data-source=ExampleDS", "allowMultipleUsers");
	}

	private static void getMbeanData(MBeanServerConnection connection, String mbeanName, String attributeName) throws MalformedObjectNameException, MBeanException,
			AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException {
		
		System.out.println("[mbeanName:" + mbeanName + "]");
		System.out.println("[attributeName:" + attributeName + "]");
		
		ObjectName mbeanObj = new ObjectName(mbeanName);
		Object attrObj = connection.getAttribute(mbeanObj, attributeName);
		
		if( attrObj instanceof javax.management.openmbean.CompositeDataSupport ) {
			CompositeData cd = (CompositeData) attrObj;
			
			for( String name : cd.getCompositeType().keySet() ) {
				System.out.println( " > " + name + ":" + cd.get(name));
			}			
		}else {
			System.out.println( " > " + attrObj);	
		}

	}
}

色々検証した結果、上記ソースのJMXクライアントとWildFlyが同じサーバ上に存在する場合
WildFlyのユーザ、パスワード設定は不要で、デフォルトポート9990に対しJMX取得が可能でした。

WildFlyにユーザ、パスワードが設定されていようが、設定されていまいが取得可能です。

実行結果

10月 10, 2020 11:32:44 午後 org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 5.0.12.Final
10月 10, 2020 11:32:44 午後 org.xnio.Xnio <clinit>
INFO: XNIO version 3.7.2.Final
10月 10, 2020 11:32:44 午後 org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.7.2.Final
10月 10, 2020 11:32:44 午後 org.jboss.logmanager.JBossLoggerFinder getLogger
ERROR: The LogManager accessed before the "java.util.logging.manager" system property was set to "org.jboss.logmanager.LogManager". Results may be unexpected.
10月 10, 2020 11:32:44 午後 org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 2.3.3.Final
10月 10, 2020 11:32:44 午後 org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.9.1.Final
[mbeanName:java.lang:type=Memory]
[attributeName:HeapMemoryUsage]
 > committed:217743360
 > init:67108864
 > max:518979584
 > used:142836136
[mbeanName:java.lang:name=Eden Space,type=MemoryPool]
[attributeName:Usage]
 > committed:60358656
 > init:17891328
 > max:143130624
 > used:42993920
[mbeanName:jboss.as:subsystem=datasources,data-source=ExampleDS]
[attributeName:allowMultipleUsers]
 > false

JMXクライアントとWildFlyが別サーバにある場合は、WildFlyのセキュリティが影響するのかエラーになります。
そのためWildFlyのユーザ、パス設定が必要です。
ユーザ、パス設定は
wildfly-17.0.1.Final/bin/add-user.sh
で追加可能です。
例としてソース上のUSER、PASSWORDが空白のままの場合

private final static String USER = "";
private final static String PASSWORD = "";

実行結果(USER、PASSWORDが空白のままの場合)

10月 10, 2020 11:37:53 午後 org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 5.0.12.Final
10月 10, 2020 11:37:53 午後 org.xnio.Xnio <clinit>
INFO: XNIO version 3.7.2.Final
10月 10, 2020 11:37:53 午後 org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.7.2.Final
10月 10, 2020 11:37:54 午後 org.jboss.logmanager.JBossLoggerFinder getLogger
ERROR: The LogManager accessed before the "java.util.logging.manager" system property was set to "org.jboss.logmanager.LogManager". Results may be unexpected.
10月 10, 2020 11:37:54 午後 org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 2.3.3.Final
10月 10, 2020 11:37:54 午後 org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.9.1.Final
Exception in thread "main" javax.security.sasl.SaslException: Authentication failed: all available authentication mechanisms failed:
   JBOSS-LOCAL-USER: javax.security.sasl.SaslException: ELY05128: Failed to read challenge file [Caused by java.io.FileNotFoundException: \opt\wildfly-17.0.1.Final\standalone\tmp\auth\local10103359251572860045.challenge (指定されたパスが見つかりません。)]
	at org.jboss.remoting3.remote.ClientConnectionOpenListener.allMechanismsFailed(ClientConnectionOpenListener.java:109)
	at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.handleEvent(ClientConnectionOpenListener.java:446)
	at org.jboss.remoting3.remote.ClientConnectionOpenListener$Capabilities.handleEvent(ClientConnectionOpenListener.java:242)
	at org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
	at org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
	at org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)
	at org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
	at ...asynchronous invocation...(Unknown Source)
	at org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:587)
	at org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:549)
	at org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:537)
	at org.jboss.remotingjmx.RemotingConnector.internalRemotingConnect(RemotingConnector.java:268)
	at org.jboss.remotingjmx.RemotingConnector.internalConnect(RemotingConnector.java:156)
	at org.jboss.remotingjmx.RemotingConnector.connect(RemotingConnector.java:103)
	at java.management/javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:270)
	at java.management/javax.management.remote.JMXConnectorFactory.connect(JMXConnectorFactory.java:229)
	at mbeantest.MbeanTest.main(MbeanTest.java:39)
	Suppressed: javax.security.sasl.SaslException: ELY05128: Failed to read challenge file [Caused by java.io.FileNotFoundException: \opt\wildfly-17.0.1.Final\standalone\tmp\auth\local10103359251572860045.challenge (指定されたパスが見つかりません。)]
		at org.wildfly.security.sasl.localuser.LocalUserClient.evaluateMessage(LocalUserClient.java:108)
		at org.wildfly.security.sasl.util.AbstractSaslParticipant.evaluateMessage(AbstractSaslParticipant.java:219)
		at org.wildfly.security.sasl.util.AbstractSaslClient.evaluateChallenge(AbstractSaslClient.java:98)
		at org.wildfly.security.sasl.util.AbstractDelegatingSaslClient.evaluateChallenge(AbstractDelegatingSaslClient.java:54)
		at org.wildfly.security.sasl.util.PrivilegedSaslClient.lambda$evaluateChallenge$0(PrivilegedSaslClient.java:55)
		at java.base/java.security.AccessController.doPrivileged(Native Method)
		at org.wildfly.security.sasl.util.PrivilegedSaslClient.evaluateChallenge(PrivilegedSaslClient.java:55)
		at org.jboss.remoting3.remote.ClientConnectionOpenListener$Authentication.lambda$handleEvent$0(ClientConnectionOpenListener.java:650)
		at org.jboss.remoting3.EndpointImpl$TrackingExecutor.lambda$execute$0(EndpointImpl.java:975)
		at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
		at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
		at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
		at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
		at java.base/java.lang.Thread.run(Thread.java:834)
	Caused by: java.io.FileNotFoundException: \opt\wildfly-17.0.1.Final\standalone\tmp\auth\local10103359251572860045.challenge (指定されたパスが見つかりません。)
		at java.base/java.io.FileInputStream.open0(Native Method)
		at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
		at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
		at org.wildfly.security.sasl.localuser.LocalUserClient.evaluateMessage(LocalUserClient.java:94)
		... 13 more

SaslException: Authentication failedとなる。
そこでUSER、PASSWORDをWildFlyに設定したものにすると

//環境に合わせて変えること
private final static String USER = "admin";
private final static String PASSWORD = ""wildflypass";

実行結果(USER、PASSWORDを正しいものに設定)

10月 10, 2020 11:44:27 午後 org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version 5.0.12.Final
10月 10, 2020 11:44:27 午後 org.xnio.Xnio <clinit>
INFO: XNIO version 3.7.2.Final
10月 10, 2020 11:44:27 午後 org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.7.2.Final
10月 10, 2020 11:44:27 午後 org.jboss.logmanager.JBossLoggerFinder getLogger
ERROR: The LogManager accessed before the "java.util.logging.manager" system property was set to "org.jboss.logmanager.LogManager". Results may be unexpected.
10月 10, 2020 11:44:28 午後 org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 2.3.3.Final
10月 10, 2020 11:44:28 午後 org.wildfly.security.Version <clinit>
INFO: ELY00001: WildFly Elytron version 1.9.1.Final
[mbeanName:java.lang:type=Memory]
[attributeName:HeapMemoryUsage]
 > committed:102875136
 > init:67108864
 > max:518979584
 > used:45051864
[mbeanName:java.lang:name=Eden Space,type=MemoryPool]
[attributeName:Usage]
 > committed:28770304
 > init:17891328
 > max:143130624
 > used:2419904
[mbeanName:jboss.as:subsystem=datasources,data-source=ExampleDS]
[attributeName:allowMultipleUsers]
 > false

JMXクライアントとWildFlyが別サーバに合ったとしても取得可能です。