10年 Java程序员,硬核人生!勇往直前,永不退缩!

欢迎围观我的git:https://github.com/R1310328554/spring_security_learn 寻找志同道合的有志于研究技术的朋友,关注本人微信公众号: 觉醒的码农,或Q群 165874185

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

很早就开始去了解这个了,不过一直都是皮毛,基本概念明白,具体api几乎一无不知。。。

 

认真看了几篇文章,做了测试,终于有所了解

 

 

参考 入门级别: http://www.cnblogs.com/agou/articles/286871.html http://www.cnblogs.com/allenny/articles/179208.html

 

写得最好的:http://www.cnblogs.com/yaohonv/archive/2012/02/08/jmx.html, 图也很清楚,不过初入门的时候看起来比较吃力, 其中对jmx-rmi有所涉及,不错,可惜实验不通。没地方下载jmxremoting.jar

这个相当不错:http://www.cnblogs.com/zjstar12/archive/2012/06/10/2544387.html

http://www.cnblogs.com/xzh31390080/articles/2231213.html 很精辟简练,不过只能是最后才可以看,初学者看了也白看。。 像我之前那样怎么看都没用。

 

个人理解:

 

关于mbean:

standard MBean,这种类型的MBean最简单: 一个接口,一个实现类即可,不需要任何其他类依赖,但是命名必须遵循一定的规范,例如我们的MBean为Hello,则接口必须为HelloMBean。

假如某个属性只有get方法,则说明这个属性是只读的,get/set都有的话,说明这个属性是可读可写的

 

DynamicMBean 可以动态拓展需要管控的资源,即允许bean里面的属性、方法可变,因此需要实现额外的方法:

http://www.cnblogs.com/zjstar12/archive/2012/06/10/2544387.html

package javax.management; public interface DynamicMBean{     public Object getAttribute( String attribute )throws AttributeNotFoundException, MBeanException,ReflectionException;

    public void setAttribute( Attribute attribute )throws AttributeNotFoundException,InvalidAttributeValueException,MBeanException,ReflectionException;

    public AttributeList getAttributes( String[] attributes );

    public AttributeList setAttributes( AttributeList attributes );

    public Object invoke( String actionName, Object[] params,String[] signature ) throws MBeanException,ReflectionExceptionn

    public MBeanInfo getMBeanInfo(); }

 

openMBean及其他一些未规范的就不说了

 

 

关于jmx客户端都jmx服务端的访问:

1 通过浏览器,jmx client程序启用http协议,这个时候需要一个HTMLAdapter

2 jconsole。  不能访问? 看看: http://www.cnblogs.com/orientsun/archive/2012/07/25/2608525.html

3 程序访问?

a 通过JMXConnector

http://www.cnblogs.com/yaohonv/archive/2012/02/08/jmx.html

b 通过http协议,HTMLAdapter?

 

 

 

一些重要的接口:

 

ManagementFactory 专门生产MBeanServer 

MBeanServer  一般就是MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

这个很重要,主要就是通过它来管理mbean的,主要方法有:registerMBean,unRegisterMBean,addNotificationListenerremoveNotificationListener

 createMBean/queryMBean

get/setAttributes

instantiate 不知道干什么的。。。

   

JMXServiceURL 创建ConnectorServer需要用到,

 RMIConnectorServer  -> ConnectorServer

JMXConnector

 

 

待续。。

 

=========================================== 20140215 =========================================================

今天终于搞定!!

一个完整的例子贴上!!!:

package jmx;
public interface HelloMBean {
    // management attributes
    public String getName();
    public void setName(String name);
    // management operations
    public void print();
}

 

package jmx;
public class Hello implements HelloMBean {

    private String name = "";

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }

    public void print() {
    System.out.println("Hello, " + name + "!!" );
    }
}

 

package jmx;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXPrincipal;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.security.auth.Subject;

public class JmxServer {

    private final AtomicBoolean runningFlag = new AtomicBoolean(true);
    
    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        try {
            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

            String addr = "10.74.169.50:31999";//本机的话ip地址可以使用localhost或者127.0.0.1
            JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://"
                    + addr + "/jndi/rmi://" + addr + "/jmxrmi");

            Map<String, Object> jmxEnvironment = new HashMap<String, Object>();
            jmxEnvironment.put("jmx.remote.credentials", new String[] { "saf",
                    "asswrd" });

