Performance


Quality of service will become an important attribute in distinguishing your service from others. Quality of service will correlate strongly to your service's over-all popularity. Performance is one aspect of quality of service and can be measured by latency and throughput. Latency is the roundtrip time, from sending a request to receiving a response. Throughput is the number of requests a Web service handles in a specified period.

Over time, many Web services will bump into limitations in the underlying transport protocols, such as HTTP. HTTP is a stateless protocol that only attempts best-effort delivery. This may create many problems for your service, because it does not guarantee that packets will arrive in the order in which they were sent, that all packets will make it to their destination, or that enough bandwidth is available. Several emerging protocols, such as Direct Internet Message Encapsulation (DIME), Reliable HTTP (HTTPR), and Blocks Extensible Exchange Protocol (BEEP), address latency and guaranteed delivery. Adoption of these protocols may take time.

In the meantime, if your service is not response-time sensitive, consider message queuing. Web services can use message queuing implementations based on Java Message Service (described in detail later) for invocations. A messaging approach will provide your service with a reliable, adaptable mechanism for asynchronous exchange of data throughout your enterprise. A message queue can make sure that a message is delivered once and only once. It will also deliver messages to the target as they arrive, without the receiver's having to request them.

One of the biggest slowdowns in performance is related to an XML parser's speed when reading a SOAP message. By its nature, XML does not allow for much size optimization. Because SOAP is based on XML, it has this limitation and more. Unlike regular XML, a SOAP message must include all typing information. Besides parsing this, the XML parser may also need to perform multiple parsing passes to extract the SOAP envelope and body from the SOAP packet.

Many XML parsers are bloated and require significant CPU and memory resources. Some support features such as validating whether a document is well formed, type checking, conversion, and so on. Many of the SOAP stacks are implementations of the Document Object Model (DOM), which is inherently slow to parse large messages. You could consider a nonvalidating, SAX-based SOAP implementation, which will reduce memory overhead and increase throughput.

XML has the side effect of increasing data—in many cases, by five times or more. Because SOAP uses XML as its payload, the best way to increase performance is to consider compressing the XML. In a Java-based Web service, this can be handled easily with a ZippedOutputStream, if your downstream Web services can also use this format. One of the factors to consider when compressing XML is to do it only when the CPU overhead required for compression is less than the network latency.

The best way to determine the performance characteristics of your service is to use a service proxy. Service proxies are used to hide any communications details from a client and are similar to stubs in Java RMI. Service proxies contain code specific to the bindings in the service interface. Listing 16.1 shows the WSDL for a simple timer service that returns the time it took to call another service.

Listing 16.1: WSDL for timer service

start example
 <?xml version="1.0" encoding="UTF-8"?> <definitions name="TimerService"   targetNamespace="http://www.flutebank.com/TimerService"   xmlns="http://schemas.xmlsoap.org/wsdl/"   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"   xmlns:tns="http://www.flutebank.com/TimerService"     xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <message name="IntimerRequest">   <part name="meth1_inType1" type="xsd:string"/> </message> <message name="OuttimerResponse">   <part name="meth1_outType" type="xsd:string"/> </message> <portType name="TimerService">   <operation name="timer">     <input message="IntimerRequest"/>     <output message="OuttimerResponse"/>   </operation> </portType> <binding name="TimerServiceBinding" type="TimerService">   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>   <operation name="time">     <soap:operation soapAction="urn:timerservice-service"/>     <input>       <soap:body           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"           namespace="urn:timerservice-service"           use="encoded"/>     </input>     <output>       <soap:body           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"           namespace="urn:timerservice-service" use="encoded"/>     </output>   </operation> </binding> <service       name="TimerService">   <documentation>Java Web services Architecture</documentation>   <port binding="TimerServiceBinding" name="TimerServicePort">     <soap:address location="http://www.flutebank.com:8080/soap/servlet/rpcrouter"/>   </port> </service> </definitions> 
end example

Many Web service toolkits will automatically generated a service proxy from WSDL. Creating a timer service requires modifying the generated code. Listing 16.2 contains modified code that simply wraps the call to the Web service through the invoke method.

Listing 16.2: Timer service proxy

start example
 import java.net.*; import java.util.*; import org.apache.soap.*; import org.apache.soap.encoding.*; import org.apache.soap.rpc.*; import org.apache.soap.util.xml.*; import com.flutebank.Timer; public class TimerServiceProxy {   private Call call = new Call();   private URL url = null;   private String SOAPActionURI = "";   private SOAPMaptimeRegistry smr = call.getSOAPMaptimeRegistry();    public TimerServiceProxy() throws MalformedURLException {      call.setTargetObjectURI("urn:timerservice-service");      call.setEncodingStyleURI("http://schemas.xmlsoap.org/soap/encoding/");      this.url = new URL("http://www.flutebank.com:8080/soap/servlet/rpcrouter");      this.SOAPActionURI = "urn:timerservice-service";     }      public synchronized void setEndPoint(URL url) {      this.url = url;     }      public synchronized URL getEndPoint() {       return url;     }      public synchronized String time (String meth1_inType1) throws SOAPException {       if (url == null) {         throw new SOAPException(Constants.FAULT_CODE_CLIENT, "A URL must be                                                                           specified");      }          call.setMethodName("time");      Vector params = new Vector();      Parameter meth1_inType1Param = new Parameter("meth1_inType1", String.class,                                                                  meth1_inType1, null);      params.addElement(meth1_inType1Param);      call.setParams(params);       // Start an instance of the flutebank Timer       Timer timer = new Timer();       timer.start();       Response res = call.invoke(url, SOAPActionURI);       // Stop the Timer       timer.stop();          // Calculate the difference in time       System.out.println("Response Time="+ timer.getDifference());       // Check for any errors in the response       if (res.generatedFault()) {         Fault fault = resp.getFault();         throw new SOAPException(fault.getFaultCode(), fault.getFaultString());        }       else       {         Parameter retValue = res.getReturnValue();         return (String)retValue.getValue();       }    } } 
end example

Quantifying performance bottlenecks in your service infrastructure will become a necessity. Timing each step in a Web service that uses a chain of Web services could also use the above approach.




Java Web Services Architecture
Java Web Services Architecture (The Morgan Kaufmann Series in Data Management Systems)
ISBN: 1558609008
EAN: 2147483647
Year: 2005
Pages: 210

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net