2015-08-10 7 views
1

Мы разрабатываем приложение Java-EE, работающее на Wildfly 8 в Wildfly-Openshift-Cartridge. Приложение Openshift предназначено для масштабирования, поэтому более одного узла JVM будет работать как кластер.Как открыть JChannel (JGroups) с помощью Openshift Wildfly 8 Cartridge

Связь между различными узлами, мне нравится использовать JGroups. Однако я не могу открыть новый JChannel, хотя сам JGroups работает. Само приложение также работает, если я развертываю приложение локально, например. 3 автономных экземпляра wildfly.

по умолчанию standalone.xml из wildfly-катриджей уже содержит конфигурацию JGroups:

.... 
<subsystem xmlns="urn:jboss:domain:jgroups:2.0" default-stack="tcp"> 
    <stack name="tcp"> 
     <transport type="TCP" socket-binding="jgroups-tcp"> 
      <property name="external_addr">${env.OPENSHIFT_GEAR_DNS}</property> 
      <property name="external_port">${env.OPENSHIFT_WILDFLY_CLUSTER_PROXY_PORT}</property> 
      <property name="bind_port">${env.OPENSHIFT_WILDFLY_CLUSTER_PORT}</property> 
      <property name="bind_addr">${env.OPENSHIFT_WILDFLY_IP}</property> 
      <property name="defer_client_bind_addr">true</property> 
     </transport> 
     <protocol type="TCPPING"> 
      <property name="timeout">30000</property> 
      <property name="initial_hosts">${env.OPENSHIFT_WILDFLY_CLUSTER}</property> 
      <property name="port_range">0</property> 
      <property name="num_initial_members">1</property> 
     </protocol> 
     <protocol type="MERGE2"/> 
     <protocol type="FD"/> 
     <protocol type="VERIFY_SUSPECT"/> 
     <protocol type="BARRIER"/> 
     <protocol type="pbcast.NAKACK"/> 
     <protocol type="UNICAST2"/> 
     <protocol type="pbcast.STABLE"/> 
     <protocol type="AUTH"> 
      <property name="auth_class">org.jgroups.auth.MD5Token</property> 
      <property name="token_hash">SHA</property> 
      <property name="auth_value">${env.OPENSHIFT_SECRET_TOKEN}</property> 
     </protocol> 
     <protocol type="pbcast.GMS"/> 
     <protocol type="UFC"/> 
     <protocol type="MFC"/> 
     <protocol type="FRAG2"/> 
     <!--protocol type="pbcast.STATE_TRANSFER"/> 
     <protocol type="pbcast.FLUSH"/--> 
    </stack> 
</subsystem> 
.... 

По этому, по умолчанию стек должен быть TCP - что имеет смысл, так как UDP мультикастинг не допускается в среде OpenShift.

Если я развернуть приложение на OpenShift (масштабируется с двумя ходовой), сам JGroups кажется общаться между JVM,: Выход из wildfly/журнала/server.log:

.... 
INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (ServerService Thread Pool -- 59) ISPN000078: Starting JGroups Channel 
INFO [stdout] (ServerService Thread Pool -- 59) 
INFO [stdout] (ServerService Thread Pool -- 59) ------------------------------------------------------------------- 
INFO [stdout] (ServerService Thread Pool -- 59) GMS: address=xxx.rhcloud.com/ejb, cluster=ejb, physical address=172.30.0.163:62417 
.... 
INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (Incoming-5,shared=tcp) ISPN000094: Received new cluster view: [xxx.rhcloud.com/ejb|4] (1) xxx.rhcloud.com/ejb] 
.... 
INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (Incoming-6,shared=tcp) ISPN000094: Received new cluster view: [yyyy.rhcloud.com/ejb|5] (2) [xxx.rhcloud.com/ejb, 55b89cd750044609f0000043-xx.rhcloud.com/ejb] 
... 

Это работает коробки, без какого-либо собственного программирования.

Но теперь я хочу открыть JChannel для отправки сообщений от одной JVM ко всем остальным.

... 
import org.jgroups.*; 
... 
public class MyNotifier extends ReceiverAdapter 
{ 
    ... 

