当前位置: 代码迷 >> Web前端 >> [转] 运用JMX访问WebLogic Server MBean(监控应用服务器系列文章五)
  详细解决方案

[转] 运用JMX访问WebLogic Server MBean(监控应用服务器系列文章五)

热度:615   发布时间:2012-07-02 17:46:22.0
[转] 使用JMX访问WebLogic Server MBean(监控应用服务器系列文章五)

前言:最近在做一个监控应用服务器(Tocmat、WebSphere、WebLogic)的项目,目前已小有规模,回头看看,一路走来,也算是磕磕绊绊,遇到过种种问题,走过不少弯路,不过程序员最不怕的就是遇到问题――有什么问题就解决什么问题。为了留下点印记,为后来人留下点经验之谈,助之少走弯路,特意把这些经验整理出来,与大家分享。水平有限,如有疏漏,还望指正?? 如有疑问可以Q我:562116039。

?

这是官方文档,很多朋友刚着手监控WebLogic的项目时,并不一定能找到这篇文章,所以很容易深陷于互联网的知识海洋而迷茫困惑,这也说明了一个哲理――东西多了不一定是好事。特将此文转载于此,结合该系列的其他文章,希望能给您带来帮助。

?

下列部分描述如何从 JMX 客户端访问 WebLogic Server MBean:

?

?


为远程客户端设置类路径

如果 JMX 客户端运行在它自己的 JVM(即,不是 WebLogic Server 实例的 JVM)中,请在该客户端的类路径中包括下列 JAR 文件:

WL_HOME\lib\wljmxclient.jar

其中 WL_HOME 是 WebLogic Server 的安装目录。

此 JAR 包含 BEA 对 HTTP 和 IIOP 协议及其专用 T3 协议的实现。通过 BEA 的实现,JMX 客户端随其连接请求发送登录凭据,而 WebLogic Server 安全框架对这些客户端进行身份验证。只有通过身份验证的客户端才能访问在 WebLogic Server MBean 服务器中注册的 MBean。

注意: 尽管 BEA 建议您使用它对 HTTP 和 IIOP 协议或其专用 T3 协议的实现,但是 JMX 客户端可以使用在标准 JDK 中定义的 IIOP 协议。请参阅仅使用 JDK 类的远程连接。

?

?


建立到 MBean 服务器的远程连接

每个 WebLogic Server 域包括三种类型的 MBean 服务器,其中每一种服务器提供对不同 MBean 层次结构的访问。请参阅 MBean 服务器。

要连接到 WebLogic MBean 服务器,请执行下列操作:

?

  1. 通过构造 javax.management.remote.JMXServiceURL 对象描述 MBean 服务器的地址。
  2. 将下列参数值传递给构造方法(请参阅“J2SE 5.0 API Specification”中的 JMXServiceURL):

    • 作为与 MBean 服务器通信所用协议的下列值之一:
      t3t3shttphttpsiiopiiops
    • 承载 MBean 服务器的 WebLogic Server 实例的监听地址
    • WebLogic Server 实例的监听端口
    • MBean 服务器的绝对 JNDI 名称。JNDI 名称必须以 /jndi/ 开头,且后跟表?4-1 中所述的 JNDI 名称之一。
  3. 构造 javax.management.remote.JMXConnector 对象。此对象包含 JMX 客户端用来连接到 MBean 服务器的方法。
    • weblogic.management.remote 包定义可以用于连接到 WebLogic MBean 服务器的协议。远程 JMX 客户端必须在其类路径上包括此包中的类。请参阅为远程客户端设置类路径。
  4. JMXConnector 的构造方法如下:javax.management.remote.JMXConnectorFactory.
    connector(JMXServiceURL
    serviceURL, Map<String,?> environment)

    将下列参数值传递给构造方法(请参阅“J2SE 5.0 API Specification”中的 JMXConnectorFactory):

    • 在上一步中创建的 JMXServiceURL 对象。
    • 包含下列名值对的散列映射:
      javax.naming.Context.SECURITY_PRINCIPAL, admin-user-name 
      javax.naming.Context.SECURITY_CREDENTIALS, admin-user-password 
      javax.management.remote.JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote" 
      ?
  5. 通过调用 JMXConnector.getMBeanServerConnection() 方法连接到 WebLogic MBean 服务器。
  6. 该方法返回 javax.management.MBeanServerConnection 类型的对象。

    MBeanServerConnection 对象是到 WebLogic MBean 服务器的连接。可以将它用于本地连接和远程连接。请参阅“J2SE 5.0 API Specification”中的 MBeanServerConnection

  7. BEA 建议在客户端完成其工作时,通过调用 JMXConnector.close() 方法关闭到 MBean 服务器的连接。

