前言:最近在做一個監控應用服務器(Tocmat、WebSphere、WebLogic)的項目,目前已小有規模,回頭看看,一路走來,也算是磕磕絆絆,遇到過種種問題,走過不少彎路,不過程序員最不怕的就是遇到問題——有什麼問題就解決什麼問題。爲了留下點印記,爲後來人留下點經驗之談,助之少走彎路,特意把這些經驗整理出來,與大家分享。水平有限,如有疏漏,還望指正
在寫WebLogic監控程序的過程中,可以說是相當坎坷,因爲因爲我要支持監控WebLogic不同版本,而WebLogic不同版本對JMX的支持卻有着不小的區別,在網上也沒有找到完整的解決方案,所以只能自己一點點的摸索,如今終於撥雲見日了,OMG。在此,我們只探討監控WebLogic 8.x的解決方案,其他版本後續跟進,我會整理出一個完整的文章。爲什麼監控WebLogic 8.x要先單獨寫個文章呢——因爲8.x跟新的9.x和10.x不一樣,剛開始入手會遇到很麻煩的問題。如果我入手之前能看到這篇文章,嘿嘿,那就謝天謝地了。
好了,不囉嗦了,我們開始:
首先第一條,要訪問WebLogic Server 8.x的MBeans,必須是在JDK1.4環境下,否則會很麻煩,原因如下:
因爲WebLogic 8.x的weblogic.jar中有自己的javax.management包,而JDK1.5中也有javax.management包(以前版本沒有),運行時會優先調用JDK1.5中javax.management包裏的類,因此產生錯誤。而且weblogic8.x支持JMX 1.0,而JDK1.5支持JMX1.2 。
網上有人說通過System.setProperty("jmx.serial.form", "1.0");這樣的設置可以解決問題,經試驗根本不行。
如果要在JDK5+環境下監控WebLogic Server 8.x,需要寫自己classloader,屏蔽JDK自己的javax.management包,轉而加載weblogic.jar中的javax.management包。
使用JMX訪問WebLogic Server 8.x的MBeans,需要使用的JAR包是weblogic.jar、webservices.jar。可以在%WL_HOME%\server\lib目錄下找到。
如果只加入weblogic.jar包,有些API可以訪問,但是運行MBeanHome->getAllMBeans()方法獲取所有MBean時會拋異常:
- weblogic.rjvm.PeerGoneException: ; nested exception is: weblogic.utils.NestedException: Ljavax/xml/soap/SOAPException; - with nested exception: [java.lang.NoClassDefFoundError: Ljavax/xml/soap/SOAPException;] at weblogic.rjvm.BasicOutboundRequest.sendReceive(BasicOutboundRequest.java:108) at weblogic.rmi.internal.BasicRemoteRef.invoke(BasicRemoteRef.java:164) at weblogic.management.internal.AdminMBeanHomeImpl_815_WLStub.getAllMBeans(Unknown Source) at cn.chenfeng.jmx.weblogic.ListAllMBeans.main(ListAllMBeans.java:27) Caused by: weblogic.utils.NestedException: Ljavax/xml/soap/SOAPException; - with nested exception: [java.lang.NoClassDefFoundError: Ljavax/xml/soap/SOAPException;] at weblogic.rjvm.RJVMImpl.gotExceptionReceiving(RJVMImpl.java:967) at weblogic.rjvm.ConnectionManager.gotExceptionReceiving(ConnectionManager.java:930) at weblogic.rjvm.t3.T3JVMConnection.hasException(T3JVMConnection.java:870) at weblogic.socket.SocketMuxer.deliverExceptionAndCleanup(SocketMuxer.java:588) at weblogic.socket.SocketMuxer.deliverHasException(SocketMuxer.java:544) at weblogic.socket.JavaSocketMuxer.processSockets(JavaSocketMuxer.java:306) at weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:32) at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224) at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183) --------------- nested within: ------------------ weblogic.rmi.extensions.RemoteRuntimeException: Unexpected Exception - with nested exception: [weblogic.rjvm.PeerGoneException: ; nested exception is: weblogic.utils.NestedException: Ljavax/xml/soap/SOAPException; - with nested exception: [java.lang.NoClassDefFoundError: Ljavax/xml/soap/SOAPException;]] at weblogic.management.internal.AdminMBeanHomeImpl_815_WLStub.getAllMBeans(Unknown Source) at cn.chenfeng.jmx.weblogic.ListAllMBeans.main(ListAllMBeans.java:27)
weblogic.rjvm.PeerGoneException: ; nested exception is: weblogic.utils.NestedException: Ljavax/xml/soap/SOAPException; - with nested exception: [java.lang.NoClassDefFoundError: Ljavax/xml/soap/SOAPException;] at weblogic.rjvm.BasicOutboundRequest.sendReceive(BasicOutboundRequest.java:108) at weblogic.rmi.internal.BasicRemoteRef.invoke(BasicRemoteRef.java:164) at weblogic.management.internal.AdminMBeanHomeImpl_815_WLStub.getAllMBeans(Unknown Source) at cn.chenfeng.jmx.weblogic.ListAllMBeans.main(ListAllMBeans.java:27) Caused by: weblogic.utils.NestedException: Ljavax/xml/soap/SOAPException; - with nested exception: [java.lang.NoClassDefFoundError: Ljavax/xml/soap/SOAPException;] at weblogic.rjvm.RJVMImpl.gotExceptionReceiving(RJVMImpl.java:967) at weblogic.rjvm.ConnectionManager.gotExceptionReceiving(ConnectionManager.java:930) at weblogic.rjvm.t3.T3JVMConnection.hasException(T3JVMConnection.java:870) at weblogic.socket.SocketMuxer.deliverExceptionAndCleanup(SocketMuxer.java:588) at weblogic.socket.SocketMuxer.deliverHasException(SocketMuxer.java:544) at weblogic.socket.JavaSocketMuxer.processSockets(JavaSocketMuxer.java:306) at weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:32) at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224) at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183) --------------- nested within: ------------------ weblogic.rmi.extensions.RemoteRuntimeException: Unexpected Exception - with nested exception: [weblogic.rjvm.PeerGoneException: ; nested exception is: weblogic.utils.NestedException: Ljavax/xml/soap/SOAPException; - with nested exception: [java.lang.NoClassDefFoundError: Ljavax/xml/soap/SOAPException;]] at weblogic.management.internal.AdminMBeanHomeImpl_815_WLStub.getAllMBeans(Unknown Source) at cn.chenfeng.jmx.weblogic.ListAllMBeans.main(ListAllMBeans.java:27)
加入webservices.jar包就可以解決這個問題了。
下面展示一下我自己跑的Demo
- package cn.chenfeng.jmx.weblogic;
- import java.util.Hashtable;
- import java.util.Iterator;
- import java.util.Set;
- import javax.management.MBeanServer;
- import javax.management.ObjectName;
- import javax.naming.Context;
- import javax.naming.InitialContext;
- import weblogic.jndi.Environment;
- import weblogic.management.Helper;
- import weblogic.management.MBeanHome;
- import weblogic.management.configuration.DomainMBean;
- import weblogic.management.configuration.ServerMBean;
- import weblogic.management.runtime.RuntimeMBean;
- /**
- * 使用MBeanHome的getMBeansByType和getRuntimeMBean方法獲取MBean
- *
- * @author 陳峯
- *
- */
- public class WebLogicMonitor {
- public static void main(String[] args) {
- WebLogicMonitor monitor = new WebLogicMonitor();
- try {
- monitor.collectData8();
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.println();
- try {
- monitor.collectData8_3();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public void collectData8() throws Exception {
- final String providerUrl = "t3://192.168.1.2:7001";
- final String username = "weblogic";
- final String password = "weblogic";
- MBeanHome home = (MBeanHome) Helper.getAdminMBeanHome(username,
- password, providerUrl);
- System.out.println("Admin MBeanHome --> DomainName : "
- + home.getDomainName());
- /*
- * 獲取MBeanHome的另一個方法,Helper內部就是通過這種方法實現的
- */
- {
- Environment env = new Environment();
- env.setProviderUrl(providerUrl);
- env.setSecurityPrincipal(username);
- env.setSecurityCredentials(password);
- Context ctx = env.getInitialContext();
- MBeanHome localHome = (MBeanHome) ctx
- .lookup(MBeanHome.LOCAL_JNDI_NAME);
- MBeanHome adminHome = (MBeanHome) ctx
- .lookup(MBeanHome.ADMIN_JNDI_NAME);
- System.out.println("Local MBeanHome --> DomainName : "
- + localHome.getDomainName());
- System.out.println("Admin MBeanHome --> DomainName : "
- + adminHome.getDomainName());
- }
- {
- Set mbeans = home.getMBeansByType("ServerRuntime");
- System.out.println("ServerRuntime MBeans : " + mbeans);
- }
- {
- System.out
- .println("\n===============獲取DomainMBean再獲取其他信息==================");
- DomainMBean domainMBean = home.getActiveDomain();
- System.out.println("DomainMBean --> Name : "
- + domainMBean.getName());
- System.out.println("DomainMBean --> ObjectName : "
- + domainMBean.getObjectName());
- int adminPort = domainMBean.getAdministrationPort();
- System.out.println("DomainMBean --> Administration Port : "
- + adminPort);
- String consoleContextPath = domainMBean.getConsoleContextPath();
- System.out.println("DomainMBean --> Console Context Path : "
- + consoleContextPath);
- ServerMBean[] servers = domainMBean.getServers();
- for (int i = 0; i < servers.length; i++) {
- ServerMBean server = servers[i];
- System.out
- .println("DomainMBean --> ServerMBean --> ObjectName : "
- + server.getObjectName());
- }
- }
- /**
- * JDBC連接池,根據Type獲取指定類型的MBeans
- */
- {
- System.out
- .println("\n===============獲取JDBC連接池信息==================");
- Set mbeans = home.getMBeansByType("JDBCConnectionPoolRuntime");
- System.out.println("JDBCConnectionPoolRuntime MBeans : " + mbeans);
- Iterator itt = mbeans.iterator();
- while (itt.hasNext()) {
- RuntimeMBean mbean = (RuntimeMBean) itt.next();
- String name = mbean.getName();
- int count = Integer.parseInt(mbean.getAttribute(
- "ActiveConnectionsCurrentCount").toString());
- System.out.println("【JDBCConnectionPoolRuntime --> " + name
- + " --> ActiveConnectionsCurrentCount】: " + count);
- }
- }
- /**
- * 根據Name和Type獲取指定RuntimeMBean
- */
- {
- System.out
- .println("\n===============根據Name和Type獲取指定RuntimeMBean==================");
- RuntimeMBean mbean = home.getRuntimeMBean("MedRecXAPool-PointBase",
- "JDBCConnectionPoolRuntime");
- System.out.println(mbean.getObjectName());
- }
- }
- public void collectData8_3() throws Exception {
- System.out.println("=============== 獲取MBeanServer ================");
- String url = "t3://192.168.1.2:7001"; // URL of the server instance
- String username = "weblogic";
- String password = "weblogic";
- Hashtable props = new Hashtable();
- props.put(Context.PROVIDER_URL, url);
- props.put(Context.INITIAL_CONTEXT_FACTORY,
- "weblogic.jndi.WLInitialContextFactory");
- props.put(Context.SECURITY_PRINCIPAL, username);
- props.put(Context.SECURITY_CREDENTIALS, password);
- InitialContext ctx = new InitialContext(props);
- MBeanServer mbeanServer = (MBeanServer) ctx
- .lookup("weblogic.management.server");
- System.out.println("MBeanServer:" + mbeanServer);
- Set jdbcMBeans = mbeanServer.queryNames(new ObjectName(
- "*:Type=JDBCConnectionPool,*"), null);
- for (Iterator itt = jdbcMBeans.iterator(); itt.hasNext();) {
- Object jdbcMBean = itt.next();
- System.out.println(jdbcMBean);
- }
- }
- }
package cn.chenfeng.jmx.weblogic;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.naming.Context;
import javax.naming.InitialContext;
import weblogic.jndi.Environment;
import weblogic.management.Helper;
import weblogic.management.MBeanHome;
import weblogic.management.configuration.DomainMBean;
import weblogic.management.configuration.ServerMBean;
import weblogic.management.runtime.RuntimeMBean;
/**
* 使用MBeanHome的getMBeansByType和getRuntimeMBean方法獲取MBean
*
* @author 陳峯
*
*/
public class WebLogicMonitor {
public static void main(String[] args) {
WebLogicMonitor monitor = new WebLogicMonitor();
try {
monitor.collectData8();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println();
try {
monitor.collectData8_3();
} catch (Exception e) {
e.printStackTrace();
}
}
public void collectData8() throws Exception {
final String providerUrl = "t3://192.168.1.2:7001";
final String username = "weblogic";
final String password = "weblogic";
MBeanHome home = (MBeanHome) Helper.getAdminMBeanHome(username,
password, providerUrl);
System.out.println("Admin MBeanHome --> DomainName : "
+ home.getDomainName());
/*
* 獲取MBeanHome的另一個方法,Helper內部就是通過這種方法實現的
*/
{
Environment env = new Environment();
env.setProviderUrl(providerUrl);
env.setSecurityPrincipal(username);
env.setSecurityCredentials(password);
Context ctx = env.getInitialContext();
MBeanHome localHome = (MBeanHome) ctx
.lookup(MBeanHome.LOCAL_JNDI_NAME);
MBeanHome adminHome = (MBeanHome) ctx
.lookup(MBeanHome.ADMIN_JNDI_NAME);
System.out.println("Local MBeanHome --> DomainName : "
+ localHome.getDomainName());
System.out.println("Admin MBeanHome --> DomainName : "
+ adminHome.getDomainName());
}
{
Set mbeans = home.getMBeansByType("ServerRuntime");
System.out.println("ServerRuntime MBeans : " + mbeans);
}
{
System.out
.println("\n===============獲取DomainMBean再獲取其他信息==================");
DomainMBean domainMBean = home.getActiveDomain();
System.out.println("DomainMBean --> Name : "
+ domainMBean.getName());
System.out.println("DomainMBean --> ObjectName : "
+ domainMBean.getObjectName());
int adminPort = domainMBean.getAdministrationPort();
System.out.println("DomainMBean --> Administration Port : "
+ adminPort);
String consoleContextPath = domainMBean.getConsoleContextPath();
System.out.println("DomainMBean --> Console Context Path : "
+ consoleContextPath);
ServerMBean[] servers = domainMBean.getServers();
for (int i = 0; i < servers.length; i++) {
ServerMBean server = servers[i];
System.out
.println("DomainMBean --> ServerMBean --> ObjectName : "
+ server.getObjectName());
}
}
/**
* JDBC連接池,根據Type獲取指定類型的MBeans
*/
{
System.out
.println("\n===============獲取JDBC連接池信息==================");
Set mbeans = home.getMBeansByType("JDBCConnectionPoolRuntime");
System.out.println("JDBCConnectionPoolRuntime MBeans : " + mbeans);
Iterator itt = mbeans.iterator();
while (itt.hasNext()) {
RuntimeMBean mbean = (RuntimeMBean) itt.next();
String name = mbean.getName();
int count = Integer.parseInt(mbean.getAttribute(
"ActiveConnectionsCurrentCount").toString());
System.out.println("【JDBCConnectionPoolRuntime --> " + name
+ " --> ActiveConnectionsCurrentCount】: " + count);
}
}
/**
* 根據Name和Type獲取指定RuntimeMBean
*/
{
System.out
.println("\n===============根據Name和Type獲取指定RuntimeMBean==================");
RuntimeMBean mbean = home.getRuntimeMBean("MedRecXAPool-PointBase",
"JDBCConnectionPoolRuntime");
System.out.println(mbean.getObjectName());
}
}
public void collectData8_3() throws Exception {
System.out.println("=============== 獲取MBeanServer ================");
String url = "t3://192.168.1.2:7001"; // URL of the server instance
String username = "weblogic";
String password = "weblogic";
Hashtable props = new Hashtable();
props.put(Context.PROVIDER_URL, url);
props.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
props.put(Context.SECURITY_PRINCIPAL, username);
props.put(Context.SECURITY_CREDENTIALS, password);
InitialContext ctx = new InitialContext(props);
MBeanServer mbeanServer = (MBeanServer) ctx
.lookup("weblogic.management.server");
System.out.println("MBeanServer:" + mbeanServer);
Set jdbcMBeans = mbeanServer.queryNames(new ObjectName(
"*:Type=JDBCConnectionPool,*"), null);
for (Iterator itt = jdbcMBeans.iterator(); itt.hasNext();) {
Object jdbcMBean = itt.next();
System.out.println(jdbcMBean);
}
}
}