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 private 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 defMasterRMIRegistryPort = 10101;
55 public static final int defRegionserverRMIRegistryPort = 10102;
56
57
58
59
60
61
62
63 private static JMXConnectorServer JMX_CS = null;
64
65 public static JMXServiceURL buildJMXServiceURL(int rmiRegistryPort,
66 int rmiConnectorPort) throws IOException {
67
68 StringBuilder url = new StringBuilder();
69 url.append("service:jmx:rmi://localhost:");
70 url.append(rmiConnectorPort);
71 url.append("/jndi/rmi://localhost:");
72 url.append(rmiRegistryPort);
73 url.append("/jmxrmi");
74
75 return new JMXServiceURL(url.toString());
76
77 }
78
79 public void startConnectorServer(int rmiRegistryPort, int rmiConnectorPort)
80 throws IOException {
81 boolean rmiSSL = false;
82 boolean authenticate = true;
83 String passwordFile = null;
84 String accessFile = null;
85
86 System.setProperty("java.rmi.server.randomIDs", "true");
87
88 String rmiSSLValue = System.getProperty("com.sun.management.jmxremote.ssl",
89 "false");
90 rmiSSL = Boolean.parseBoolean(rmiSSLValue);
91
92 String authenticateValue =
93 System.getProperty("com.sun.management.jmxremote.authenticate", "false");
94 authenticate = Boolean.parseBoolean(authenticateValue);
95
96 passwordFile = System.getProperty("com.sun.management.jmxremote.password.file");
97 accessFile = System.getProperty("com.sun.management.jmxremote.access.file");
98
99 LOG.info("rmiSSL:" + rmiSSLValue + ",authenticate:" + authenticateValue
100 + ",passwordFile:" + passwordFile + ",accessFile:" + accessFile);
101
102
103 HashMap<String, Object> jmxEnv = new HashMap<String, Object>();
104
105 RMIClientSocketFactory csf = null;
106 RMIServerSocketFactory ssf = null;
107
108 if (rmiSSL) {
109 if (rmiRegistryPort == rmiConnectorPort) {
110 throw new IOException("SSL is enabled. " +
111 "rmiConnectorPort cannot share with the rmiRegistryPort!");
112 }
113 csf = new SslRMIClientSocketFactory();
114 ssf = new SslRMIServerSocketFactory();
115 }
116
117 if (csf != null) {
118 jmxEnv.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf);
119 }
120 if (ssf != null) {
121 jmxEnv.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf);
122 }
123
124
125 if (authenticate) {
126 jmxEnv.put("jmx.remote.x.password.file", passwordFile);
127 jmxEnv.put("jmx.remote.x.access.file", accessFile);
128 }
129
130
131 LocateRegistry.createRegistry(rmiRegistryPort);
132
133 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
134
135
136 JMXServiceURL serviceUrl = buildJMXServiceURL(rmiRegistryPort, rmiConnectorPort);
137
138 try {
139
140 synchronized(JMXListener.class) {
141 if (JMX_CS != null) {
142 throw new RuntimeException("Started by another thread?");
143 }
144 JMX_CS = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, jmxEnv, mbs);
145 JMX_CS.start();
146 }
147 LOG.info("ConnectorServer started!");
148 } catch (IOException e) {
149 LOG.error("fail to start connector server!", e);
150 }
151
152 }
153
154 public void stopConnectorServer() throws IOException {
155 synchronized(JMXListener.class) {
156 if (JMX_CS != null) {
157 JMX_CS.stop();
158 LOG.info("ConnectorServer stopped!");
159 JMX_CS = null;
160 }
161 }
162 }
163
164
165 @Override
166 public void start(CoprocessorEnvironment env) throws IOException {
167 int rmiRegistryPort = -1;
168 int rmiConnectorPort = -1;
169 Configuration conf = env.getConfiguration();
170
171 if (env instanceof MasterCoprocessorEnvironment) {
172
173 rmiRegistryPort =
174 conf.getInt("master" + RMI_REGISTRY_PORT_CONF_KEY, defMasterRMIRegistryPort);
175 rmiConnectorPort = conf.getInt("master" + RMI_CONNECTOR_PORT_CONF_KEY, rmiRegistryPort);
176 LOG.info("Master rmiRegistryPort:" + rmiRegistryPort + ",Master rmiConnectorPort:"
177 + rmiConnectorPort);
178 } else if (env instanceof RegionServerCoprocessorEnvironment) {
179
180 rmiRegistryPort =
181 conf.getInt("regionserver" + RMI_REGISTRY_PORT_CONF_KEY,
182 defRegionserverRMIRegistryPort);
183 rmiConnectorPort =
184 conf.getInt("regionserver" + RMI_CONNECTOR_PORT_CONF_KEY, rmiRegistryPort);
185 LOG.info("RegionServer rmiRegistryPort:" + rmiRegistryPort
186 + ",RegionServer rmiConnectorPort:" + rmiConnectorPort);
187
188 } else if (env instanceof RegionCoprocessorEnvironment) {
189 LOG.error("JMXListener should not be loaded in Region Environment!");
190 return;
191 }
192
193 synchronized(JMXListener.class) {
194 if (JMX_CS != null) {
195 LOG.info("JMXListener has been started at Registry port " + rmiRegistryPort);
196 }
197 else {
198 startConnectorServer(rmiRegistryPort, rmiConnectorPort);
199 }
200 }
201 }
202
203 @Override
204 public void stop(CoprocessorEnvironment env) throws IOException {
205 stopConnectorServer();
206 }
207
208 }