?

示例:连接到 Domain Runtime MBean Server

请注意有关清单?4-1 中代码的下列信息:

?

  • 类使用全局变量 connectionconnector 来表示到 MBean 服务器的连接。对于每个类实例,应该仅调用一次 initConnection() 方法(它将值分配给 connectionconnector 变量),以建立可以在类内重用的单个连接。
  • initConnection() 方法采用用户名和密码(以及服务器的监听地址和监听端口)作为参数,在实例化类时传递这些参数。BEA 建议使用此方法,因为它阻止代码包含未加密的用户凭据。包含这些参数的 String 对象将由 JVM 的垃圾收集例程破坏并从内存中删除。
  • 类在完成其工作后,调用 JMXConnector.close() 关闭到 MBean 服务器的连接。(请参阅“J2SE 5.0 API Specification”中的 JMXConnector。)
  • 清单?4-1 连接到 Domain Runtime MBean Server
public class MyConnection {
	private static MBeanServerConnection connection;

	private static JMXConnector connector;

	private static final ObjectName service;

	/** 
	 * 实例化与 Domain Runtime MBean Server 的连接。
	 */
	public static void initConnection(String hostname, String portString,
			String username, String password) throws IOException,
			MalformedURLException {
		String protocol = "t3";
		Integer portInteger = Integer.valueOf(portString);
		int port = portInteger.intValue();
		String jndiroot = "/jndi/";
		String mserver = "weblogic.management.mbeanservers.domainruntime";
		JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port,
				jndiroot + mserver);
		Hashtable h = new Hashtable();
		h.put(Context.SECURITY_PRINCIPAL, username);
		h.put(Context.SECURITY_CREDENTIALS, password);
		h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
				"weblogic.management.remote");
		connector = JMXConnectorFactory.connect(serviceURL, h);
		connection = connector.getMBeanServerConnection();
	}

	public static void main(String[] args) throws Exception {
		String hostname = args[0];
		String portString = args[1];
		String username = args[2];
		String password = args[3];
		MyConnection c = new MyConnection();
		initConnection(hostname, portString, username, password); //...
		connector.close(); }
	}
}
?

最佳实践:选择 MBean 服务器

