7 Replies Latest reply on Nov 8, 2002 6:04 AM by gerwec

    SOAP call optimization

    morphace

      This is a follow-up of the initial thread

      http://www.jboss.org/modules/bb/index.html?module=bb&op=viewtopic&t=forums/ intention is to discuss different possibilities to make SOAP calls over http and low bandwidth connections faster.

      Our company is an ERP vendor and I am currently working on a thin client solution for our system.

      For this purpose I developed a server-side framework, which feeds some kind of browser (dynamic swing gui) on the client side.

      The (value) objects are delivered by an object broker on the server side, which is invoked from the client by SOAP calls.

      I use SOAP first of all, because it can use http/https as transport protocol (which easily passes firewalls).

      Our thin client will be used over high bandwidth connections (intranet) as well as over low bandwidth connections (over the internet for example) and that's why I am concerned about the SOAP call overhead.

      I invite everyone to discuss this issue, especially "Dr. Schorsch", who developed JBoss.net.

      Markus

        • 1. SOAP call optimization
          morphace

          A few days ago, I tested our thin client from my home office (with an ISDN (64 KBit/s) VPN connection over the internet to our main office, no compression).

          I was lucky with the results, except with the latency of
          the SOAP calls.

          At this point I have to mention, that the workload of my SOAP calls (the ValueObjects) are allready compressed (please forgive me, but I serialize them to a byte[], which is then gzipped and transported as base64Binary).

          This is not platform independent, I know, but platform independency is not my primary goal. I'll write a corresponding serializer later ... ;-)

          So, we are talking about the pure call overhead.

          The invocation of a simple calculator "web-service" (multiplies two numbers and returns the result) took about 1 sec. !?

          I tried to imagine, how the performance would look like, if I used many SOAP calls.

          I decided better not to imagine ...

          My first idea (of course) was, to compress the SOAP calls somehow and I studied the Axis documentation and learned, that this is not as easy as I thought, if I wanted to stay on top of http (please correct me, if I'm wrong).

          So I decided to test things systematically, to get out, if it is worth the case to implement some compression handlers ...

          • 2. SOAP call optimization
            morphace

            I took the JBoss 3.2.0beta for my tests and my little calculator service:

            public class TestService {
            public int calculate(int a, int b) {
            return a * b;
            }
            }

            I deployed the service and took the everage time of 100 calls(local, on the same machine, not over the wire).

            I got 350 msecs per call!

            I remember, that I had tested Apache SOAP longer ago and had 35 msecs per call !?

            As the service over http is invoked by a servlet, I decided to measure time consumption of a http GET against a servlet (again the everage of 100 invocations).

            I got about 180 msecs and was very surprised! I felt, that this was too slow, so I decided to run the same tests against the JBoss/Tomcat combination.

            I undeployed JBossWeb (Jetty) and deployed Tomcat 4.1 (from JBoss 3.0.4/Tomcat 4.1) to JBoss 3.2.0beta and ran my tests.

            The test with the servlet took 10 msecs now!

            The execution of the calculator took 70 msecs (which is much faster then before, but slower as my original Apache SOAP tests, why?)

            Why were my tests with Jetty as web-container so slow ?
            Is this a configuration problem ?

            Next, I ran the tests on the same config over my 64KBit wire and got about 530 msecs per call.

            This means, that the possible perfomance gain of compressed SOAP calls could be about 400 msecs per call, which is worth the case to think about.

            My question is now: is there someone, who implemented allready a compression handler over http with Axis ?

            I dived in the Axis source code and came to the following results:

            The response of the AxisServlet could be easily compressed by a corresponding servlet filter. I don't know, if this works with the HTTPRequest too.

            For the client, I'd have to re-implement HTTPSender, because most methods are private, so there is no chance to provide another (GZip decorated) Output- or InputStream implementation :-(

            The second possibility would be to compress only the SOAP message and let the http stuff as it is, but I don't know, if this will give much better results.

            Any other ideas ?

            TX
            Markus

            • 3. SOAP call optimization
              morphace

              Today I got out new things:

              1.

              When I take the average of 100 SOAP calls (calculator service) against the JBoss/Tomcat duo (on the same machine, not over the wire), 1 call takes only 22 msecs!

              The is because the 1st call takes about 460 msecs the following calls between 10 and 20 msecs.

              This is goood ...

              With JBoss/Jetty the average call takes 350 msecs.

              This is baaad ... but why is there this difference ?


              2.

              I used tcpmon (from the axis package) to get out the amout of data, that is flowing from the client to the server and vice versa.

              I got about roughly 700 bytes for both ways, that means about 1400 bytes per call.

              Over a 64KBit ISDN line (with VPN over the internet) the transfer should take about 200 msecs + the normal overhead of 20 msecs in average, let's say 250 msecs. In my opinion everthing up to 300 msecs would be ok.

              But as I mentioned before, an average call took about 500 msecs in my case.

              I got suspicious and measured the time to transfer a 740KB file from the main office to my machine. This took about 100 seconds, wich is perfect for a 64KBit line.

              So what was wrong ?

              The only thing, that I could imagine, was, that there is a problem to transfer small packets over the VPN-line.

              Then I tried the test over a direct dial-in connection (without VPN) to our office.

              The result was 280 msecs/per call; perfect!

              The VPN seems to have a latency and that's the explanation.

              Although my results were very good now, I tried to speed up things even more.

              I tried to use handlers, that compress and uncompress the SOAP message.

              I calculated a reduction of the message size to about 50% of the original size (450 bytes/237 bytes). This should give another 60 msecs per call.

              Unfortunatly, something is happening with my compressed bytes.

              When I try to uncompress the message on the "other side", I get an exception, that the bytestream is not GZip compressed.

              Here's the source:

              import java.io.ByteArrayOutputStream;
              import org.apache.axis.Message;

              import org.apache.axis.AxisFault;

              import org.apache.axis.Handler;
              import org.apache.axis.MessageContext;
              import org.apache.axis.handlers.BasicHandler;

              import java.util.zip.GZIPOutputStream;

              public class CompressionHandler extends BasicHandler {

              public CompressionHandler() {
              }

              public void invoke(MessageContext msgContext) throws AxisFault {
              try {
              System.out.println("compress");

              ByteArrayOutputStream bos = new ByteArrayOutputStream();
              GZIPOutputStream gz = new GZIPOutputStream(bos);

              Message msg = msgContext.getRequestMessage();

              gz.write(msg.getSOAPPartAsBytes());
              gz.close();
              bos.close();

              Message msg2 = new Message(bos.toByteArray());

              msgContext.setRequestMessage(msg2);

              System.out.println(msg2.getSOAPPartAsString());
              }
              catch (Exception e) {
              throw AxisFault.makeFault(e);
              }
              }

              }


              package axistest;

              import java.io.ByteArrayInputStream;
              import org.apache.axis.Message;

              import org.apache.axis.AxisFault;

              import org.apache.axis.Handler;
              import org.apache.axis.MessageContext;
              import org.apache.axis.handlers.BasicHandler;

              import java.util.zip.GZIPInputStream;

              public class DeCompressionHandler extends BasicHandler {

              public DeCompressionHandler() {
              }

              public void invoke(MessageContext msgContext) throws AxisFault {
              try {
              System.out.println("decompress");

              Message msg = msgContext.getRequestMessage();

              ByteArrayInputStream bis = new ByteArrayInputStream(msg.getSOAPPartAsBytes());
              GZIPInputStream gzis = new GZIPInputStream(bis);

              Message msg2 = new Message(gzis);
              msg2.getSOAPPartAsBytes();

              msgContext.setRequestMessage(msg2);

              gzis.close();
              bis.close();
              }
              catch (Exception e) {
              throw AxisFault.makeFault(e);
              }
              }

              }


              Any ideas ?


              • 4. Re: SOAP call optimization
                gerwec

                have you added the handlers correct to you web-service.xml file?


                ...


                ..









                c.u.
                gernot

                • 5. Re: SOAP call optimization
                  gerwec

                  I forget to asked. Have you set the transport and created a wsdd file on the client side?

                  c.u.
                  gernot

                  • 6. SOAP call optimization
                    morphace

                    Hi Gernot,

                    yes, I did (both).

                    Everything seems to work, the message is compressed on the client side, the server gets the message, but the content is different ...

                    It looks like a compressed string, but some bytes are exchanged.

                    I guess, that this has to do with the character set (UTF-8). Could this be the reason ?

                    c.u.
                    Markus


                    • 7. Re: SOAP call optimization
                      gerwec

                      Well!
                      it could. axis replaces the umlauts, etc. Are you sure that the client send the correct stuff?
                      You can also try to set your handler in axis-config.xml to be the first one. I'm not so sure if the standard handlers don't change something. You you tell were the message changes?

                      c.u.
                      gernot

                      ps. do you use the tcpmon? tried to switch it off? just guessing,.. ;-)