JBoss 中的 JMS,如何穿透防火墙?

JBoss 中可穿透防火墙的 JMS 承载方式有 RMI、HTTP 和 UIL2。RMI 和 HTTP 太慢了,所以 UIL2 是可以接受的选择。

然而,在 JBOSS 的所有版本中,默认情况下,都存在 UIL2 不能穿透防火墙的问题。

以 JBoss 3.2.4 为分界点,本文给出了前后两种解决方法。

环境描述

见下图,JBoss Server 部署在内网上,主机名为 myserver,通过防火墙 Firewall-B 连接到公网上。公网外有一台客户端机器 hostA,上面运行了 JMS 客户端程序。

拓扑结构示意图



问题描述

JMS 客户端连接不上 myserver 上的 JMS 服务器,通常是:


Code:
JMSException occurred: org.jboss.mq.SpyJMSException: Cannot authenticate user; - nested throwable: (java.net.ConnectException: 不允许��? org.jboss.mq.SpyJMSException: Cannot authenticate user; - nested throwable: (java.net.ConnectException: 不允许联接)   at org.jboss.mq.Connection.authenticate(Connection.java:883) Caused by: java.net.ConnectException: 不允许联接   at java.net.PlainSocketImpl.socketConnect(Native Method)   at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:305)
[Ctrl+A Select All]



问题分析

太长了,省略……

解决方法

一、针对 JBoss 3.2.4(不含)以前的版本

我在 JBoss 3.2.3 上打了一个 patch,可从此处下载,下载后把 rar 改成 jar 即可:
 
[url]http://img1.51cto.com/attachment/200611/59583_1162519435.rar[/url]
(如果此链接不能下载,则到文章的最底下找链接,那是博客自动加的)

操作步骤:

1、用所下载的 jbossmq.jar 替换 JBoss 服务器端的 jbossmq.jar,通常位于:jboss/server/default/lib 目录下;

2、修改 JBoss 的启动脚本 run.sh,在 JAVA_OPTS 变量里面加上“-DSERVER_NAME=<服务器的主机名>”,如:
JAVA_OPTS="$JAVA_OPTS -Dprogram.name=$PROGNAME -DSERVER_NAME=myserver"
3、启动 JBoss 服务器;

4、把所下载的 jbossmq.jar 加入到 JMS 客户端的 Classpath 中,注意:一定要加在 jbossall-client.jar 的前面

5、在客户端的机器的 hosts 文件中加入 myserver 与公网 IP 的映射,例如:210.0.0.1     myserver

hosts 文件通常是 windows\system32\drivers\etc\hosts 或 /etc/hosts;

6、在客户端 JMS 程序的启动脚本中,也加上“-DSERVER_NAME=myserver”选项;

7、恭喜你,可以启动 JMS 客户端了。

二、针对 JBoss 3.2.4(含)以后的版本

JBoss 3.2.4 起修改了这个 BUG,只要在 JMS 客户端的启动脚本中加上如下选项即可:
“-Dorg.jboss.mq.il.uil2.useServerHost=true”

自己编写补丁

对于 3.2.3 以前的版本,请自己动手打 patch,步骤如下:

1、修改 org\jboss\mq\il\uil2\UILServerIL.java 的 createConnection() 方法,在如下代码前:


Code:
if( localAddr != null )   socket = socketFactory.createSocket(addr, port, localAddr, localPort); else   socket = socketFactory.createSocket(addr, port);
[Ctrl+A Select All]


加上代码:


Code:
//可以用你自己的方式来获得服务器的名称,例如从配置文件中读 String s1 = System.getProperty("SERVER_NAME"); if(s1 != null) {   addr = InetAddress.getByName(s1);       //这句就可以省了,或者用 log4j 来打印调试信息   //System.out.println("addr = " + addr.toString()); }
[Ctrl+A Select All]


最终结果是:


Code:
String s1 = System.getProperty("SERVER_NAME"); if(s1 != null) {   addr = InetAddress.getByName(s1);   //System.out.println("addr = " + addr.toString()); } if( localAddr != null )   socket = socketFactory.createSocket(addr, port, localAddr, localPort); else   socket = socketFactory.createSocket(addr, port);
[Ctrl+A Select All]


把这个类编译,并替换旧的 jbossmq.jar 中的同名文件。然后打 patch,方法见上文。

本文出自 “豪客城” 博客,转载请与作者联系!

你可能感兴趣的:(jboss,防火墙,jms,休闲,穿透)