            InetAddress ipInterface = InetAddress.getByName("10.74.169.50");
            RMISocketFactory rmiFactory = RMISocketFactory.getDefaultSocketFactory();
                    //new AnchorSocketFactory(ipInterface,"false");
            LocateRegistry.createRegistry(31999, null, rmiFactory);
            
             // 這個是必須的,否則報 no such object in table之類是異常!!!! 花了相當長時間才發現這點
            jmxEnvironment.put(
                    RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,
                    rmiFactory);

            // 需要认证则这么写:
//            JMXAuthenticator auth = createJMXAuthenticator();
//            jmxEnvironment.put(JMXConnectorServer.AUTHENTICATOR, auth);

            JMXConnectorServer connector = JMXConnectorServerFactory
                    .newJMXConnectorServer(address, jmxEnvironment,
                            ManagementFactory.getPlatformMBeanServer());
            HelloMBean mbean = new Hello();
            ObjectName testMBeanName = new ObjectName(
                    "helloMBean:name=helloMBean");
            testMBeanName = new ObjectName("helloMBeanDomain", "type",
                    "HelloMBean");
            mbs.registerMBean(mbean, testMBeanName);

            connector.start();
        } catch (Exception e) {
            e.printStackTrace();
        }

//        try {//这个好像没用
//            synchronized (this) {
//                while (runningFlag.get()) {
//                    this.wait();
//                }
//            }
//        } catch (Exception e) {
//
//        }
    }

    private JMXAuthenticator createJMXAuthenticator() {
        return new JMXAuthenticator() {
            public Subject authenticate(Object credentials) {
                String[] sCredentials = (String[]) credentials;
                if (null == sCredentials || sCredentials.length != 2) {
                    throw new SecurityException("Authentication failed!");
                }
                String userName = sCredentials[0];
                String pValue = sCredentials[1];
                if ("saf".equals(userName) && "asswrd".equals(pValue)) {
                    Set principals = new HashSet();
                    principals.add(new JMXPrincipal(userName));
                    return new Subject(true, principals, Collections.EMPTY_SET,
                            Collections.EMPTY_SET);
                }
                throw new SecurityException("Authentication failed!");
            }
        };
    }

}

 

package jmx;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.HashMap;
import java.util.Map;

import javax.management.JMX;
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 JmxClient {

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        ObjectName hello_name = null;
        try {
            hello_name = new ObjectName("helloMBeanDomain", "type",
                    "HelloMBean");
            System.out.println("\tOBJECT NAME = " + hello_name);
            // service:jmx:rmi://%s:%d/jndi/rmi://%s:%d/jmxrmi
            String addr = "10.74.169.50:31999";
            JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://"
                    + addr + "/jndi/rmi://" + addr + "/jmxrmi");
            System.out.println("JmxRemote.main()1");
            Map<String, Object> jmxEnvironment = new HashMap<String, Object>();

            // 如果服務端有认证,則客戶端也要这么写:
            // jmxEnvironment.put("jmx.remote.credentials", new String[] {
            // "saf", "asswrd"});

            JMXConnector connector = JMXConnectorFactory.connect(address,
                    jmxEnvironment);
            System.out.println("JmxRemote.main()2");
            MBeanServerConnection mbs = connector.getMBeanServerConnection();
            System.out.println("JmxRemote.main()3");
            ThreadMXBean threadBean = ManagementFactory.newPlatformMXBeanProxy(
                    mbs, ManagementFactory.THREAD_MXBEAN_NAME,
                    ThreadMXBean.class);
            System.out
                    .println(" getThreadCount " + threadBean.getThreadCount());// 线程数量

            MBeanServerConnection connection = connector
                    .getMBeanServerConnection();
            HelloMBean helloMBean = JMX.newMXBeanProxy(connection, hello_name,
                    HelloMBean.class);

            System.out.println("aaaaaaaa " + helloMBean);

            helloMBean.setName("LKKKKKKK ddd basdf");

            helloMBean.print();

       connector.close();

}
catch (Exception e) { e.printStackTrace(); return; } } }

 

package jmx;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocketFactory;

public class AnchorSocketFactory extends RMISocketFactory {
    private InetAddress ipInterface = null;
    private String sslEnabled;
    
    public AnchorSocketFactory() {
    }

    public AnchorSocketFactory(InetAddress ipInterface, String sslEnabled) {
        this.ipInterface = ipInterface;
        this.sslEnabled = sslEnabled;
    }

