6 Replies Latest reply on Sep 6, 2011 3:02 AM by chengwen

    EJB3 is slower than EJB2

    chengwen

      Hello,all.

       

      I am trying to migrate ejb2 to ejb3 these days. But I found that the ejb functions are slower after the miagration when I try to access ejb form a remote client.

       

      My environment: JBoss 6.0.0.0 final. EJB3. win server2008, 64bit

       

      Here is my code:

       

      the ejb in the server:

       

      @Stateless
      @Remote(ReflectEJB.class)
      @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843")
      public class ReflectEJBBean implements ReflectEJB
      {
          public void login(String name, String pwd){
            .........
          } 
      }
      

       

      the test code in the remote client:

       

       

      try {
      
                Properties jndiProps = new Properties();
                jndiProps.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
                jndiProps.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
                jndiProps.put("java.naming.provider.url",url);
      
                long time1 = System.currentTimeMillis();
                System.out.println("begin to connect:");
      
                InitialContext ctx = new InitialContext(jndiProps);       
      
                ReflectEJB  ejb = (ReflectEJB) ctx.lookup("ReflectEJBBean/remote");
      
                long time2 = System.currentTimeMillis();
                System.out.println(connect finished,time (ms):" + (time2 - time1));         
      
                ejb.login(name,pwd);
                long time3 = System.currentTimeMillis();
                System.out.println(login in finished,time (ms):" + (time3 - time2));       
      
            }
            catch (NamingException e) {
                e.printStackTrace();
          }
      }
      

       

      The test result in two different remote clients:

       

      machine1, win7 32bit, ip address 10.26.13.202

       

      begin to connect:
      connect finished,time (ms):2628
      login in finished,time (ms):583
      

       

      machine2, windows xp, ip address 10.26.13.82

       

      begin to connect:
      connect finished,time (ms):10172
      login in finished,time (ms):9437
      

       

      When I run the test code on the same machine of the server, the result is:

       

      begin to connect:
      connect finished,time (ms):2445
      login in finished,time (ms):109
      

       

      Take a look at the results in machine2 . The ejb performance is terrible.

      After I found that machine2 is slow, I tried serveral other machines, it turned out that machine2 is not the only machine that got the terrible performance.

       

      I wonder why the ejb3 is slow in some machine. I have to improve the slow performance, but I have no idea about how.

       

      Anyone please tell me any possible reason?

       

      Thanks very, very much.

        • 1. Re: EJB3 is slower than EJB2
          jaikiran

          There might be many reasons for the performance numbers you are getting. Can't say which, without looking at the details, including the code in the login method of the EJB and other resources involved (like any DB).

          • 2. Re: EJB3 is slower than EJB2
            chengwen

            Thanks jarkiran.

             

            I changed the code in the login method to only "System.out.println("");" , but it still took nearly 12 seconds to finish the lookup() method.

             

            I tried two computers with differen OS as the server to exclude the reason of computer hardware itself. They both got the problem.

            The following is some details. Please help me to see if there is any possible reason.

             

            Server

             

            Computer:   Intel(R) Xeon(R) CPU R5506 @2.13GHz

                                RAM : 4GB

            OS   :           Win7 64bit

            JBoss :        Jboss 6.0.0.0 final

             

            startup parameters:

            捕获.PNG

             

            The code of ReflectEJBBean.java in ejb.jar:

             

            @Stateless
            @Remote(ReflectEJB.class)
            @RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843")
            public class ReflectEJBBean implements ReflectEJB
            {
                public void login(String name, String pwd){
                  System.out.println("login");
                } 
            }
            

             

            The jboss.xml in the META-INF folded in ejb.jar:

             

            <?xml version="1.0" encoding="utf-8"?>
            
            <jboss xmlns="http://www.jboss.com/xml/ns/javaee"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
                                        http://www.jboss.org/j2ee/schema/jboss_5_0.xsd"
                         version="5.0">
            
              <enterprise-beans>
                 <session>
                   <ejb-name>ReflectEJBBean</ejb-name>
                   <remote-binding>
                       <jndi-name>ReflectEJBBean/remote</jndi-name>
                       <client-bind-url>sslsocket://${java.rmi.server.hostname}:3843</client-bind-url>
                   </remote-binding>       
                 </session>
              </enterprise-beans>
            
            </jboss>
            

             

            The ejb3-connectors-jboss-beans.xml in %jboss_home%/server/default/deploy:

             

            <?xml version="1.0" encoding="UTF-8"?>
            <!--
            
              EJB3 Connectors
            
            -->
            
            <deployment xmlns="urn:jboss:bean-deployer:2.0">
                <!--  We don't want the AOPDependencyBuilder  -->
                <annotation>@org.jboss.aop.microcontainer.annotations.DisableAOP</annotation>
            
              <!--
            
                JBoss Remoting Connector
            
                Note: Bean Name "org.jboss.ejb3.RemotingConnector" is used
                as a lookup value; alter only after checking java references
                to this key.
            
              -->
              <bean name="org.jboss.ejb3.RemotingConnector"
                class="org.jboss.remoting.transport.Connector">
            
                <property name="invokerLocator">
            
                  <value-factory bean="ServiceBindingManager"
                    method="getStringBinding">
                    <parameter>
                      jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3
                    </parameter>
                    <parameter>
                      <null />
                    </parameter>
                    <parameter>socket://${hostforurl}:${port}?timeout=300000</parameter>
                    <parameter>
                      <null />
                    </parameter>
                    <parameter>3873</parameter>
                  </value-factory>
            
                </property>
                <property name="serverConfiguration">
                  <inject bean="ServerConfiguration" />
                </property>
              </bean>
            
              <!-- Remoting Server Configuration -->
              <bean name="ServerConfiguration"
                class="org.jboss.remoting.ServerConfiguration">
                <property name="invocationHandlers">
                  <map keyClass="java.lang.String" valueClass="java.lang.String">
                    <entry>
                      <key>AOP</key>
                      <value>
                        org.jboss.aspects.remoting.AOPRemotingInvocationHandler
                      </value>
                    </entry>
                  </map>
                </property>
              </bean>
            
              <bean name="EJB3SSLRemotingConnector" class="org.jboss.remoting.transport.Connector"> 
                <property name="invokerLocator">sslsocket://${jboss.bind.address}:3843</property>  
                <property name="serverConfiguration"> 
                  <inject bean="ServerConfiguration"/> 
                </property>  
                <property name="serverSocketFactory"> 
                  <inject bean="sslServerSocketFactory"/> 
                </property> 
              </bean>  
              <bean name="sslServerSocketFactory" class="org.jboss.security.ssl.DomainServerSocketFactory"> 
                <constructor> 
                  <parameter> 
                    <inject bean="EJB3SSLDomain"/> 
                  </parameter> 
                </constructor> 
              </bean>  
              <bean name="EJB3SSLDomain" class="org.jboss.security.plugins.JaasSecurityDomain"> 
                <constructor> 
                  <parameter>EJB3SSLDomain</parameter> 
                </constructor>  
                <property name="keyStoreURL">../conf/server.keystore</property>  
                <property name="keyStorePass">1234567a</property> 
              </bean> 
            
            
            </deployment>
            

             

            And I changed naming-jboss-beans.xml in %jboss_home%/server/default/deploy for some reason:

             

             

            <?xml version="1.0" encoding="UTF-8"?>
            <deployment xmlns="urn:jboss:bean-deployer:2.0">
            
                <!-- ==================================================================== -->
                <!-- Remote interface to JNDI, JNDI util and legacy beans: $Id:$          -->
                <!-- ==================================================================== -->
            
                <bean name="LookupPool">
                    <constructor factoryMethod="newFixedThreadPool"
                        factoryClass="java.util.concurrent.Executors">
                        <!-- At least 2 threads are required -->
                        <parameter>2</parameter>
                    </constructor>
                </bean>
            
                <bean name="RemoteNamingBean" class="org.jnp.server.Main">
                    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss:service=Naming", exposedInterface=org.jnp.server.MainMBean, registerDirectly=true)</annotation>
            
                    <property name="namingInfo"><inject bean="LocalNamingBean" /></property>
            
                    <!-- The call by value mode. true if all lookups are unmarshalled using
                        the caller's TCL, false if in VM lookups return the value by reference. -->
                    <property name="callByValue">false</property>
            
                    <!-- The listening port for the bootstrap JNP service. Set this to -1
                        to run the NamingService without the JNP invoker listening port. -->
                    <property name="port">
                        <value-factory bean="ServiceBindingManager"
                            method="getIntBinding">
                            <parameter>jboss:service=Naming</parameter>
                            <parameter>Port</parameter>
                        </value-factory>
                    </property>
            
                    <!-- The bootstrap JNP server bind address. This also sets the default
                        RMI service bind address. Empty == all addresses -->
                    <property name="bindAddress">${java.rmi.server.hostname}</property>
            
                    <!-- The port of the RMI naming service, 0 == anonymous -->
                    <property name="rmiPort">
                        <value-factory bean="ServiceBindingManager" method="getIntBinding">
                            <parameter>jboss:service=Naming</parameter>
                            <parameter>RmiPort</parameter>
                        </value-factory>
                    </property>
            
                    <!-- The RMI service bind address. Empty == all addresses  -->
                    <property name="rmiBindAddress">${java.rmi.server.hostname}</property>
            
                    <!-- Set the java.rmi.server.hostname system property to rmiBindAddress -->
                    <property name="enableRmiServerHostname">true</property>
            
                    <!-- The thread pool service used to control the bootstrap lookups -->
                    <property name="lookupExector"><inject bean="LookupPool"/></property>
                </bean>
            
                <bean name="JndiViewBean" class="org.jboss.naming.JNDIView">
                    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss:service=JNDIView", exposedInterface=org.jboss.naming.JNDIViewMBean, registerDirectly=true)</annotation>
            
                    <!-- The HANamingService service name -->
                    <property name="HANamingService">jboss:service=HAJNDI</property>
                </bean>
            
                <!-- An obsolete bean only needed if using legacy detached invoker access,
                    or the createAlias/removeAlias operations
                -->
                <bean name="NamingService" class="org.jboss.naming.NamingService">
                    <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss:service=NamingBeanImpl", exposedInterface=org.jboss.naming.NamingServiceMBean, registerDirectly=true)</annotation>
            
                    <!--  An example of using the unifed invoker as the transport.
                        <depends optional-attribute-name="InvokerProxyFactory"
                        proxy-type="attribute">jboss:service=proxyFactory,type=unified,target=Naming</depends>
                    -->
                    <property name="namingInfo"><inject bean="RemoteNamingBean"/></property>
                    <!-- Do not start the injected naming bean -->
                    <property name="startNamingBean">false</property>
                </bean>
            
                <bean name="NamingProviderURLWriter"
                  class="org.jboss.naming.NamingProviderURLWriter">
            
                    <property name="server"><inject bean="JBossServer"/></property>
                    <property name="bootstrapAddress"><inject bean="RemoteNamingBean" property="bindAddress"/></property>
                    <property name="bootstrapPort"><inject bean="RemoteNamingBean" property="port"/></property>
                </bean>
            
            </deployment>
            

             

            The testing code:

             

            public static void main(String[] args) {
            
                  try {
                      
                      System.setProperty("javax.net.ssl.trustStore", "../conf/console.truststore");
                      System.setProperty("javax.net.ssl.trustStorePassword", "12345678");
                      
                      Properties jndiProps = new Properties();
                      jndiProps.put("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");
                      jndiProps.put("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
                      jndiProps.put("java.naming.provider.url","10.26.11.1:1099");
                     
                      
                       InitialContext ctx = new InitialContext(jndiProps);
                       
                       long time1 = System.currentTimeMillis();
                       System.out.println("begin:");
                       ReflectEJB bean  = (ReflectEJB) ctx.lookup("ReflectEJBBean/remote");
            
                       long time2 = System.currentTimeMillis();
                       System.out.println("connect(ms):" + (time2 - time1));
                                 
                       String result = bean.login();
                       
                       long time3 = System.currentTimeMillis();
                       
                       System.out.println("login(ms):" + (time3 - time2) );
                       
                       System.out.println("result="+result);
                       
                      } catch (Exception e) {
                       e.printStackTrace ();
                      }
              }
            

             

             

            .

            • 3. Re: EJB3 is slower than EJB2
              chengwen

              And the network speed of the server computer is not slow. When I ping the server form the client computer, I got tims<1ms TTL=127

               

              So, what's the problem?

               

              network?

              computer?

              jvm parameters?

              jboss parameters?

              ejb code?

               

              Please tell me the possible reason. Or tell me how I can indentify the reason.

              Is that "11 seconds lookup" a normal speed? If it isn't, what is the normal speed of the lookup function?

              • 4. Re: EJB3 is slower than EJB2
                chengwen

                Hello jaikiran

                 

                I think I have found the bottleneck.

                 

                I tried to remove the SSL configuration from the ejb. Than the speed of the response got a great change.

                 

                The configuration:

                 

                The code of ReflectEJBBean.java in ejb.jar:

                 

                @Stateless
                @Remote(ReflectEJB.class)
                //@RemoteBinding(clientBindUrl="sslsocket://0.0.0.0:3843")
                public class ReflectEJBBean implements ReflectEJB
                {
                    public void login(String name, String pwd){
                      System.out.println("login");
                    }
                }

                 

                And I removed the jboss.xml from the ejb.jar.

                Other configurations were the same.

                 

                With SSL:

                begin to connect:
                connect finished,time (ms):10172
                login in finished,time (ms):9437

                 

                Without SSL:

                begin to connect:
                connect finished,time (ms):613
                login in finished,time (ms):66

                 

                Compared to the 0.6 second, after adding SSL to ejb, the cost increased to 10 second. It is more than 100 times  slower.

                I am not sure, is SSL really cost that much? Or is there something wrong with my configuration of SSL ?

                 

                Please give me some advise to move on. Thanks very much.

                • 5. Re: EJB3 is slower than EJB2
                  wdfink

                  yes, EJB3 is slower than EJB2 but only if you measure the duration of the overhead, mean the time for client-server communication including the method preparation.

                  I measured this (I think with 5.1) and a ping method (no business code) will take around 50% more time, but remember this are nanos and in case of business code it will be negligible.

                   

                  For SSL I can't remember the exact times but as I remember it is similar to the EJB2-EJB3 differences or less.

                  • 6. Re: EJB3 is slower than EJB2
                    chengwen

                    Thanks, Wolf.

                     

                    I think you mean that "ejb 3 + ssl is slower , but it is not obvious, so that it can be ingored".

                    But now my problem is, in ejb3 , without ssl, the lookup function cost 0.6 seconds. But with ssl, it cost 11 seconds. The difference is so great that it can not be ingored.  The ejb is nearlly unavailable after adding SSL.

                     

                    Maybe I should change the title from "EJB3 is slower than EJB2" to "SSL makes EJB3 very very slow". 

                     

                    I wonder why.  What's wrong with my configuration of SSL ? Or what happened?