Tuesday, June 30, 2009

Java tool for Web Service load testing

Scenarios where real-time communication with a web service-end user is imminent, it is imperative to test the service for its ability to take up the load. This may have the following benefits:

1. More scalable and robust service design: If a service's threshold limit of fulfilling the simultaneous requests is, say n, that may respond to the end user(s) in a reasonable amount of time, any extra user will be timed-out/errored out by the service. This problem can be alleviated, if not fully eliminated, by increasing the server's resources and hence reserving extra memory/processes to serve those "extra" users.
2. Business benefits: Any such load testing will ensure a seamless integration between the systems in the context for a set number of "extra" loads on the service. As it is true with most of the successful integration solution, this will make the concerned business process more effecient and smooth leading to increased revenue. This can be explained by an example:
If a CRM application, which is being operated by an end user GUI application, is trying to use back-end web service for submissions/queries, multiple users can hit the "Submit" button simultaneuously. All of the users, must get the response within a reasonable wating time for this integration to be successful.

Technical Details:
Following is the brief summary of what this tool does technically:
1. Reads a property file to get the information like: host, end-point, authentication information, request file(s) location, response file(s) location, log file(s) location, etc.
2. Creates n number of threads (Based on the number of request files). Initialize each one of them with the details mentioned in the above point. Also, as each thread reads exactly one request file, wrap it up with SOAP message.
3. Once the threads are initialized as mentioned above, each of them is run at one go.
4. Each thread will then tries to contact the host and push the HTTP requests at the same time.

The details follow:
I have used the following special Java APIs to build the said tool:
- Java 5 multithreading API: to make sure that once all the client threads are created, they (try) to hit the service at one go. this utilises the CountDownLatch object.
- Java Networking API: to connect any of the threads with the remote server and communicate with the service end-point. At first, I tried using the SOAP API but failed as some of the HTTP messages being returned by the server was not in the SOAP format but in the HTML format.

Main highlights of the classes used: Following are the lists of the custom classes and some (not all) of their properties and methods.

  • Main Class:
GenericWSClientThreadExecutor: Has main method to prepare the worker threads for their tasks.

Attributes:
- java.util.Properties props //Reading propery file and extracting the configuration information.
- int threads //Number of threads or requests to be sent at a time.

Methods:
- init() //Initialize the config parameters from the file.
- execute() //Create threads and start them. Also contact a logger to log the performances.

  • Thread Class:
GenericWSClientThread implements Runnable: Represents one worker.

Attributes:
//Keep track of the number of threads created and those that have finished the job.
- CountDownLatch startLatch, endLatch
- HTTPClient client //An object that will make the actual communication with the server.

Methods:
- parseResponse(String response) //Parses the response to look for the HTTP status.
- createResponseFile(String fileName) //To create the correspondiong thread's response file.
- run() // Implementation of Runnable.run. This reads the request, initialise HTTPClient object and communicates with end-point using the other properties set for this thread.
//Handle the exceptions and HTTP status code appropriately.

  • Communicator Class:
HTTPClient: To communicate with server.

Attributes:
- int connectionTimeout //Timeout while contacting host.
- int readTimeout //Timeout while reading response from stream sent by the host.

Methods:
- encode(String source) //To encode authentication information string into Base64 Encoding.
- String invokeWS(String SOAPURL, byte[] payloadRequest, String SOAPAction, String user, String passCode) //Prepare HTTPConnection, set request headers and body and send to host.
//Also throws appropriate exception to the worker thread.

  • Other Utility Classes:
1. PerformanceTestRecorder - Once all the threads are finished, open a file stream and record the performance of each thread along-with their IDs and names.
2. ThreadRecord - A bean that may represent one thread record in the aforementioned performance record file.
3. PropertyReader - To read simple or XML property file.
4. WSUtil - To convert String to SOAPMessage, SOAPMessage object to string, etc.
5. Exception classes - Meaningful exceptions like, RetryException, MovedPermanentlyException, etc can be formed based on the HTTP response code.

Improvements needed:
1. Problem handling the status code 301: The client loses authentication information while it is being re-directed to specific URL by the internal implementation of HTTPURLConnection. This eventually results in HTTP error code 401 Unauthorized. I tried to get to the level of Socket API to formulate requests and response, but the performance became worse and the connection was getting timed out every 30 seconds. On top of this, because it is not the part of the IOException when using sockets, the client would never know what is happening to its specific request, even if it tries multiple times. It is possible that the request is being proessed in the background while the client keeps sending the request again and again.

Welcome to my blogs

The contents here are my independent point of view. They reflect my thoughts, experience in my professional and social life.

Search This Blog