WebLogic Server 域维护三种类型的 MBean 服务器,其中每种类型都完成一个特定的功能。通过支持尝试完成的任务的 MBean 服务器访问 MBean:

  • 要修改域的配置,请使用 Edit MBean Server。
  • 要监视对配置 MBean 的待定层次结构的更改,请使用 Edit MBean Server。
  • 要仅监视活动的配置 MBean(而不监视运行时 MBean),请使用 Runtime MBean Server。
  • 通过 Runtime MBean Server 进行监视需要的内存和网络流量,比通过 Domain Runtime MBean Server 进行监视的小。(WebLogic Server 在客户端请求连接到它时才初始化 Domain Runtime MBean Server。)

    在大多数情况下,域中的所有服务器实例具有一组相同的配置数据,因此不管在管理服务器上还是在受管服务器监视 Runtime MBean Server 都无关紧要。但是,如果所做的更改使服务器在重新启动后才能继续工作,则该服务器将不再接受任何更改,这样其配置数据可能会过时。在这种情况下,监视此服务器的 Runtime MBean Server 仅指示特定服务器实例的配置。要了解更改 WebLogic Server 域并激活更改的过程,请参阅“了解域配置”中的管理配置更改

  • 如果客户端为多个服务器监视运行时 MBean,或者如果客户端运行在单独的 JVM 中,BEA 建议您连接到管理服务器上的 Domain Runtime MBean Server,而不是分别连接到域中每个服务器实例上的每个 Runtime MBean Server。
  • 如果您向 Domain Runtime MBean Server 中的 MBean 注册 JMX 监听器和筛选器,则 JMX 筛选器与它所监视的 MBean 运行在同一个 JVM 中。例如,如果向受管服务器上的 MBean 注册筛选器,则该筛选器运行在受管服务器上,并仅将满足筛选条件的消息转发到监听器。

    通常,使用 Domain Runtime MBean Server 的代码更易于维护且更安全,其原因如下:

    • 代码只需构造单个 URL 即可连接到管理服务器上的 Domain Runtime MBean Server。此后,代码可以查找所有服务器实例的值,(可选)并且可以筛选结果。
    • 如果代码使用 Runtime MBean Server 读取多个服务器实例上的 MBean 值,则它必须为每个服务器实例(都具有唯一的监听地址/监听端口组合)构造一个 URL。
    • 可以通过管理服务器的受保护管理端口路由 WebLogic Server 域中的所有管理流量,还可以使用防火墙阻止从防火墙外部连接到受管服务器的管理端口。
    • 通过 Domain Runtime MBean Server 定向所有 JMX 请求时,由于网络滞后和内存使用的增加而导致性能稍微下降。直接连接到每个受管服务器的 Runtime MBean Server 读取 MBean 值,可消除 Domain Runtime MBean Server 为了从受管服务器检索值而建立的网络跃点。但是,对于大多数网络拓扑和性能要求,Domain Runtime MBean Server 启用的简化代码维护和增强安全性更为可取。

      图 4-1 Domain Runtime MBean Server 与 Runtime MBean Server



      ?

      ?

      仅使用 JDK 类的远程连接

      BEA 建议您使用 WebLogic Server 类从远程 JMX 客户端进行连接。但是,远程 JMX 客户端可能仅使用 JDK 中的类连接到 WebLogic Server JMX 代理。为此,请执行下列操作:

      1. 为承载 MBean 的 WebLogic Server 实例启用 IIOP 协议。将默认 IIOP 用户配置为具有管理员权限的 WebLogic Server 用户。
      2. 请参阅“管理控制台联机帮助”中的启用和配置 IIOP

      3. 在 JMX 客户端中,按如下所示构造 javax.management.JMXConnector 对象:
        String hostname = "WLS-host" 
        int port = WLS-port String protocol = "rmi"; 
        String jndiroot= new String("/jndi/iiop://" + hostname + ":" + port + "/"); 
        String mserver = "MBean-server-JNDI-name"; 
        JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port, jndiroot + mserver); 
        Hashtable h = new Hashtable(); 
        h.put(Context.SECURITY_PRINCIPAL, username); 
        h.put(Context.SECURITY_CREDENTIALS, password); 
        connector = JMXConnectorFactory.connect(serviceURL, h); 
        ?
      4. 其中 WLS-hostWLS-port 是 WebLogic Server 实例的监听地址和监听端口,MBean-server-JNDI-name 是表?4-1 中列出的值之一。

      ?

      请注意,您创建的散列表不包括协议包的名称。通过将此值保留为 null,JMX 客户端使用来自 com.sun.jmx.remote.protocol 包(在 JDK 中)的协议定义。

      ?


      建立到 Runtime MBean Server 的本地连接

      本地客户端可以通过 JNDI 树而不是构造 JMXServiceURL 对象,访问 WebLogic Server 实例的 Runtime MBean Server。只有 Runtime MBean Server 在 JNDI 树中注册自身。

      从 JNDI 进行访问时,Runtime MBean Server 返回其 javax.management.MBeanServer 接口。此接口包含 MBeanServerConnection 接口中的所有方法以及诸如 registerMBean()(本地进程可以使用它注册自定义 MBean)之类的其他方法。(请参阅“J2SE 5.0 API Specification”中的 MBeanServer。)

      如果 JMX 客户端的类位于企业应用程序的顶层(即,如果它们是从应用程序的 APP-INF 目录部署的),则 Runtime MBean Server 的 JNDI 名称是:
      java:comp/env/jmx/runtime

      如果 JMX 客户端的类位于 J2EE 模块(如 EJB 或 Web 应用程序)中,则 Runtime MBeanServer 的 JNDI 名称是:
      java:comp/jmx/runtime

      例如:

    InitialContext ctx = new InitialContext(); 
    server = (MBeanServer)ctx.lookup("java:comp/jmx/runtime"); 

    ??

    ?


    在 MBean 层次结构中导航

    WebLogic Server 用一种层次数据模型来组织自己的 MBean。(请参阅 WebLogic Server MBean 数据模型。)在此模型中,所有父 MBean 都包括包含其子级的对象名的特性。在标准 JMX API 中使用子级的对象名,可获取或设置子 MBean 的特性值或者调用其方法。

    要在 WebLogic Server MBean 层次结构中导航,请执行下列操作:

    1. 启动到 MBean 服务器的连接。
    2. 请参阅上一部分:建立到 MBean 服务器的远程连接。

      启动连接将返回
      javax.management.MBeanServerConnection 类型的对象。

    3. 通过调用 MBeanServerConnection.getAttribute(ObjectName object-name,
      String
      attribute) 方法,获取 MBean 层次结构根部 MBean 的对象名,其中:
      • object-name 是在 MBean 服务器中注册的服务 MBean 的对象名。(请参阅服务 MBean。)
      • 表?2-3 描述每种类型的 MBean 服务器中可用的服务 MBean 的类型。

      • attribute 是包含根 MBean 的服务 MBean 特性的名称。
    4. 相继调用与下列内容类似的代码:
      ObjectName on =
      MBeanServerConnection
      .getAttribute(object-name, attribute)
      其中:
      • object-name 是 MBean 层次结构中当前节点 (MBean) 的对象名。
      • attribute 是包含子 MBean 的一个或多个实例的当前 MBean 中特性的名称。如果该特性包含多个子级,则将输出分配给对象名数组 ObjectName[]

    要确定某个 MBean 在 MBean 层次结构中的位置,请参阅 WebLogic Server MBean Reference 中对该 MBean 的描述。对于每个 MBean,“WebLogic Server MBean Reference”列出了包含当前 MBean 的工厂方法的父 MBean。对于其工厂方法不是公共方法的 MBean,“WebLogic Server MBean Reference”列出了可以从其访问当前 MBean 的其他 MBean。

    ?


    示例:输出服务器的名称和状态

    清单?4-2 中的代码示例连接到 Domain Runtime MBean Server,并使用 DomainRuntimeServiceMBean 为域中的每个 ServerRuntimeMBean 获取对象名。然后,它检索并输出每个服务器的 ServerRuntimeMBean NameState 特性的值。

    请注意有关清单?4-2 中代码的下列信息:

    • 除了 connectionconnector 全局变量外,类将 WebLogic Server 服务 MBean 的对象名分配给一个全局变量。类内的方法将频繁使用此对象名,它在定义后不需要更改。
    • printServerRuntimes() 方法获取 DomainRuntimeServiceMBean ServerRuntimes 特性的值,该特性包含域中所有 ServerRuntimeMBean 实例的数组。(请参阅“WebLogic Server MBean Reference”中的 DomainRuntimeServiceMBean。)
    • 清单?4-2 示例:输出服务器的名称和状态
    package cn.chenfeng;
    
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.util.Hashtable;
    import javax.management.MBeanServerConnection;
    import javax.management.MalformedObjectNameException;
    import javax.management.ObjectName;
    import javax.management.remote.JMXConnector;
    import javax.management.remote.JMXConnectorFactory;
    import javax.management.remote.JMXServiceURL;
    import javax.naming.Context;
    
    public class PrintServerState {
    	private static MBeanServerConnection connection;
    
    	private static JMXConnector connector;
    
    	private static final ObjectName service;
    
    	// 实例化 DomainRuntimeServiceMBean 对象名 
    	// 这样可以通过类使用此对象名。 
    	static {
    		try {
    			service = new ObjectName(
    					"com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
    		} catch (MalformedObjectNameException e) {
    			throw new AssertionError(e.getMessage());
    		}
    	}
    
    	/**实例化与 Domain Runtime MBean Server的连接 */
    	public static void initConnection(String hostname, String portString,
    			String username, String password) throws IOException,
    			MalformedURLException {
    		String protocol = "t3";
    		Integer portInteger = Integer.valueOf(portString);
    		int port = portInteger.intValue();
    		String jndiroot = "/jndi/";
    		String mserver = "weblogic.management.mbeanservers.domainruntime";
    		JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port,
    				jndiroot + mserver);
    		Hashtable h = new Hashtable();
    		h.put(Context.SECURITY_PRINCIPAL, username);
    		h.put(Context.SECURITY_CREDENTIALS, password);
    		h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
    				"weblogic.management.remote");
    		connector = JMXConnectorFactory.connect(serviceURL, h);
    		connection = connector.getMBeanServerConnection();
    	}
    
    	/** * 打印一组 ServerRuntimeMBeans。 * 此 MBean 是运行时 MBean 层次的根, * 此域中的每个服务器承载自己的实例。 */
    	public static ObjectName[] getServerRuntimes() throws Exception {
    		return (ObjectName[]) connection
    				.getAttribute(service, "ServerRuntimes");
    	}
    
    	/** * 迭代 ServerRuntimeMBean,获取名称和状态 */
    	public void printNameAndState() throws Exception {
    		ObjectName[] serverRT = getServerRuntimes();
    		System.out.println("got server runtimes");
    		int length = (int) serverRT.length;
    		for (int i = 0; i < length; i++) {
    			String name = (String) connection.getAttribute(serverRT[i], "Name");
    			String state = (String) connection.getAttribute(serverRT[i],
    					"State");
    			System.out.println("Server name: " + name + ".Server state: "
    					+ state);
    		}
    	}
    
    	public static void main(String[] args) throws Exception {
    		String hostname = args[0];
    		String portString = args[1];
    		String username = args[2];
    		String password = args[3];
    		PrintServerState s = new PrintServerState();
    		initConnection(hostname, portString, username, password);
    		s.printNameAndState();
    		connector.close();
    	}
    }
    ??

    ?


    示例:监视 Servlet

    Web 应用程序中的每个 servlet 提供 ServletRuntimeMBean(包含有关 servlet 的运行时状态的信息)的实例。(请参阅“WebLogic Server MBean Reference”中的 ServletRuntimeMBean。)

    在 WebLogic Server 数据模型中,ServletRuntimeMBean 的路径如下:

    1. Domain Runtime MBean Server(用于域中所有服务器上的所有 servlet)或特定服务器实例上的 Runtime MBean Server。
    2. DomainRuntimeServiceMBeanRuntimeServiceMBeanServerRuntimes 特性。
    3. ServerRuntimeMBeanApplicationRuntimes 特性。
    4. ApplicationRuntimeMBeanComponentRuntimes 特性。
    5. ComponentRuntimes 特性包含许多类型的组件运行时 MBean,其中一种是 WebAppComponentRuntimeMBean。在获取此特性的值时,使用子 MBean 的 Type 特性可以获取特定类型的组件运行时 MBean。

    6. WebAppComponentRuntimeMBeanServletRuntimes 特性。

    清单?4-3 中的代码在上文中所述的层次结构中导航,并获取 ServletRuntimeMBean 特性的值。

    清单?4-3 监视 Servlet

    ?

