【转】JMX实践-JMX连接端口
首先要从JMX URL说起。如下是一个典型的JMX URL:
service:jmx:rmi://localhost:5000/jndi/rmi://localhost:6000/jmxrmi
这个JMX URL可以分为如下几个部分:
service:jmx: 这个是JMX URL的标准前缀,所有的JMX URL都必须以该字符串开头。
rmi: 这个是connector server的传输协议,在这个url中是使用rmi来进行传输的。JSR 160规定了所有connector server都必须至少实现rmi传输,是否还支持其他的传输协议依赖于具体的实现。比如MX4J就支持soap、soap+ssl、hessian、burlap等等传输协议。
localhost:5000: 这个是connector server的IP和端口,该部分是一个可选项,可以被省略掉。(具体参见下文解释)
/jndi/rmi://localhost:6000/jmxrmi: 这个是connector server的路径,具体含义取决于前面的传输协议。比如该URL中这串字符串就代表着该connector server的stub是使用jndi api绑定在rmi://localhost:6000/jmxrmi这个地址。
如果在服务器端,我们用该URL创建一个connector server,则大概流程如下:
将connect server(javax.management.remote.rmi.RMIConnectorServer)内部的server对象(javax.management.remote.rmi.RMIJRMPServerImpl)的rmi stub export到本地的5000端口,接收外部连接
通过jndi api将该stub绑定在rmi://localhost:6000/jmxrmi这个地址上,这需要在本地的6000端口上运行着一个rmiregistry,如果不存在则会抛出异常
......
可以看到,如果在服务器端创建connector server时,该URL的第三部分(即localhost:5000)如果省略的话,则connector server会随机任意选择一个可用的端口。
如果在客户端,我们通过该URL创建一个connector,则大概按照如下的流程:
通过jndi api到rmi://localhost:6000/jmxrmi这个地址取回stub
stub中已经包含了真实服务器的地址,所以可以直接根据该stub连接到真实的服务器
......
可以看到,如果在客户端创建connector时,该URL的第三部分可以被省略掉。事实上我们也经常这么做,比如上面这个示例,在客户端建立connector所用的JMX URL可以被省略为:
service:jmx:rmi:///jndi/rmi://localhost:6000/jmxrmi
从这个示例中我们也可以看到,如果采用rmi作为传输协议的话,客户端需要进行两个连接。首先客户端连接到rmiregistry上得到真实服务器的stub(如rmi://localhost:6000/rmxrmi),然后客户端再根据该stub连接到真实的服务器上(如rmi://localhost:5000)。
在Sun Java 5.0的实现当中,可以通过指定运行期属性来配置JMX。比如:
-Dcom.sun.management.jmxremote.port=6000
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.password.file=conf/jmxremote.password
-Dcom.sun.management.jmxremote.access.file=conf/jmxremote.access
除开密码和权限控制的配置外,这段运行期相当于一个如下的JMX URL:
service:jmx:rmi://localhost:0/jndi/rmi://localhost:6000/jmxrmi (红色部分可以被省略掉)
可以看到,通过指定com.sun.management.jmxremote.port属性,相当于指定了rmiregistry的运行端口,但是真正运行的服务器的stub export端口为0,会在运行期任意选择一个未被使用的端口号。如果该程序运行在防火墙后面,这个动态分配的端口号会让我们非常难以配置防火墙规则。
由于Sun Java 5.0实现的疏忽,并没有为我们提供一个运行期属性来配置stub export端口号,那么如何自定义一个JMX连接端口呢?
假设我们不传入任何运行期参数,仅通过代码来自定义一个connector server:
LocateRegistry.createRegistry(6000);
JMXConnectorServer cs = JMXConnectorServerFactory
.newJMXConnectorServer(url, env, beanServer);
cs.start();
第一行代码指明在6000端口创建一个rmiregistry。
第二行代码创建了一个connector server。第一个URL参数传入指定的JMXServiceURL,比如new JMXServiceURL("service:jmx:rmi://localhost:5000/jndi/rmi://localhost:6000/jmxrmi"),值得注意的是红色部分标出的IP和端口号要和第一步中创建的rmiregistry一致。第二个参数指定创建时的环境,我们可以暂时传入一个空Map。第三个参数指定要创建连接的MBeanServer,比如在Java 5.0下可以是ManagementFactory.getPlatformMBeanServer()。
第三行代码开启了创建的connector server。
这三行代码创建的connector server工作的很好,除了一点:真实的服务器没有任何认证和授权机制,会允许所有人访问。
自定义权限控制可以通过刚才第二行代码的第二个参数来进行设置:
Map env = new HashMap();
env.put(JMXConnectorServer.AUTHENTICATOR, JMXAuthenticator子类的实例);
比如在MX4J中就提供了一个mx4j.tools.remote.PasswordAuthenticator的类,通过配置文件来匹配用户名和密码;Sun也提供了一个com.sun.jmx.remote.security.JMXPluggableAuthenticator的类通过JAAS来配置验证和权限。用户可以参照这两个类来提供自定义的实现。这里提供一个简单的示例(不带任何效验机制,仅用于示例)
env.put(JMXConnectorServer.AUTHENTICATOR, new JMXAuthenticator() {
public Subject authenticate(Object credentials) {
String[] sCredentials = (String[]) credentials;
String userName = sCredentials[0];
String password = sCredentials[1];
if ("test".equals(userName) && "test".equals(password)) {
Set principals = new HashSet();
principals.add(new JMXPrincipal(user));
return new Subject(true, principals, Collections.EMPTY_SET,
Collections.EMPTY_SET);
}
throw new SecurityException("Authentication failed! "
+ message);
}
});
加入这段代码后,真实的服务器必须要验证后才能访问,但又有了一个新问题:rmiregistry没有任何验证。这意味着其他人可以把一个不相干的stub绑定到同一地址,从而替换掉真实服务器stub。好在幸运的是,无法把一个服务器端类路径上不存在的stub类绑定到rmiregistry,否则真实的用户名和密码就有可能被泄漏出去。
如果直接通过rmi对外提供的接口,我们没有办法修正这个问题,除非将代码绑定于特定的Java实现,比如Sun就直接通过它自己的rmi实现类来做(所以通过运行期参数配置jmx生成的rmiregistry是只读的,没有该安全性问题)。具体可参见sun.management.Agent和sun.management.jmxremote包下相关类。
但是我们可以换一个思路,比如不绑定到rmiregistry而绑定到其他的实现了验证机制的jndi provider,例如ldap上。由于bind jndi的代码在相关connector server的实现类中,比如javax.management.remote.rmi.RMIConnectorServer中bind jndi的代码:
void bind(String jndiUrl, Hashtable attributes,
RMIServer rmiServer, boolean rebind)
throws NamingException, MalformedURLException {
// if jndiURL is not null, we nust bind the stub to a
// directory.
InitialContext ctx =
new InitialContext(attributes);
if (rebind)
ctx.rebind(jndiUrl, rmiServer);
else
ctx.bind(jndiUrl, rmiServer);
ctx.close();
}
它在传入attributes时并没有特定的jndi的INITIAL_CONTEXT_FACTORY,所以我们可以通过两种方法来指定特定的INITIAL_CONTEXT_FACTORY:
在类路径上放上一个jndi.properties,配置相应的jndi属性
在start connector server前,先在系统属性中指定相应的jndi属性,start后再把这些属性恢复成原有属性
其中第一种方式不需要额外的代码,但是可能会对系统中其他jndi的InitialContext产生影响;第二种方式稍微麻烦点,但是在实现上比较完美。
值得提到的是,如果采用rmiregistry,并且rmiregistry和server在同一个JVM内,stub和rmiregistry可以共享一个端口。比如可以使用如下的JMX URL:
service:jmx:rmi://localhost:6000/jndi/rmi://localhost:6000/jmxrmi
但注意一定要在同一JVM内,比如先用LocateRegistry.createRegistry(6000)创建本地rmiregistry,再通过该URL开启connector server,则可以共享6000端口。
分享到:
相关推荐
port JMX 服务器应该监听的端口。 默认值为5678 user用于身份验证的用户(连同密码) password用于身份验证的密码(然后也需要用户) 成功启动后,代理将打印出带有完整 URL 的成功消息,客户端可
在Java HotSpot虚拟机中,使用开箱即用的远程jmx时会打开服务器端口,其中一些端口是动态的,这使防火墙非常难受。 下面显示了这一痛苦的事情: java \ -Djava.net.preferIPv4Stack=true \ -Dcom.sun....
activeMQ开启jmx固定rmi端口,穿透防火墙,用了一天的时间,踩了无数的坑,拿出来共享.
要将Java代理绑定到特定IP,请将端口号更改为host:port 。 请参阅./run_sample_httpserver.sh ,以获取针对自身运行httpserver的示例脚本。 请注意,由于JMX的特性, /metrics端点可能会超过Prometheus默认的10...
JMX导出程序加载器 该应用程序将代理加载到正在运行的Java进程中。 实现时,只能在JVM启动时将其加载到Java进程中。 只需进行很小的更改,就可以将其加载到已经运行的Java进程中。 您可以看看我们的中的更改 加载...
java版s源码JMX代理 ...配置侦听端口: server : type : simple applicationContextPath : / connector : type : http port : 8000 请注意,指定applicationContextPath很重要,否则所有请求都必须在 UR
java jmx agent不安全的配置漏洞
如果要更改此设置,请在运行之前在index.js文件的第51行中输入新的端口号。 仅适用于Linux / Ubuntu和Mac OS。 将在更高版本中增加Windows兼容性。 该脚本将覆盖以下文件。 如果希望保存任何自定义设置,请在运行此...
可以禁止或允许远程主机访问本地主机的某个端口和某些端口,也可禁止或允许本地主机访问远程主机的某个端口和某些端口。 对于近期通过135端口传播的病毒可以起到防护作用。 功能示例 一.禁止远程访问本地135端口 1...
Jetty java程序指定一个端口,开通一个TCP服务。此代码是用来测试的,仅供参考,不具备项目价值
主机和端口与JMX调试端口所在的位置有关。 app-under-test是一个字符串字段,可用于区分输出中的特定java进程(在收集器输出中生成“ appname”的标签/ v。)如果使用属性文件,则需要指定它作为bosun-jmx.jar文件...
Docker 开启远程链接(2375端口)提供外部访问1. 登陆Docker所在服务器,编辑docker.service文件2. 利用Docker Client远程工具进行docker操作(无需登陆服务器)2.1 下载安装Dcoker远程链接工具3.软件声明 1. 登陆...
那些私有管理界面,JMX端口或Erlang / Elixir分发端口不对外开放? 没问题。 Shipspotter aut Shipspotter一个远程端口转发工具,用于访问Docker容器内部的服务。 那些私有管理界面,JMX端口或Erlang / Elixir分发...
jmeter 模拟ip http请求 并发测试 压力测试
代理可以连接到正在运行的JVM实例 领事支持(http端口已注册到领事) 它也可以作为独立的HTTP服务器运行,并刮擦远程JMX目标。 跑步 要作为javaagent运行,请并运行: java -javaagent:./jmx_prometheus_java...
环境准备我们这里就不直接演示了,直接配置tomcat的jmx 1、进入到tomcat的bin目录下 # cd /opt/tomcat/apache-tomcat-8.0.48/bin/ 2、编辑配置文件 # vim catalina.sh 3、在下图中上面添加参数 参数...
java8 看不到源码Java虚拟机 OpenNMS 配置以使用 Java 管理扩展 (JMX) 从 Java 虚拟机监控性能指标。...此配置已通过以下测试: ...JMX ...本例中数据采集添加到默认采集包中,采集间隔为5分钟(服务...此示例使用端口 18980 作
指定端口运行 java -jar testing_platform-0.1-SNAPSHOT.jar --server.port=9999 ### 原理 上传/新建jmx脚本,通过java执行 `jmeter -n -t xxx.jmx -o -p dir` 来运行脚本并生成html报告。 web框架基于...
2. web 服务的端口号的修改 3. JBoss 的安全设置 3.1 jmx-console 登录的用户名和密码设置 3.2 web-console 登录的用户名和密码设置 4. JBoss 数据源的配置 5. JMS使用和设置 5.1 JMS消息的传递模型 5.2 JMS的配置 ...