Stress Testing Your BeansThe idea of performing stress or load tests is to be able to determine how many users the system can support without degrading and also how the system will degrade as the number of users increase. With load testing, you keep running tests, modifying your configuration, and then re-running the tests. You will start to see how different configurations help or hinder your application's capability to handle increased user loads. All applications have a breaking point where too many users can bring the system to its knees. The point of conducting load tests is to determine what that number is. Similar to performance tools, there are several good load-testing tools on the market. Table 18.2 lists a few of the most popular. Table 18.2. Several Load-Testing Tools
Caution Most of the load-testing tools in Table 18.2 require Windows NT, Windows 2000, or Unix systems. For most development shops , this is not a problem. However, if you plan to evaluate these at home, this is something to keep in mind. Because load testing is attempting to simulate multiple users, it's a little more complicated than just trying to simulate a single user. This is why using one of the tools listed in Table 18.2 is probably going to give you a more accurate idea of how your system will perform under heavy loads than you can get on your own. Most of them are designed to test from a Web site, although a few of them can test enterprise beans directly. Again, if you are pressed for time and would like to get an idea of the results, you can build a simple Java program that simulates multiple users. Note In a real-world scenario, application users would be using different machines to access the application. This simple approach should be no substitute for using a quality program to simulate real loads. The commercial products offer a great deal of flexibility and configuration options and usually can record scripts taken from real use of your application and be played back. This simple program should be used merely to give you a rough impression of the application's capability until you can use a much more complex set of tools. Listing 18.2 shows a very basic example of how to use threads to simulate more than one client accessing an EJB. Listing 18.2 Simple Example that Uses Threads to Simulate Multiple Clientsimport java.util.Collection; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import com.que.ejb20.auction.controller.AuctionHouse; import com.que.ejb20.auction.controller.AuctionHouseHome; public class AuctionHouseMultipleTest implements Runnable { // The number of clients to simulate public static final int NUMBER_OF_CLIENTS = 5; // Constructor public AuctionHouseMultipleTest() { super(); } // Returns a remote interface to the AuctionHouseBean private AuctionHouse getAuctionHouse() { Context initCtx = null; AuctionHouse house = null; try { // Create the initial context initCtx = new InitialContext(); Object obj = initCtx.lookup( "AuctionHouse" ); // Narrow and cast the object AuctionHouseHome auctionHouseHome = (AuctionHouseHome)PortableRemoteObject.narrow( obj, AuctionHouseHome.class ); // Create a remote reference and store it into the instance reference house = auctionHouseHome.create(); }catch(Exception ex ) { ex.printStackTrace(); }finally{ try{ if ( initCtx != null ){ initCtx.close(); } }catch( Exception ex ){ ex.printStackTrace(); } } // Return the remote reference return house; } /** * Test the enterprise bean's methods */ private void runTest( AuctionHouse house ) { try{ // record the start time long beginTime = System.currentTimeMillis(); // Invoke the method Collection auctions = house.getAllAuctions( 1, 10 ); // Record the end time long endTime = System.currentTimeMillis(); // Print out the time that the method took System.out.println( "Time: " + (endTime - beginTime) + " millisecs" ); }catch( Exception ex ){ System.out.println( "Problem running the test!" ); }finally{ // Clean up the remote reference try{ if ( house != null ) house.remove(); }catch( Exception ex ){ ex.printStackTrace(); } } } // Method required by the Runnable interface // This is the method that will run when start is called public void run() { // get the remote interface AuctionHouse house = getAuctionHouse(); if ( house != null ){ runTest( house ); }else{ // If there was a problem, just exit System.out.println( "Error creating AuctionHouse remote" ); System.exit( 0 ); } } // The startup method public static void main(String[] args) { // Create the correct number of threads and start each of them for ( int i = 1; i < NUMBER_OF_CLIENTS; i++ ) { AuctionHouseMultipleTest test = new AuctionHouseMultipleTest(); Thread thread = new Thread( test ); thread.start(); } } } The program in Listing 18.2 uses a constant number of clients to iterate through and create separate threads. Each thread creates a remote reference to the AuctionHouse EJB and invokes the getAllAuctions operation. The time it takes for each thread is printed to the console. Caution When doing simple thread tests such as the example in Listing 18.2, you must ensure that multiple threads are really executing at the same time. If a thread finishes too quickly, before other threads have a chance to execute, you might not really be testing all the concurrency issues. In some cases, you might have to use the yield method of the Thread class to help ensure that multiple threads execute at the same time. This example and the one in Listing 18.1 are overly simple. The main point of the examples is to show you how you can use a normal Java program to get yourself started in conducting performance and load testing for your enterprise beans. The most important point to remember when doing any type of testing is to start as early as possible and do as much as possible, time permitting. |