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
// ========================================================================
15
package org.mortbay.terracotta.servlet;
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;
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;
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
import org.testng.annotations.Test;
42
* @version $Revision: 1319 $ $Date: 2008-11-14 00:55:54 +0100 (Fr, 14. Nov 2008) $
44
public class TIMLightLoadTest
47
public void testLightLoad() throws Exception
49
File warDir = new File(System.getProperty("java.io.tmpdir"), "lightLoad");
50
warDir.deleteOnExit();
52
File webInfDir = new File(warDir, "WEB-INF");
53
webInfDir.deleteOnExit();
55
File webXml = new File(webInfDir, "web.xml");
56
webXml.deleteOnExit();
58
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
59
"<web-app xmlns=\"http://java.sun.com/xml/ns/j2ee\"\n" +
60
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
61
" xsi:schemaLocation=\"http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd\"\n" +
62
" version=\"2.4\">\n" +
65
FileWriter w = new FileWriter(webXml);
69
Random random = new Random(System.nanoTime());
70
String contextPath = "/lightLoad";
71
String servletMapping = "/server";
72
int port1 = random.nextInt(50000) + 10000;
73
Server server1 = new Server(port1);
74
WebAppContext context1 = new WebAppContext(warDir.getCanonicalPath(), contextPath);
75
context1.setSessionHandler(new SessionHandler());
76
context1.addServlet(TestServlet.class, servletMapping);
77
server1.setHandler(context1);
81
int port2 = random.nextInt(50000) + 10000;
82
Server server2 = new Server(port2);
83
WebAppContext context2 = new WebAppContext(warDir.getCanonicalPath(), contextPath);
84
context2.setSessionHandler(new SessionHandler());
85
context2.addServlet(TestServlet.class, servletMapping);
86
server2.setHandler(context2);
90
HttpClient client = new HttpClient();
91
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
95
String[] urls = new String[2];
96
urls[0] = "http://localhost:" + port1 + contextPath + servletMapping;
97
urls[1] = "http://localhost:" + port2 + contextPath + servletMapping;
99
ContentExchange exchange1 = new ContentExchange(true);
100
exchange1.setMethod(HttpMethods.GET);
101
exchange1.setURL(urls[0] + "?action=init");
102
client.send(exchange1);
103
exchange1.waitForDone();
104
assert exchange1.getResponseStatus() == HttpServletResponse.SC_OK;
105
String sessionCookie = exchange1.getResponseFields().getStringField("Set-Cookie");
106
assert sessionCookie != null;
107
System.out.println("sessionCookie = " + sessionCookie);
109
ExecutorService executor = Executors.newCachedThreadPool();
110
int clientsCount = 50;
111
CyclicBarrier barrier = new CyclicBarrier(clientsCount + 1);
112
int requestsCount = 100;
113
Worker[] workers = new Worker[clientsCount];
114
for (int i = 0; i < clientsCount; ++i)
116
workers[i] = new Worker(barrier, requestsCount, sessionCookie, urls);
118
executor.execute(workers[i]);
120
// Wait for all workers to be ready
122
long start = System.nanoTime();
124
// Wait for all workers to be done
126
long end = System.nanoTime();
127
long elapsed = TimeUnit.NANOSECONDS.toMillis(end - start);
128
System.out.println("elapsed ms: " + elapsed);
130
for (Worker worker : workers) worker.stop();
131
executor.shutdownNow();
133
// Perform one request to get the result
134
ContentExchange exchange2 = new ContentExchange(true);
135
exchange2.setMethod(HttpMethods.GET);
136
exchange2.setURL(urls[0] + "?action=result");
137
exchange2.getRequestFields().add("Cookie", sessionCookie);
138
client.send(exchange2);
139
exchange2.waitForDone();
140
assert exchange2.getResponseStatus() == HttpServletResponse.SC_OK;
141
String response = exchange2.getResponseContent();
142
System.out.println("get = " + response);
143
assert response.trim().equals(String.valueOf(clientsCount * requestsCount));
161
public static class Worker implements Runnable
163
private final HttpClient client;
164
private final CyclicBarrier barrier;
165
private final int requestsCount;
166
private final String sessionCookie;
167
private final String[] urls;
169
public Worker(CyclicBarrier barrier, int requestsCount, String sessionCookie, String[] urls)
171
this.client = new HttpClient();
172
this.client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
173
this.barrier = barrier;
174
this.requestsCount = requestsCount;
175
this.sessionCookie = sessionCookie;
179
public void start() throws Exception
184
public void stop() throws Exception
193
// Wait for all workers to be ready
196
Random random = new Random(System.nanoTime());
197
for (int i = 0; i < requestsCount; ++i)
199
int urlIndex = random.nextInt(urls.length);
201
ContentExchange exchange = new ContentExchange(true);
202
exchange.setMethod(HttpMethods.GET);
203
exchange.setURL(urls[urlIndex] + "?action=increment");
204
exchange.getRequestFields().add("Cookie", sessionCookie);
205
client.send(exchange);
206
exchange.waitForDone();
207
assert exchange.getResponseStatus() == HttpServletResponse.SC_OK;
210
// Wait for all workers to be done
215
throw new RuntimeException(x);
220
public static class TestServlet extends HttpServlet
223
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
225
String action = request.getParameter("action");
226
if ("init".equals(action))
228
HttpSession session = request.getSession(true);
229
session.setAttribute("value", 0);
231
else if ("increment".equals(action))
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);
238
else if ("result".equals(action))
240
HttpSession session = request.getSession(false);
241
int value = (Integer)session.getAttribute("value");
242
PrintWriter writer = response.getWriter();
243
writer.println(value);