1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.apache.hadoop.conf.Configuration;
24 import org.apache.hadoop.hbase.CoprocessorEnvironment;
25 import org.apache.hadoop.hbase.coprocessor.*;
26
27 import java.io.IOException;
28 import java.lang.management.ManagementFactory;
29 import java.rmi.registry.LocateRegistry;
30 import java.rmi.server.RMIClientSocketFactory;
31 import java.rmi.server.RMIServerSocketFactory;
32 import java.util.HashMap;
33
34 import javax.management.MBeanServer;
35 import javax.management.remote.JMXConnectorServer;
36 import javax.management.remote.JMXConnectorServerFactory;
37 import javax.management.remote.JMXServiceURL;
38 import javax.management.remote.rmi.RMIConnectorServer;
39 import javax.rmi.ssl.SslRMIClientSocketFactory;
40 import javax.rmi.ssl.SslRMIServerSocketFactory;
41
42
43
44
45
46
47
48
49 public class JMXListener implements Coprocessor {
50
51 public static final Log LOG = LogFactory.getLog(JMXListener.class);
52 public static final String RMI_REGISTRY_PORT_CONF_KEY = ".rmi.registry.port";
53 public static final String RMI_CONNECTOR_PORT_CONF_KEY = ".rmi.connector.port";
54 public static final int defRMIRegistryPort = 10102;
55
56
57
58
59
60
61
62 private static JMXConnectorServer jmxCS = null;
63
64 public static JMXServiceURL buildJMXServiceURL(int rmiRegistryPort,
65 int rmiConnectorPort) throws IOException {
66
67 StringBuilder url = new StringBuilder();
68 url.append("service:jmx:rmi://localhost:");
69 url.append(rmiConnectorPort);
70 url.append("/jndi/rmi://localhost:");
71 url.append(rmiRegistryPort);
72 url.append("/jmxrmi");
73
74 return new JMXServiceURL(url.toString());
75
76 }
77
78 public void startConnectorServer(int rmiRegistryPort, int rmiConnectorPort)
79 throws IOException {
80 boolean rmiSSL = false;
81 boolean authenticate = true;
82 String passwordFile = null;
83 String accessFile = null;
84
85 System.setProperty("java.rmi.server.randomIDs", "true");
86
87 String rmiSSLValue = System.getProperty("com.sun.management.jmxremote.ssl",
88 "false");
89 rmiSSL = Boolean.parseBoolean(rmiSSLValue);
90
91 String authenticateValue =
92 System.getProperty("com.sun.management.jmxremote.authenticate", "false");
93 authenticate = Boolean.parseBoolean(authenticateValue);
94
95 passwordFile = System.getProperty("com.sun.management.jmxremote.password.file");
96 accessFile = System.getProperty("com.sun.management.jmxremote.access.file");
97
98 LOG.info("rmiSSL:" + rmiSSLValue + ",authenticate:" + authenticateValue
99 + ",passwordFile:" + passwordFile + ",accessFile:" + accessFile);
100
101
102 HashMap<String, Object> jmxEnv = new HashMap<String, Object>();
103
104 RMIClientSocketFactory csf = null;
105 RMIServerSocketFactory ssf = null;
106
107 if (rmiSSL) {
108 if (rmiRegistryPort == rmiConnectorPort) {
109 throw new IOException("SSL is enabled. " +
110 "rmiConnectorPort cannot share with the rmiRegistryPort!");
111 }
112 csf = new SslRMIClientSocketFactory();
113 ssf = new SslRMIServerSocketFactory();
114 }
115
116 if (csf != null) {
117 jmxEnv.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
118 }
119 if (ssf != null) {
120 jmxEnv.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);
121 }
122
123
124 if (authenticate) {
125 jmxEnv.put("jmx.remote.x.password.file", passwordFile);
126 jmxEnv.put("jmx.remote.x.access.file", accessFile);
127 }
128
129
130 LocateRegistry.createRegistry(rmiRegistryPort);
131
132 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
133
134
135 JMXServiceURL serviceUrl = buildJMXServiceURL(rmiRegistryPort, rmiConnectorPort);
136
137 try {
138
139 jmxCS = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, jmxEnv, mbs);
140 jmxCS.start();
141 LOG.info("ConnectorServer started!");
142 } catch (IOException e) {
143 LOG.error("fail to start connector server!", e);
144 }
145
146 }
147
148 public void stopConnectorServer() throws IOException {
149 synchronized(JMXListener.class) {
150 if (jmxCS != null) {
151 jmxCS.stop();
152 LOG.info("ConnectorServer stopped!");
153 jmxCS = null;
154 }
155 }
156 }
157
158
159 @Override
160 public void start(CoprocessorEnvironment env) throws IOException {
161 int rmiRegistryPort = -1;
162 int rmiConnectorPort = -1;
163 Configuration conf = env.getConfiguration();
164
165 if (env instanceof MasterCoprocessorEnvironment) {
166 LOG.error("JMXListener should not be loaded in Master Environment!");
167 } else if (env instanceof RegionServerCoprocessorEnvironment) {
168
169 rmiRegistryPort =
170 conf.getInt("regionserver" + RMI_REGISTRY_PORT_CONF_KEY, defRMIRegistryPort);
171 rmiConnectorPort =
172 conf.getInt("regionserver" + RMI_CONNECTOR_PORT_CONF_KEY, rmiRegistryPort);
173 LOG.info("RegionServer rmiRegistryPort:" + rmiRegistryPort
174 + ",RegionServer rmiConnectorPort:" + rmiConnectorPort);
175
176 } else if (env instanceof RegionCoprocessorEnvironment) {
177 LOG.error("JMXListener should not be loaded in Region Environment!");
178 }
179
180 synchronized(JMXListener.class) {
181 if (jmxCS != null) {
182 LOG.info("JMXListener has been started at Registry port " + rmiRegistryPort);
183 }
184 else {
185 startConnectorServer(rmiRegistryPort, rmiConnectorPort);
186 }
187 }
188 }
189
190 @Override
191 public void stop(CoprocessorEnvironment env) throws IOException {
192 stopConnectorServer();
193 }
194
195 }