Wildfly 10.1,使用IPv6进行JMS查找

时间:2018-02-19 16:59:27

标签: jms wildfly netty ipv6 activemq-artemis

我有一个有效的IPv4配置,用于在Wildfly 10.1作为服务器的富Java客户端中使用ActiveMQ。我试图切换到IPv6,它不再起作用了。问题是,上下文查找检索包含IPv6范围id的ServerLocator对象,例如: [FD00 :: d7dc:b4cc:2e2a:EA1%enp0s3]

但此范围仅在服务器上有效。当客户端尝试连接到ServerLocator中的服务器时,它显然不能,因为enp0s3是服务器上的接口而不是客户端上的接口。当我在调试模式下删除作用域时,应用程序再次运行没有问题。所以这只是错误的范围...

有没有办法设置服务器,只发送没有范围的地址?服务器在Java 8上运行,OS在Centos 7上运行。

我的客户代码是:

        String JMS_CONNECTION_FACTORY_JNDI = "jms/RemoteConnectionFactory";
        Context context = getApplicationManager().getConnectionHandler().getContext();
        TopicConnectionFactory cf = (TopicConnectionFactory) context.lookup(JMS_CONNECTION_FACTORY_JNDI);
        topicConnection = cf.createTopicConnection();

正确设置了上下文属性,适用于IPv4。

配置很标准:

   <interfaces>
    <interface name="management">
        <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
    </interface>
    <interface name="public">
        <inet-address value="${jboss.bind.address:127.0.0.1}"/>
    </interface>
</interfaces>
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
    <socket-binding name="management-http" interface="management" port="${jboss.management.http.port:9990}"/>
    <socket-binding name="management-https" interface="management" port="${jboss.management.https.port:9993}"/>
    <socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
    <socket-binding name="http" port="${jboss.http.port:8080}"/>
    <socket-binding name="https" port="${jboss.https.port:8443}"/>
    <socket-binding name="txn-recovery-environment" port="4712"/>
    <socket-binding name="txn-status-manager" port="4713"/>
    <outbound-socket-binding name="mail-smtp">
        <remote-destination host="localhost" port="25"/>
    </outbound-socket-binding>
 </socket-binding-group>

信息:

    <subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
        <server name="default">
            <security enabled="false"/>
            <security-setting name="#">
                <role name="guest" send="true" consume="true" create-durable-queue="true" delete-durable-queue="true" create-non-durable-queue="true" delete-non-durable-queue="true"/>
            </security-setting>
            <address-setting name="#" dead-letter-address="jms.queue.DLQ" expiry-address="jms.queue.ExpiryQueue" max-size-bytes="10485760" page-size-bytes="2097152" message-counter-history-day-limit="10"/>
            <http-connector name="http-connector" socket-binding="http" endpoint="http-acceptor"/>
            <http-connector name="http-connector-throughput" socket-binding="http" endpoint="http-acceptor-throughput">
                <param name="batch-delay" value="50"/>
            </http-connector>
            <in-vm-connector name="in-vm" server-id="0"/>
            <http-acceptor name="http-acceptor" http-listener="default"/>
            <http-acceptor name="http-acceptor-throughput" http-listener="default">
                <param name="batch-delay" value="50"/>
                <param name="direct-deliver" value="false"/>
            </http-acceptor>
            <in-vm-acceptor name="in-vm" server-id="0"/>
            <jms-queue name="ExpiryQueue" entries="java:/jms/queue/ExpiryQueue"/>
            <jms-queue name="DLQ" entries="java:/jms/queue/DLQ"/>
            <jms-queue name="simulationServerQueue" entries="queue/simulationServerQueue java:/jms/queue/simulationServerQueue"/>
            <jms-queue name="simulationWrapperQueue" entries="queue/simulationWrapperQueue java:/jms/queue/simulationWrapperQueue"/>
            <jms-topic name="StatusMessaging" entries="topic/StatusMessaging java:/jms/queue/StatusMessaging"/>
            <jms-topic name="SimulationMessaging" entries="topic/SimulationMessaging java:/jms/queue/SimulationMessaging"/>
            <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>
            <connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="http-connector"/>
            <pooled-connection-factory name="activemq-ra" entries="java:/JmsXA java:jboss/DefaultJMSConnectionFactory" connectors="in-vm" transaction="xa"/>
        </server>

和属性:

