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 jmxCS = 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 jmxCS = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, jmxEnv, mbs);
141 jmxCS.start();
142 LOG.info("ConnectorServer started!");
143 } catch (IOException e) {
144 LOG.error("fail to start connector server!", e);
145 }
146
147 }
148
149 public void stopConnectorServer() throws IOException {
150 synchronized(JMXListener.class) {
151 if (jmxCS != null) {
152 jmxCS.stop();
153 LOG.info("ConnectorServer stopped!");
154 jmxCS = null;
155 }
156 }
157 }
158
159
160 @Override
161 public void start(CoprocessorEnvironment env) throws IOException {
162 int rmiRegistryPort = -1;
163 int rmiConnectorPort = -1;
164 Configuration conf = env.getConfiguration();
165
166 if (env instanceof MasterCoprocessorEnvironment) {
167
168 rmiRegistryPort =
169 conf.getInt("master" + RMI_REGISTRY_PORT_CONF_KEY, defMasterRMIRegistryPort);
170 rmiConnectorPort = conf.getInt("master" + RMI_CONNECTOR_PORT_CONF_KEY, rmiRegistryPort);
171 LOG.info("Master rmiRegistryPort:" + rmiRegistryPort + ",Master rmiConnectorPort:"
172 + rmiConnectorPort);
173 } else if (env instanceof RegionServerCoprocessorEnvironment) {
174
175 rmiRegistryPort =
176 conf.getInt("regionserver" + RMI_REGISTRY_PORT_CONF_KEY,
177 defRegionserverRMIRegistryPort);
178 rmiConnectorPort =
179 conf.getInt("regionserver" + RMI_CONNECTOR_PORT_CONF_KEY, rmiRegistryPort);
180 LOG.info("RegionServer rmiRegistryPort:" + rmiRegistryPort
181 + ",RegionServer rmiConnectorPort:" + rmiConnectorPort);
182
183 } else if (env instanceof RegionCoprocessorEnvironment) {
184 LOG.error("JMXListener should not be loaded in Region Environment!");
185 return;
186 }
187
188 synchronized(JMXListener.class) {
189 if (jmxCS != null) {
190 LOG.info("JMXListener has been started at Registry port " + rmiRegistryPort);
191 }
192 else {
193 startConnectorServer(rmiRegistryPort, rmiConnectorPort);
194 }
195 }
196 }
197
198 @Override
199 public void stop(CoprocessorEnvironment env) throws IOException {
200 stopConnectorServer();
201 }
202
203 }