?

package cn.chenfeng;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.naming.Context;

public class MonitorServlets {
	private static MBeanServerConnection connection;

	private static JMXConnector connector;

	private static final ObjectName service;

	// 实例化 DomainRuntimeServiceMBean 的对象名 
	// 因此可以通过类使用此对象名。 
	static {
		try {
			service = new ObjectName(
					"com.bea:Name=DomainRuntimeService,Type=weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean");
		} catch (MalformedObjectNameException e) {
			throw new AssertionError(e.getMessage());
		}
	}

	/** * 实例化与 Domain Runtime MBean Server 的连接 */
	public static void initConnection(String hostname, String portString,
			String username, String password) throws IOException,
			MalformedURLException {
		String protocol = "t3";
		Integer portInteger = Integer.valueOf(portString);
		int port = portInteger.intValue();
		String jndiroot = "/jndi/";
		String mserver = "weblogic.management.mbeanservers.domainruntime";
		JMXServiceURL serviceURL = new JMXServiceURL(protocol, hostname, port,
				jndiroot + mserver);
		Hashtable h = new Hashtable();
		h.put(Context.SECURITY_PRINCIPAL, username);
		h.put(Context.SECURITY_CREDENTIALS, password);
		h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
				"weblogic.management.remote");
		connector = JMXConnectorFactory.connect(serviceURL, h);
		connection = connector.getMBeanServerConnection();
	}

	/** * 获取一组 ServerRuntimeMBean */
	public static ObjectName[] getServerRuntimes() throws Exception {
		return (ObjectName[]) connection
				.getAttribute(service, "ServerRuntimes");
	}

	/** * 获取一组 WebApplicationComponentRuntimeMBean */
	public void getServletData() throws Exception {
		ObjectName[] serverRT = getServerRuntimes();
		int length = (int) serverRT.length;
		for (int i = 0; i < length; i++) {
			ObjectName[] appRT = (ObjectName[]) connection.getAttribute(
					serverRT[i], "ApplicationRuntimes");
			int appLength = (int) appRT.length;
			for (int x = 0; x < appLength; x++) {
				System.out.println("Application name: "
						+ (String) connection.getAttribute(appRT[x], "Name"));
				ObjectName[] compRT = (ObjectName[]) connection.getAttribute(
						appRT[x], "ComponentRuntimes");
				int compLength = (int) compRT.length;
				for (int y = 0; y < compLength; y++) {
					System.out.println(" Component name: "
							+ (String) connection.getAttribute(compRT[y],
									"Name"));
					String componentType = (String) connection.getAttribute(
							compRT[y], "Type");
					System.out.println(componentType.toString());
					if (componentType.toString().equals(
							"WebAppComponentRuntime")) {
						ObjectName[] servletRTs = (ObjectName[]) connection
								.getAttribute(compRT[y], "Servlets");
						int servletLength = (int) servletRTs.length;
						for (int z = 0; z < servletLength; z++) {
							System.out.println(" Servlet name: "
									+ (String) connection.getAttribute(
											servletRTs[z], "Name"));
							System.out.println(" Servlet context path: "
									+ (String) connection.getAttribute(
											servletRTs[z], "ContextPath"));
							System.out.println(" Invocation Total Count : "
									+ (Object) connection.getAttribute(
											servletRTs[z],
											"InvocationTotalCount"));
						}
					}
				}
			}
		}
	}

	public static void main(String[] args) throws Exception {
		String hostname = args[0];
		String portString = args[1];
		String username = args[2];
		String password = args[3];
		MonitorServlets s = new MonitorServlets();
		initConnection(hostname, portString, username, password);
		s.getServletData();
		connector.close();
	}
}

?

?

?

?

?

?

?

?

?

?

?

  相关解决方案