/* * Copyright (C) 2009 Camptocamp * * This file is part of MapFish Server * * MapFish Server is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MapFish Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with MapFish Server. If not, see <http://www.gnu.org/licenses/>. */ package integration; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethodBase; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.params.HttpConnectionManagerParams; import org.apache.log4j.*; import org.pvalsecc.misc.FileUtilities; import org.pvalsecc.misc.UnitUtilities; import java.io.File; import java.io.IOException; import java.util.TreeSet; /** * Simple program to test a tomcat print module under heavy load. */ public class HeavyLoad { private static final int NB_THREADS = 1; private static final int TIMEOUT = 3 * 60 * 1000; private static final String DEFAULT = "default"; static { BasicConfigurator.configure(new ConsoleAppender( new PatternLayout("%d{HH:mm:ss.SSS} [%t] %-5p %30.30c - %m%n"))); Logger.getRootLogger().setLevel(Level.INFO); //httpclient is a bit pesky about loading everything in memory... //disabling the warnings. Logger.getLogger(HttpMethodBase.class).setLevel(Level.ERROR); } public static final Logger LOGGER = Logger.getLogger(HeavyLoad.class); private static String url; private static HttpClient httpClient; private static String spec; private static final TreeSet<ServerStats> servers = new TreeSet<ServerStats>(); public static void main(String[] args) throws IOException { url = args[0] + "/create.json"; final String specFile = args[1]; for (int i = 2; i < args.length; i++) { String server = args[i]; servers.add(new ServerStats(server)); } if(servers.isEmpty()) { servers.add(new ServerStats(DEFAULT)); } MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); final HttpConnectionManagerParams params = connectionManager.getParams(); params.setSoTimeout(TIMEOUT); params.setConnectionTimeout(TIMEOUT); params.setDefaultMaxConnectionsPerHost(NB_THREADS); params.setMaxTotalConnections(NB_THREADS); httpClient = new HttpClient(connectionManager); spec = FileUtilities.readWholeTextFile(new File(specFile)); Thread[] threads = new Thread[NB_THREADS]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new Reader(), "reader-" + i); threads[i].start(); } for (int i = 0; i < threads.length; i++) { try { threads[i].join(); } catch (InterruptedException e) { } } } public static class Reader implements Runnable { public void run() { while (true) { doQuery(); } } private static void doQuery() { final ServerStats server; synchronized (servers) { server = servers.first(); servers.remove(server); server.addUsage(); servers.add(server); } try { PostMethod method = new PostMethod(url); method.setRequestHeader("Connection", "close"); method.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); if(!server.server.equals(DEFAULT)) { method.setRequestHeader("Cookie", "SRV=" + server.server + "; path=/"); } method.setRequestEntity(new StringRequestEntity(spec, "application/json", "utf-8")); LOGGER.info("doing query... server=" + server.server); long start = System.currentTimeMillis(); httpClient.executeMethod(method); if (method.getStatusCode() != 200) { LOGGER.error("Invalid status code: " + method.getStatusCode()); System.exit(-1); } method.getResponseBody(); final long duration = System.currentTimeMillis() - start; LOGGER.info("...query done in " + UnitUtilities.toElapsedTime(duration) + " server=" + server.updateStats(duration)); method.releaseConnection(); } catch (IOException e) { LOGGER.error("server=" + server, e); System.exit(-1); } } } private static class ServerStats implements Comparable<Object> { private final String server; private Integer curUsage = 0; private Integer totUsage = 0; private long totDuration = 0; public ServerStats(String server) { this.server = server; } public int compareTo(Object o) { if (!(o instanceof ServerStats)) { throw new RuntimeException(); } final ServerStats other = (ServerStats) o; int thisVal = curUsage; int anotherVal = other.curUsage; int result = thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1); if (result == 0) { result = server.compareTo(other.server); } return result; } public synchronized String updateStats(long duration) { totUsage++; totDuration += duration; String result = toString(); curUsage--; return result; } public synchronized String toString() { return String.format("%s avgTime=%s nbDone=%d curQ=%d", server, totUsage > 0 ? UnitUtilities.toElapsedTime(totDuration / totUsage) : "null", totUsage, curUsage); } public synchronized void addUsage() { curUsage++; } } }