View Javadoc

1   // ========================================================================
2   // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // Licensed under the Apache License, Version 2.0 (the "License");
5   // you may not use this file except in compliance with the License.
6   // You may obtain a copy of the License at
7   // http://www.apache.org/licenses/LICENSE-2.0
8   // Unless required by applicable law or agreed to in writing, software
9   // distributed under the License is distributed on an "AS IS" BASIS,
10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  // See the License for the specific language governing permissions and
12  // limitations under the License.
13  // ========================================================================
14  
15  package org.mortbay.terracotta.servlet;
16  
17  import java.io.File;
18  import java.io.FileWriter;
19  import java.io.IOException;
20  import java.io.PrintWriter;
21  import java.util.Random;
22  import java.util.concurrent.CyclicBarrier;
23  import java.util.concurrent.ExecutorService;
24  import java.util.concurrent.Executors;
25  import java.util.concurrent.TimeUnit;
26  
27  import javax.servlet.ServletException;
28  import javax.servlet.http.HttpServlet;
29  import javax.servlet.http.HttpServletRequest;
30  import javax.servlet.http.HttpServletResponse;
31  import javax.servlet.http.HttpSession;
32  
33  import org.mortbay.jetty.HttpMethods;
34  import org.mortbay.jetty.Server;
35  import org.mortbay.jetty.client.ContentExchange;
36  import org.mortbay.jetty.client.HttpClient;
37  import org.mortbay.jetty.servlet.SessionHandler;
38  import org.mortbay.jetty.webapp.WebAppContext;
39  
40  /**
41   * @version $Revision: 1228 $ $Date: 2008-09-25 08:47:13 -0500 (Thu, 25 Sep 2008) $
42   */
43  public class TIMLightLoadTest
44  {
45      public static void main(String[] args) throws Exception
46      {
47          new TIMLightLoadTest().testLightLoad();
48      }
49  
50      public void testLightLoad() throws Exception
51      {
52          File warDir = new File(System.getProperty("java.io.tmpdir"), "lightLoad");
53          warDir.deleteOnExit();
54          warDir.mkdir();
55          File webInfDir = new File(warDir, "WEB-INF");
56          webInfDir.deleteOnExit();
57          webInfDir.mkdir();
58          File webXml = new File(webInfDir, "web.xml");
59          webXml.deleteOnExit();
60          String xml =
61                  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
62                  "<web-app xmlns=\"http://java.sun.com/xml/ns/j2ee\"\n" +
63                  "         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
64                  "         xsi:schemaLocation=\"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd\"\n" +
65                  "         version=\"2.4\">\n" +
66                  "\n" +
67                  "</web-app>";
68          FileWriter w = new FileWriter(webXml);
69          w.write(xml);
70          w.close();
71  
72          String contextPath = "/lightLoad";
73          String servletMapping = "/server";
74          int port1 = 8080;
75          Server server1 = new Server(port1);
76          WebAppContext context1 = new WebAppContext(warDir.getCanonicalPath(), contextPath);
77          context1.setSessionHandler(new SessionHandler());
78          context1.addServlet(TestServlet.class, servletMapping);
79          server1.setHandler(context1);
80          server1.start();
81          try
82          {
83              int port2 = 8181;
84              Server server2 = new Server(port2);
85              WebAppContext context2 = new WebAppContext(warDir.getCanonicalPath(), contextPath);
86              context2.setSessionHandler(new SessionHandler());
87              context2.addServlet(TestServlet.class, servletMapping);
88              server2.setHandler(context2);
89              server2.start();
90              try
91              {
92                  HttpClient client = new HttpClient();
93                  client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
94                  client.start();
95                  try
96                  {
97                      ContentExchange exchange1 = new ContentExchange(true);
98                      exchange1.setMethod(HttpMethods.GET);
99                      exchange1.setURL("http://localhost:" + port1 + contextPath + servletMapping + "?action=init");
100                     client.send(exchange1);
101                     exchange1.waitForDone();
102                     assert exchange1.getResponseStatus() == HttpServletResponse.SC_OK;
103                     String sessionCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
104                     assert sessionCookie != null;
105                     System.out.println("sessionCookie = " + sessionCookie);
106 
107                     ExecutorService executor = Executors.newCachedThreadPool();
108                     int clientsCount = 10;
109                     CyclicBarrier barrier = new CyclicBarrier(clientsCount + 1);
110                     int requestsCount = 100;
111                     Worker[] workers = new Worker[clientsCount];
112                     for (int i = 0; i < clientsCount; ++i)
113                     {
114                         workers[i] = new Worker(barrier, requestsCount, sessionCookie);
115                         workers[i].start();
116                         executor.execute(workers[i]);
117                     }
118                     // Wait for all workers to be ready
119                     barrier.await();
120                     long start = System.nanoTime();
121 
122                     // Wait for all workers to be done
123                     barrier.await();
124                     long end = System.nanoTime();
125                     long elapsed = TimeUnit.NANOSECONDS.toMillis(end - start);
126                     System.out.println("elapsed ms: " + elapsed);
127 
128                     for (Worker worker : workers) worker.stop();
129                     executor.shutdownNow();
130 
131                     // Perform one request to get the result
132                     ContentExchange exchange2 = new ContentExchange(true);
133                     exchange2.setMethod(HttpMethods.GET);
134                     exchange2.setURL("http://localhost:" + port1 + contextPath + servletMapping + "?action=result");
135                     exchange2.getRequestFields().add("Cookie", sessionCookie);
136                     client.send(exchange2);
137                     exchange2.waitForDone();
138                     assert exchange2.getResponseStatus() == HttpServletResponse.SC_OK;
139                     String response = exchange2.getResponseContent();
140                     System.out.println("get = " + response);
141                     assert response.trim().equals(String.valueOf(clientsCount * requestsCount));
142                 }
143                 finally
144                 {
145                     client.stop();
146                 }
147             }
148             finally
149             {
150                 server2.stop();
151             }
152         }
153         finally
154         {
155             server1.stop();
156         }
157     }
158 
159     public static class Worker implements Runnable
160     {
161         private final HttpClient client;
162         private final CyclicBarrier barrier;
163         private final int requestsCount;
164         private final String sessionCookie;
165 
166         public Worker(CyclicBarrier barrier, int requestsCount, String sessionCookie)
167         {
168             this.client = new HttpClient();
169             this.client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
170             this.barrier = barrier;
171             this.requestsCount = requestsCount;
172             this.sessionCookie = sessionCookie;
173         }
174 
175         public void start() throws Exception
176         {
177             client.start();
178         }
179 
180         public void stop() throws Exception
181         {
182             client.stop();
183         }
184 
185         public void run()
186         {
187             try
188             {
189                 // Wait for all workers to be ready
190                 barrier.await();
191 
192                 String contextPath = "/lightLoad";
193                 String servletMapping = "/server";
194                 Random random = new Random(System.nanoTime());
195 
196                 for (int i = 0; i < requestsCount; ++i)
197                 {
198                     boolean master = random.nextInt(2) > 0;
199                     int port = master ? 8080 : 8181;
200 
201                     ContentExchange exchange = new ContentExchange(true);
202                     exchange.setMethod(HttpMethods.GET);
203                     exchange.setURL("http://localhost:" + port + contextPath + servletMapping + "?action=increment");
204                     exchange.getRequestFields().add("Cookie", sessionCookie);
205                     client.send(exchange);
206                     exchange.waitForDone();
207                     assert exchange.getResponseStatus() == HttpServletResponse.SC_OK;
208                 }
209 
210                 // Wait for all workers to be done
211                 barrier.await();
212             }
213             catch (Exception x)
214             {
215                 throw new RuntimeException(x);
216             }
217         }
218     }
219 
220     public static class TestServlet extends HttpServlet
221     {
222         @Override
223         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
224         {
225             String action = request.getParameter("action");
226             if ("init".equals(action))
227             {
228                 HttpSession session = request.getSession(true);
229                 session.setAttribute("value", 0);
230             }
231             else if ("increment".equals(action))
232             {
233                 // Without synchronization, because it is taken care by Jetty/Terracotta
234                 HttpSession session = request.getSession(false);
235                 int value = (Integer)session.getAttribute("value");
236                 session.setAttribute("value", value + 1);
237             }
238             else if ("result".equals(action))
239             {
240                 HttpSession session = request.getSession(false);
241                 int value = (Integer)session.getAttribute("value");
242                 PrintWriter writer = response.getWriter();
243                 writer.println(value);
244                 writer.flush();
245             }
246         }
247     }
248 }