    JChannel channel; 

    public void start() 
    { 
     try 
     { 
      channel = new JChannel(); 
      channel.setReceiver(this); 
      channel.connect("MyNotifier"); 
     } 
     catch (ChannelException e) 
     { 
      log.error("JGroups: Error starting channel.", e); 
     } 
    } 

    public void receive(Message msg) 
    { 
     // process message 
    } 

    public void send(DataObject data) 
    { 
     Message msg = new Message(null, null, data); 

     try 
     { 
      channel.send(msg); 
     } 
     catch (Exception e) 
     { 
      log.error("JGroups: Error sending message.", e); 
     } 
    } 

    public void viewAccepted(View new_view) 
    { 
     log.info("JGroups: View accepted: " + new_view); 
    } 
} 

Исключение возникает при channel = new JChannel():

INFO [stdout] (ServerService Thread Pool -- 82) 72190 [ERROR] MyNotifier: JGroups: Error starting channel. 
INFO [stdout] (ServerService Thread Pool -- 82) org.jgroups.ChannelException: failed to start protocol stack 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.JChannel.startStack(JChannel.java:1787) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.JChannel.connect(JChannel.java:413) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.JChannel.connect(JChannel.java:388) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at xxxxx.MyNotifier.start(MyNotifier.java:41) [classes:?] 
INFO [stdout] (ServerService Thread Pool -- 82) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jboss.as.ee.component.ManagedReferenceMethodInterceptor.processInvocation(ManagedReferenceMethodInterceptor.java:52) [wildfly-ee-8.2.0.Final.jar!/:8.2.0.Final] 
... 
INFO [stdout] (ServerService Thread Pool -- 82) Caused by: java.lang.Exception: problem creating sockets (bind_addr=localhost/127.0.0.1, mcast_addr=null) 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.protocols.UDP.start(UDP.java:238) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.stack.ProtocolStack.startStack(ProtocolStack.java:990) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.JChannel.startStack(JChannel.java:1784) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) ... 136 more 
INFO [stdout] (ServerService Thread Pool -- 82) Caused by: java.lang.IllegalArgumentException: port out of range:65536 
INFO [stdout] (ServerService Thread Pool -- 82) at java.net.InetSocketAddress.checkPort(InetSocketAddress.java:143) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at java.net.InetSocketAddress.<init>(InetSocketAddress.java:188) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at java.net.DatagramSocket.<init>(DatagramSocket.java:299) ~[?:1.8.0_45] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.util.DefaultSocketFactory.createDatagramSocket(DefaultSocketFactory.java:65) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.protocols.UDP.createEphemeralDatagramSocket(UDP.java:458) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.protocols.UDP.createSockets(UDP.java:342) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.protocols.UDP.start(UDP.java:234) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.stack.ProtocolStack.startStack(ProtocolStack.java:990) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) at org.jgroups.JChannel.startStack(JChannel.java:1784) ~[jgroups-2.12.1.Final.jar:2.12.1.Final] 
INFO [stdout] (ServerService Thread Pool -- 82) ... 136 more 

Кажется, что JChannel пытается использовать даже UDP. Но как я могу использовать его в качестве подсистемы в файле standalone.xml?

Дополнительная информация: Как я писал сверху, JChannel успешно создан, если я разворачиваю приложение на некоторые локальные запущенные экземпляры wildfly, используя многоадресную рассылку UDP. Затем я попытался применить локальную конфигурацию одного и того же стека, как и в OpenShift, с результатом, который он все еще работал, но даже с UDP. Похоже, что мой channel = new JChannel(); не использует настройки из конфигурации подсистемы. Но почему?

EDIT:

я понял, что конфигурация подсистемы, т.е. по умолчанию стек установленный в подсистеме не имеет ничего общего с тем, что new JChannel() будет использовать; поэтому я пытаюсь создать теперь свой собственный tcp.xml. Однако первая проблема заключается в том, как использовать переменные среды в этой конфигурации (которая расширяется до их значения), например. Мне нужно что-то вроде <TCP bind_addr=${env.OPENSHIFT_WILDFLY_IP}/>. Как я могу это достичь?

