3 Replies Latest reply on May 15, 2014 9:28 AM by jaikiran

    Custer node not anymore an EJBReceiver after restart

    jcavezian

      Hi,

       

      I have two Jboss 7.1.3.final instances as a cluster, server1 and server2.

      Both server deploy an application A.

      Server1 deploys a application B, client application, using EJBs of application A.

       

      Application B defines jboss-ejb-client.xml file :

      <jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2">
          <client-context
              deployment-node-selector="com.my.own.RoundRobinDeploymentNodeSelector">
              <ejb-receivers>
                  <remoting-ejb-receiver outbound-connection-ref="remote-server1" />
                  <remoting-ejb-receiver outbound-connection-ref="remote-server2" />
              </ejb-receivers>
          </client-context>
      </jboss-ejb-client>
      

       

      A startup, everything works fine. Application A's EJB calls from application B are round-robin balanced on server1 and server2.

      Now, server2 goes down. Obviously, application A's EJB calls from application B are processed on... server1 !

       

      After server2 is up again, I'm expecting the load-balancing to restart, but it's not. It will never be called again...

       

      What should be done to make application A on server2 as an eligible node again when the node selector is called ?

      Thank you for any help !

      Jerome

        • 1. Re: Custer node not anymore an EJBReceiver after restart
          jcavezian

          Please let me answer to myself...

          If not a bug, this is the way it is implemented.

          Good to add I was talking about SLSB EJBReceivers..

           

          Here is my explanation (actually what I understood)

           

          At boot time, during application deployment, EJBClientContext singleton is instanciated. The EJBClientContext.ejbReceiverAssociations are registered based based on remoting-ejb-receiver defined in META-INF/jboss-ejb-client.xml file.

           

          When a node goes down, those remoting-ejb-receivers are unregistered :

           

          EJBClientContext.unregisterEJBReceiver(final EJBReceiver receiver)
          

           

          is called.

           

          At this point, there seems to be no way JBoss registers again those EJBReceivers when the node comes up again.

           

           

          And here is a workaround, please tell me if there is another one, a little less tricky.

           

          To force reloading, the only solution I found is trying to lookup a none existing statefull EJB.

           

          try {
            //donwlevel API call to create a session on a statefull EJB
            EJBClient.createSession(Object.class, "", "", "", "");
          } catch (Exception e) {
            //obviously there is an exception
          

          }

           

           

          As the EJB we are looking up could not be found among known EJBReceivers, this stackcall invokes

           

          private Collection<EJBReceiver> getEJBReceivers(final String appName, final String moduleName, final String distinctName,
                                                              final boolean attemptReconnect) {
                  final Collection<EJBReceiver> eligibleEJBReceivers = new HashSet<EJBReceiver>();
                  synchronized (this.ejbReceiverAssociations) {
                      for (final Map.Entry<EJBReceiver, ReceiverAssociation> entry : this.ejbReceiverAssociations.entrySet()) {
                          if (entry.getValue().associated) {
                              final EJBReceiver ejbReceiver = entry.getKey();
                              if (ejbReceiver.acceptsModule(appName, moduleName, distinctName)) {
                                  eligibleEJBReceivers.add(ejbReceiver);
                              }
                          }
                      }
                  }
                  if (eligibleEJBReceivers.isEmpty() && attemptReconnect) {
                      // we found no receivers, so see if we there are re-connect handlers which can create possible
                      // receivers
                      this.attemptReconnections();
                      // now that the re-connect handlers have run, let's fetch the receivers (if any) for this app/module/distinct-name
                      // combination. We won't attempt any reconnections now.
                      eligibleEJBReceivers.addAll(this.getEJBReceivers(appName, moduleName, distinctName, false));
                  }
                  return eligibleEJBReceivers;
              }
          

           

          And as eligbleEJBReceivers is obviously empty as this EJB could not be found among registered EJBReceivers, reconnection attempt are triggered.

           

          Et voila !

          All RemotingEJBReceivers are registered again, and load-balancing is swingging as expected ;-)

          • 2. Re: Custer node not anymore an EJBReceiver after restart
            manmeetjboss

            Don't you think it has performance hit? We should look for alternative solution.

            • 3. Re: Custer node not anymore an EJBReceiver after restart
              jaikiran

              You can add a custom ClusterNodeSelector and in its implementation select any node that belongs to the cluster, even if that node is not connected. The EJB client library will do the connection once you select it in the ClusterNodeSelector implementation:

               

              ClusterNodeSelector (JBoss EJB client 1.0.5.Final API)

              https://github.com/wildfly/wildfly/blob/master/build/src/main/resources/docs/schema/jboss-ejb-client_1_2.xsd#L210