jboss.bind.address=[fd00::d7dc:b4cc:2e2a:ea1]
java.rmi.server.hostname=[fd00::d7dc:b4cc:2e2a:ea1]
jboss.http.port=8080

相同的上下文(由getConnectionHandler()。getContext();)检索并且配置适用于EJB查找而没有问题。我可以通过JNDI查找接口并在服务器上执行代码。

仅影响主题连接(使用ActiveMQ)。而且只是因为SCOPE。如果我在ActiveMQConnectionFactory.readExternal(..)中的URL中以调试模式删除范围(enp0s3),则ActiveMQ可以正常工作。

更新Wildfly 11

我尝试使用Wildfly 11.0.0.Final错误更改为

java.net.UnknownHostException: no such interface enp0s3
at java.net.Inet6Address.initstr(Inet6Address.java:487)
at java.net.Inet6Address.<init>(Inet6Address.java:408)
at java.net.InetAddress.getAllByName(InetAddress.java:1181)
at java.net.InetAddress.getAllByName(InetAddress.java:1126)
at java.net.InetAddress.getByName(InetAddress.java:1076)
at io.netty.util.internal.SocketUtils$8.run(SocketUtils.java:146)

所以问题是一样的。不会为JMS客户端剥离范围标识。

EDIT Centos 7

我做了一个小程序来检查java实现以获取InetAddress:

    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements()) {
        NetworkInterface netInterface = interfaces.nextElement();
        Enumeration<InetAddress> address = netInterface.getInetAddresses();
        while (address.hasMoreElements()) {
            InetAddress addr = address.nextElement();
            if (addr instanceof Inet6Address) {
                Inet6Address inet6addr = (Inet6Address) addr;
                if (!inet6addr.isLinkLocalAddress() && !inet6addr.isLoopbackAddress())
                    System.out.println(netInterface.getName() +":"+ inet6addr.isLinkLocalAddress() +":"+ inet6addr +" - "+ inet6addr.getScopedInterface());

            }
        }
    }

在Windows上返回:

eth2:false:/fd00:0:0:0:309c:ae5c:b57c:da62 - null

因此没有设定范围。在第7期:

enp0s3:false:/fd00:0:0:0:d7dc:b4cc:2e2a:ea1%enp0s3 - name:enp0s3 (enp0s3)

所以范围设置在centos上,即使它不是本地链接。我假设在查找过程中使用了类似的东西?有什么想法吗?

更新解决方法

由于这似乎是NettyConnector的一个问题,我找到了一个解决方法。这不好,但似乎有效:

        String JMS_CONNECTION_FACTORY_JNDI = "jms/RemoteConnectionFactory";
        Context context = getApplicationManager().getConnectionHandler().getContext();
        TopicConnectionFactory cf = (TopicConnectionFactory) context.lookup(JMS_CONNECTION_FACTORY_JNDI);
        // TODO: Remove if fixed in Netty
        // THIS IS A PATCH SINCE NETTYCONNECTOR DOES NOT STRIP IPv6 SCOPE
        if (cf instanceof ActiveMQJMSConnectionFactory) {
            TransportConfiguration[] o = ((ActiveMQJMSConnectionFactory) cf).getStaticConnectors();
            for (TransportConfiguration tc : o) {
                String host = tc.getParams().get("host").toString();
                tc.getParams().put("host", stripScope(host));
            }
        }

stripScope定义为:

private String stripScope(String ipV6host) {
    // only if it contains a %
    if (ipV6host != null && ipV6host.contains("%")) {
        // Strip [ and ] if any
        if (ipV6host.charAt(0) == '[') {
            if (ipV6host.length() > 2 && ipV6host.charAt(ipV6host.length() - 1) == ']') {
                ipV6host = ipV6host.substring(1, ipV6host.length() - 1);
            } else {
                // no closing ] return input value
                return ipV6host;
            }
        }
        if (Character.digit(ipV6host.charAt(0), 16) != -1 || (ipV6host.charAt(0) == ':')) {
            // see if it is IPv6 address
            byte[] addr;
            if (IPAddressUtil.textToNumericFormatV4(ipV6host) == null
                    && (addr = IPAddressUtil.textToNumericFormatV6(ipV6host)) != null) {
                try {
                    return InetAddress.getByAddress(addr).getHostAddress();
                } catch (UnknownHostException e) {
                }
            }
        }
    }
    return ipV6host;
}

这需要进行测试......这只是第一个工作黑客...欢迎任何评论/更好的解决方案。

0 个答案:

没有答案