    public ServerSocket createServerSocket(int port) throws IOException {
        if (this.sslEnabled.equalsIgnoreCase("true")) {
            SSLServerSocket sslserversocket = null;
            try {
                SSLServerSocketFactory sslserversocketfactory =
                    (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
                sslserversocket =
                    (SSLServerSocket)sslserversocketfactory.createServerSocket(port,
                            50,
                            this.ipInterface);
            } catch (IOException e) {
                throw e;
            }
            return sslserversocket;
        } else {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(port, 50, ipInterface);
            } catch (IOException e) {

                throw e;
            }

            return serverSocket;
        }
    }

    public Socket createSocket(String dummy, int port) throws IOException {
        if (this.sslEnabled.equalsIgnoreCase("true")) {
            return SSLSocketFactory.getDefault()
                    .createSocket(this.ipInterface.getHostName(), port);
        } else {
            return new Socket(ipInterface, port);
        }
    }
}

 

如果是通过jconsole连接的就这么来:

 

 

NOTE1:

server端步骤:

1 创建MBeanServerFactory mbs = ManagementFactory.getPlatformMBeanServer();

  或者MBeanServerFactory mbs = MBeanServerFactory.createMBeanServer("HelloAgentaa"); //  这个域名要和下面的保持一致

2 设置jmxEnvMap,必须的有RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE,可选的有账号密码、ssl参数等

3 创建JMXServiceURL,支持多种协议,http/snmp/rmi 等,有一定的格式,rmi的格式是:service:jmx:rmi://%s:%d/jndi/rmi://%s:%d/jmxrmi

4 获取JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, jmxEnvMap, mbs);

5 创建ObjectName helloWorldName = new ObjectName("HelloAgentaa:type=hwa");

6 注册MBean  mbs.registerMBean(hw, helloWorldName);

7 启动connectorServer   connectorServer.start();

 client端步骤:

1 同上2  如server端有设置账号密码、ssl参数等,client端需要一致

2 同上3

3 获取JMXConnector connector = JMXConnectorFactory.connect(address, jmxEnvironment);  需要注意的是,这里我们使用的是JMXConnector,而非JMXConnectorServer!

4 创建MBeanServerConnection connection = connector.getMBeanServerConnection();

  这里很关键的是,我们需要一个MBeanServerConnection, 而不再是JMXConnectorServer! 因为这个client端。。

5 同上5

6 获取MBean: HelloWorldMBean helloMBean = JMX.newMXBeanProxy(connection, hello_name, HelloWorldMBean.class);

  这里很关键的是,newMXBeanProxy的第三个参数和返回结果都是MBean接口,否则报错

7 尽情使用MBean,嘎嘎嘎!

8 使用后关闭MBeanServerConnection

 

 

NOTE2

ObjectName有三种构造函数:
  helloWorldName = new ObjectName("HelloAgentaa", "type", "hwa");
   helloWorldName = new ObjectName("HelloAgentaa:type=hwa");
   Hashtable<String, String> sadf = new Hashtable<String, String>(); sadf.put("type", "hwa");helloWorldName = new ObjectName("HelloAgentaa",sadf );

上面三种形式等价,但是不能,helloWorldName = new ObjectName("HelloAgentaa:type=hwa", key, value); 或者new ObjectName("HelloAgentaa:type=hwa", map); 这样混合使用!

 

NOTE3

创建MBeanServerFactory有两种方式:

1 MBeanServerFactorymbs = ManagementFactory.getPlatformMBeanServer(); //  获取jmx平台基础已有的MBeanServerFactory

2 或者MBeanServerFactory mbs = MBeanServerFactory.createMBeanServer("HelloAgentaa"); // 获取新的MBeanServerFactory

具体使用哪种要酌情考虑

(clien不t需要MBeanServerFactory)

 

 

NOTE4

客户端使用完记得关闭JMXConnector

 

我这里没有设置jmx账号,所以下面两栏为空

如果需要使用ssl通道加密数据的话,则需执行(当然,要jmx服务器配置好ssl先):

jconsole -J-Djavax.net.ssl.trustStore=D:\jmx\certificate\serverTrustStore -J-Djavax.net.ssl.trustStorePassword=asswor

然后再在弹出的jconsole页面——远程连接——输入ip/port/username/password。。。。。

 

posted on 2014-02-11 00:36  CanntBelieve  阅读(8485)  评论(1编辑  收藏  举报