5 Replies Latest reply on Sep 1, 2011 8:32 PM by thunder.farmer

    How smart the ha-jndi proxy is and how to use the ha-jndi smart proxy smartly.

    thunder.farmer

      After two days' experiment, I think I get to know what happens exactly behind the scene about the ha-jndi smart proxy.

      Here I give out my understanding about the myth.

      I am talking about the scenario that standalone client runs in the different jvm.

      Any corrections or different understandings are welcome.

       

      In short, the ha-jndi proxy will NOT get updated about the cluster's changes unitl it connects to server.

      That means the smart proxy will get to know any change of cluster only when you perform lookkup.

       

      Say, there are 3 nodes in the cluster NodeA, NodeB and NodeC and all the nodes are live.

      you initialize the JNDI context like this:

       

                          Hashtable jndiEvn = new Hashtable();

                          jndiEvn.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");

                          jndiEvn.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");

                          jndiEvn.put(Context.PROVIDER_URL, "jnp://NodeA:1100,jnp://NodeB:1100,jnp://NodeC:1100");

      ctx = new InitialContext(jndiEvn);

       

      Currently the proxy create a rmi connection to the NodeA.

      So if we shutdown NodeB or NodeC and then perform a lookup, everything is fine.

      And after the lookup, the ha-jndi proxy realize that the NodeB or NodeC is down.

      But if you shutdown the NodeA which the proxy is currently connecting to, and then perform lookup, you will get CommunicationException caused by the scoet connection refused.

      Apparently the proxy is still trying to connect to NodeA.

      Don't be disappointed by the exception!

      Yes, you get an exception, but the same time you get a more smart proxy.

      Now the ha-jndi know the NodeA is down and turn to other live Nodes.

      So if you lookup the same jndi second, you will get it without any issue.

       

      So the conclusion is that if you want to achieve transparent failover, you need to do some extra work in your code to deal with extreme situaction where the node that proxy is currently connecting to is down.

       

      So the code should be like this:

                try {

                                    // lookuping will fail because the server which ha-jndi is currently connecting to is shutdown

                                    // but the ha-jndi smart proxy get a chance to to be updated about the cluster's changes.

                                    // next time, it will connect to the other server.

                                         ejbRemote = ctx.lookup(jndiName);

                          } catch (NamingException nex) {

                                    // this time, everything works fine because the ha-jndi proxy get updated from the last failure.

                                         try {

                                                        ejbRemote = ctx.lookup(jndiName);

                                         } catch (NamingException nex2) {

                                                        nex.printStackTrace();

                                         }

                          }

       

      A more interesting thing is that creating a new InitialContext doesn't resolve the problem above.

      I mean that if you try to get an uptodate ha-jndi proxy by creating a new jndi context for every lookup, it doesn't work.

      Seems the proxy get downloaded for the first time when jndi context is created.

      For e.g:

      Hashtable jndiEvn = new Hashtable();

      jndiEvn.put(...)

      IntialContext ctx =  new IntialContext();

      ctx.lookup(...)

       

      Thread.currentThread().sleep(1 * 60 * 1000);

      // during this period, current NodeA is down.

       

      IntialContext ctx =  new IntialContext();

      ctx.lookup(...); // here still you will get an CommunicationException.

      By creating a new ctx, you expect that the smart proxy knows the NodeA is down, but that's not it.

       

      attach my code for refernce

      Any comment is welcome.

        • 1. Re: How smart the ha-jndi proxy is and how to use the ha-jndi smart proxy smartly.
          thunder.farmer

          Hi,

           

          For anyone who have or will read this,

          First of all, my conclusion is WORNG,

          The JBoss EJB transparent failover works perfactly

          My issue is cluster is  NOT set up correctly

           

          Sorry for any confusing

          • 2. Re: How smart the ha-jndi proxy is and how to use the ha-jndi smart proxy smartly.
            fulgore11

            Hi Thunder Lei,

             

            What was wrong with your cluster configuration ?, I have the same problem. Although I have followed the "JBoss clustering" guide for clustered EJB,  my smart proxy/stub doesnt work correctly: if a node goes down, I have to look up again in order to connect  other node. My 'smart'  proxy doesnt detects the fail automatically. Could you  show me your final configuration and what did you do wrong at first?

             

            I hope you can help me... Thanks!.

            • 3. Re: How smart the ha-jndi proxy is and how to use the ha-jndi smart proxy smartly.
              wdfink

              You might use autodiscovery to avoid the configuration of all nodes at client side.

              Autodiscovery uses network multicast, it might be a bit difficult if the clients and the servers are not in the same network or separeted by a firewall.

               

              If you not want to use autodiscovery you should set true for the property 'jnp.disableDiscovery' to avoid unnecessary multicast and trouble.

              • 4. Re: How smart the ha-jndi proxy is and how to use the ha-jndi smart proxy smartly.
                fulgore11

                Hi,

                 

                This is my jboss.xml:

                 

                 

                <jboss>

                 

                   <unauthenticated-principal>nobody</unauthenticated-principal>

                   <enterprise-beans>

                    <session>

                         <ejb-name>ejbRemote</ejb-name>

                         <jndi-name>ejbRemote</jndi-name>

                          <invoker-bindings>

                            <invoker>

                               <invoker-proxy-binding-name>retryCluster</invoker-proxy-binding-name>

                               <jndi-name>ejbRemote</jndi-name>

                            </invoker>

                         </invoker-bindings>

                         <clustered>True</clustered>

                            <cluster-config>

                                <partition-name>DefaultPartition</partition-name>

                                <home-load-balance-policy>

                                    org.jboss.ha.framework.interfaces.RoundRobin

                                </home-load-balance-policy>

                                <bean-load-balance-policy>

                                    org.jboss.ha.framework.interfaces.RoundRobin

                                </bean-load-balance-policy>

                            </cluster-config>

                         <method-attributes>

                        </method-attributes>

                     </session>

                 

                   <invoker-proxy-bindings>

                     <invoker-proxy-binding>

                         <name>retryCluster</name>

                         <invoker-mbean>jboss:service=invoker,type=jrmpha</invoker-mbean>

                         <proxy-factory>org.jboss.proxy.ejb.ProxyFactoryHA</proxy-factory>

                         <proxy-factory-config>

                            <client-interceptors>

                               <home>

                                  <interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor>

                                  <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>

                                  <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>

                                  <interceptor>org.jboss.proxy.ejb.SingleRetryInterceptor</interceptor>

                                  <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>

                               </home>

                               <bean>

                                  <interceptor>org.jboss.proxy.ejb.StatelessSessionInterceptor</interceptor>

                                  <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>

                                  <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>

                                  <interceptor>org.jboss.proxy.ejb.SingleRetryInterceptor</interceptor>

                                  <interceptor>org.jboss.invocation.InvokerInterceptor</interceptor>

                               </bean>

                            </client-interceptors>

                         </proxy-factory-config>

                      </invoker-proxy-binding>

                   </invoker-proxy-bindings>

                 

                </jboss>

                 

                 

                and clients' jndi conf:

                 

                java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

                java.naming.factory.url.pkgs=jboss.naming:org.jnp.interfaces

                java.naming.provider.url=192.168.4.163:1100, 192.168.4.165:1100

                jnp.disableDiscovery=true

                 

                 

                run scripts:

                 

                call run -b 192.168.4.163 -c all 

                call run -b 192.168.4.165 -c all

                 

                 

                 

                but it doesnt work ...no failover and load balancing. Every time the node i'm connected to goes down the folowing exception is thrown :

                 

                org.jboss.invocation.ServiceUnavailableException: Service unavailable.

                    at org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxyHA.invoke(JRMPInvokerProxyHA.java:303)

                 

                so I have to perform lookup again to get my proxy updated. I'm using JBoss AS 4.2.2

                 

                 

                Thanks.

                • 5. Re: How smart the ha-jndi proxy is and how to use the ha-jndi smart proxy smartly.
                  thunder.farmer

                  Hi fulgore fulgore,

                   

                  I can't remember exactly what was the issue at that time.

                  What I can sure is that the tranparentive failover work perfectly.

                   

                  The differences are that I am using jboss 5.1.0 and I don't test against 4.2.2.

                   

                  your start up script and client jndi conf look fine.

                   

                  you can double check the jboss.xml, I am not clear on the jboss.xml for 4.2.2.

                  And you need to make sure your client is using the jndi conf you post above.

                  For 5.1.0, you just simply config the ejb to be clustered, either by jboss.xml or annotation

                   

                  <?xml version="1.0"?>

                  <jboss>

                            <enterprise-beans>

                                      <session>

                                                <ejb-name>ClusteredEJBName</ejb-name>

                                                <clustered>True</clustered>

                                      </session>

                            </enterprise-beans>

                  </jboss>

                   

                  I attach my code, hope it will help.

                   

                  Also you can upload your code, maybe I can have look.