PageRenderTime 50ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java

https://bitbucket.org/beginnerjyh/jetty.project
Java | 360 lines | 309 code | 34 blank | 17 comment | 33 complexity | 43ae49d7ffa64209d4992e7fc69b1018 MD5 | raw file
  1. //
  2. // ========================================================================
  3. // Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
  4. // ------------------------------------------------------------------------
  5. // All rights reserved. This program and the accompanying materials
  6. // are made available under the terms of the Eclipse Public License v1.0
  7. // and Apache License v2.0 which accompanies this distribution.
  8. //
  9. // The Eclipse Public License is available at
  10. // http://www.eclipse.org/legal/epl-v10.html
  11. //
  12. // The Apache License v2.0 is available at
  13. // http://www.opensource.org/licenses/apache2.0.php
  14. //
  15. // You may elect to redistribute this code under either of these licenses.
  16. // ========================================================================
  17. //
  18. package org.eclipse.jetty.server;
  19. import static org.junit.Assert.*;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.net.InetAddress;
  23. import java.net.Socket;
  24. import java.util.Random;
  25. import java.util.Timer;
  26. import java.util.TimerTask;
  27. import javax.servlet.AsyncContext;
  28. import javax.servlet.AsyncEvent;
  29. import javax.servlet.AsyncListener;
  30. import javax.servlet.DispatcherType;
  31. import javax.servlet.ServletException;
  32. import javax.servlet.http.HttpServletRequest;
  33. import javax.servlet.http.HttpServletResponse;
  34. import org.eclipse.jetty.server.handler.HandlerWrapper;
  35. import org.eclipse.jetty.toolchain.test.AdvancedRunner;
  36. import org.eclipse.jetty.toolchain.test.annotation.Stress;
  37. import org.eclipse.jetty.toolchain.test.PropertyFlag;
  38. import org.eclipse.jetty.util.IO;
  39. import org.eclipse.jetty.util.log.Log;
  40. import org.eclipse.jetty.util.log.Logger;
  41. import org.eclipse.jetty.util.thread.QueuedThreadPool;
  42. import org.junit.After;
  43. import org.junit.Before;
  44. import org.junit.Test;
  45. import org.junit.runner.RunWith;
  46. @RunWith(AdvancedRunner.class)
  47. public class AsyncStressTest
  48. {
  49. private static final Logger LOG = Log.getLogger(AsyncStressTest.class);
  50. protected QueuedThreadPool _threads=new QueuedThreadPool();
  51. protected Server _server = new Server(_threads);
  52. protected SuspendHandler _handler = new SuspendHandler();
  53. protected ServerConnector _connector;
  54. protected InetAddress _addr;
  55. protected int _port;
  56. protected Random _random = new Random();
  57. private final static String[][] __paths =
  58. {
  59. {"/path","NORMAL"},
  60. {"/path/info","NORMAL"},
  61. {"/path?sleep=<PERIOD>","SLEPT"},
  62. {"/path?suspend=<PERIOD>","TIMEOUT"},
  63. {"/path?suspend=60000&resume=<PERIOD>","RESUMED"},
  64. {"/path?suspend=60000&complete=<PERIOD>","COMPLETED"},
  65. };
  66. @Before
  67. public void init() throws Exception
  68. {
  69. _server.manage(_threads);
  70. _threads.setMaxThreads(50);
  71. _connector = new ServerConnector(_server);
  72. _connector.setIdleTimeout(120000);
  73. _server.setConnectors(new Connector[]{ _connector });
  74. _server.setHandler(_handler);
  75. _server.start();
  76. _port=_connector.getLocalPort();
  77. _addr=InetAddress.getLocalHost();
  78. }
  79. @After
  80. public void destroy() throws Exception
  81. {
  82. _server.stop();
  83. _server.join();
  84. }
  85. @Test
  86. @Stress("High connection count")
  87. public void testAsync() throws Throwable
  88. {
  89. if (PropertyFlag.isEnabled("test.stress"))
  90. {
  91. doConnections(1600,240);
  92. }
  93. else
  94. {
  95. doConnections(80,80);
  96. }
  97. }
  98. private void doConnections(int connections,final int loops) throws Throwable
  99. {
  100. Socket[] socket = new Socket[connections];
  101. int [][] path = new int[connections][loops];
  102. for (int i=0;i<connections;i++)
  103. {
  104. socket[i] = new Socket(_addr,_port);
  105. socket[i].setSoTimeout(30000);
  106. if (i%10==0)
  107. Thread.sleep(50);
  108. if (i%80==0)
  109. System.err.println();
  110. System.err.print('+');
  111. }
  112. System.err.println();
  113. LOG.info("Bound "+connections);
  114. for (int l=0;l<loops;l++)
  115. {
  116. for (int i=0;i<connections;i++)
  117. {
  118. int p=path[i][l]=_random.nextInt(__paths.length);
  119. int period = _random.nextInt(290)+10;
  120. String uri=__paths[p][0].replace("<PERIOD>",Integer.toString(period));
  121. long start=System.currentTimeMillis();
  122. String request =
  123. "GET "+uri+" HTTP/1.1\r\n"+
  124. "Host: localhost\r\n"+
  125. "start: "+start+"\r\n"+
  126. "result: "+__paths[p][1]+"\r\n"+
  127. ((l+1<loops)?"":"Connection: close\r\n")+
  128. "\r\n";
  129. socket[i].getOutputStream().write(request.getBytes("UTF-8"));
  130. socket[i].getOutputStream().flush();
  131. }
  132. if (l%80==0)
  133. System.err.println();
  134. System.err.print('.');
  135. Thread.sleep(_random.nextInt(290)+10);
  136. }
  137. System.err.println();
  138. LOG.info("Sent "+(loops*__paths.length)+" requests");
  139. String[] results=new String[connections];
  140. for (int i=0;i<connections;i++)
  141. {
  142. results[i]=IO.toString(socket[i].getInputStream(),"UTF-8");
  143. if (i%80==0)
  144. System.err.println();
  145. System.err.print('-');
  146. }
  147. System.err.println();
  148. LOG.info("Read "+connections+" connections");
  149. for (int i=0;i<connections;i++)
  150. {
  151. int offset=0;
  152. String result=results[i];
  153. for (int l=0;l<loops;l++)
  154. {
  155. String expect = __paths[path[i][l]][1];
  156. expect=expect+" "+expect;
  157. offset=result.indexOf("200 OK",offset)+6;
  158. offset=result.indexOf("\r\n\r\n",offset)+4;
  159. int end=result.indexOf("\n",offset);
  160. String r=result.substring(offset,end).trim();
  161. assertEquals(i+","+l,expect,r);
  162. offset=end;
  163. }
  164. }
  165. }
  166. private static class SuspendHandler extends HandlerWrapper
  167. {
  168. private final Timer _timer;
  169. private SuspendHandler()
  170. {
  171. _timer=new Timer();
  172. }
  173. @Override
  174. public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
  175. {
  176. int read_before=0;
  177. long sleep_for=-1;
  178. long suspend_for=-1;
  179. long resume_after=-1;
  180. long complete_after=-1;
  181. final String uri=baseRequest.getUri().toString();
  182. if (request.getParameter("read")!=null)
  183. read_before=Integer.parseInt(request.getParameter("read"));
  184. if (request.getParameter("sleep")!=null)
  185. sleep_for=Integer.parseInt(request.getParameter("sleep"));
  186. if (request.getParameter("suspend")!=null)
  187. suspend_for=Integer.parseInt(request.getParameter("suspend"));
  188. if (request.getParameter("resume")!=null)
  189. resume_after=Integer.parseInt(request.getParameter("resume"));
  190. if (request.getParameter("complete")!=null)
  191. complete_after=Integer.parseInt(request.getParameter("complete"));
  192. if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
  193. {
  194. if (read_before>0)
  195. {
  196. byte[] buf=new byte[read_before];
  197. request.getInputStream().read(buf);
  198. }
  199. else if (read_before<0)
  200. {
  201. InputStream in = request.getInputStream();
  202. int b=in.read();
  203. while(b!=-1)
  204. b=in.read();
  205. }
  206. if (suspend_for>=0)
  207. {
  208. final AsyncContext asyncContext = baseRequest.startAsync();
  209. asyncContext.addListener(__asyncListener);
  210. if (suspend_for>0)
  211. asyncContext.setTimeout(suspend_for);
  212. if (complete_after>0)
  213. {
  214. TimerTask complete = new TimerTask()
  215. {
  216. @Override
  217. public void run()
  218. {
  219. try
  220. {
  221. response.setStatus(200);
  222. response.getOutputStream().println("COMPLETED " + request.getHeader("result"));
  223. baseRequest.setHandled(true);
  224. asyncContext.complete();
  225. }
  226. catch(Exception e)
  227. {
  228. Request br=(Request)asyncContext.getRequest();
  229. System.err.println("\n"+e.toString());
  230. System.err.println(baseRequest+"=="+br);
  231. System.err.println(uri+"=="+br.getUri());
  232. System.err.println(asyncContext+"=="+br.getHttpChannelState());
  233. LOG.warn(e);
  234. System.exit(1);
  235. }
  236. }
  237. };
  238. synchronized (_timer)
  239. {
  240. _timer.schedule(complete,complete_after);
  241. }
  242. }
  243. else if (complete_after==0)
  244. {
  245. response.setStatus(200);
  246. response.getOutputStream().println("COMPLETED "+request.getHeader("result"));
  247. baseRequest.setHandled(true);
  248. asyncContext.complete();
  249. }
  250. else if (resume_after>0)
  251. {
  252. TimerTask resume = new TimerTask()
  253. {
  254. @Override
  255. public void run()
  256. {
  257. asyncContext.dispatch();
  258. }
  259. };
  260. synchronized (_timer)
  261. {
  262. _timer.schedule(resume,resume_after);
  263. }
  264. }
  265. else if (resume_after==0)
  266. {
  267. asyncContext.dispatch();
  268. }
  269. }
  270. else if (sleep_for>=0)
  271. {
  272. try
  273. {
  274. Thread.sleep(sleep_for);
  275. }
  276. catch (InterruptedException e)
  277. {
  278. e.printStackTrace();
  279. }
  280. response.setStatus(200);
  281. response.getOutputStream().println("SLEPT "+request.getHeader("result"));
  282. baseRequest.setHandled(true);
  283. }
  284. else
  285. {
  286. response.setStatus(200);
  287. response.getOutputStream().println("NORMAL "+request.getHeader("result"));
  288. baseRequest.setHandled(true);
  289. }
  290. }
  291. else if (request.getAttribute("TIMEOUT")!=null)
  292. {
  293. response.setStatus(200);
  294. response.getOutputStream().println("TIMEOUT "+request.getHeader("result"));
  295. baseRequest.setHandled(true);
  296. }
  297. else
  298. {
  299. response.setStatus(200);
  300. response.getOutputStream().println("RESUMED "+request.getHeader("result"));
  301. baseRequest.setHandled(true);
  302. }
  303. }
  304. }
  305. private static AsyncListener __asyncListener = new AsyncListener()
  306. {
  307. @Override
  308. public void onComplete(AsyncEvent event) throws IOException
  309. {
  310. }
  311. @Override
  312. public void onTimeout(AsyncEvent event) throws IOException
  313. {
  314. event.getSuppliedRequest().setAttribute("TIMEOUT",Boolean.TRUE);
  315. event.getSuppliedRequest().getAsyncContext().dispatch();
  316. }
  317. @Override
  318. public void onError(AsyncEvent event) throws IOException
  319. {
  320. }
  321. @Override
  322. public void onStartAsync(AsyncEvent event) throws IOException
  323. {
  324. }
  325. };
  326. }