1
2
3
4
5
6
7
8
9
10
11
12
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
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
119 barrier.await();
120 long start = System.nanoTime();
121
122
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
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
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
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
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 }