Для первого шага я попытался вставить починки правильные значения:

<config xmlns="urn:org:jgroups" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/JGroups-3.3.xsd"> 
    <TCP 
      external_addr="backend-evendingtest.rhcloud.com" 
      external_port="62417" 
      bind_port="7600" 
      bind_addr="127.11.122.129" 
      defer_client_bind_addr="true"/> 

    <TCPPING timeout="3000" 
      initial_hosts="backend-evendingtest.rhcloud.com[62417],55b89cd750044609f0000043-evendingtest.rhcloud.com[56432]" 
      port_range="0" 
      num_initial_members="1"/> 
    <MERGE2/> 
    <FD/> 
    <VERIFY_SUSPECT/> 
    <BARRIER/> 
    <pbcast.NAKACK2 
      use_mcast_xmit="false"/> 
    <UNICAST3/> 
    <pbcast.STABLE/> 
    <AUTH auth_class="org.jgroups.auth.MD5Token" 
      token_hash="SHA" 
      auth_value="2QVXd4rUYmxOtZNlxsJ7fBbWb4J8eFJup39PSC1IZck1JHDr_y4qUzFZVqUzLVZ7rDHnZWPtOpyY4pTrPAZ__D06GHHz5Uq9D5ZPMtyHPkZuvRh3cWchUX3JxA5Qsq4B"/> 
    <pbcast.GMS/> 
    <MFC/> 
    <FRAG2/> 

... но я не с Exception:

java.net.BindException: Permission denied 
     at java.net.PlainDatagramSocketImpl.bind0(Native Method) 
     at java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:94) 
     at java.net.DatagramSocket.bind(DatagramSocket.java:392) 
     at java.net.MulticastSocket.<init>(MulticastSocket.java:172) 
     at java.net.MulticastSocket.<init>(MulticastSocket.java:136) 
     at org.jgroups.util.DefaultSocketFactory.createMulticastSocket(DefaultSocketFactory.java:70) 
     at org.jgroups.stack.DiagnosticsHandler.start(DiagnosticsHandler.java:83) 
     at org.jgroups.protocols.TP.start(TP.java:1222) 
     at org.jgroups.protocols.TCP.start(TCP.java:82) 
     at org.jgroups.stack.ProtocolStack.startStack(ProtocolStack.java:952) 
     at org.jgroups.JChannel.startStack(JChannel.java:864) 

Почему somehting как 'createMulticastSocket' в этом следе? - Я не хочу использовать UDP/Multicasting ...

Заранее благодарим за помощь! - badera

+1

TCP.enable_diagnostics должен быть установлен в ложь. –

+0

Спасибо вам большое! Теперь JChannel можно создать успешно! – badera

ответ

1

новый JChannel() использует конфигурацию по умолчанию, которая является udp.xml (в JGroups JAR). Сообщение об ошибке, которое вы получаете, связано с тем, что JGroups не могут привязываться к 127.0.0.1:0 (эфемерный порт).

Я предлагаю повторно использовать канал, уже предоставленный Wildfly, см. [1] для деталей. IIRC, Wildfly 9 фактически выставляет канал JGroups, но это еще может не быть в 8 ...

[1] https://developer.jboss.org/wiki/ClusteringChangesInWildFly8

+0

Спасибо, Бела; запутанная вещь заключается в том, что мы уже определили стек по умолчанию в конфигурации подсистемы, но, я согласен, это не влияет на самоподготовленные JChannels. Поэтому я думаю, что вы имеете в виду, что я должен делать «channel = new JChannel ();' (для создания канала с одинаковыми свойствами стека)? Но как я могу ссылаться на такой канал? Я еще не нашел информацию об этом в вашей ссылке. – badera

+0

Поскольку я не нашел способ повторно использовать существующий канал дикой природы, я знаю, что пытаюсь создать свой собственный tcp.xml. Я отредактировал вопрос соответствующим образом. – badera

+0

TCP-канал, безусловно, работает, но такие переменные, как env.OPENSHIFT_WILDFLY_IP, должны быть установлены, например, через -Denv.OPENSHIFT_WILDFLY_IP = 1.2.3.4. –