There is insufficient information for AsyncWeb (subproject of Mina) on internet,
what I need is simulating a web services that reply in various seconds for load testing.
the following code may not be correct, some wiered debug message…
and I just depressed it by log4j.properties
Mostly follow the lightweight example of AsyncWeb,
the eclipse project zip can be obtained here
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
public class Main { private static final int PORT = 80; /** * Main * * @param args * @throws IOException */ public static void main(String[] args) throws IOException { SocketAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new HttpCodecFactory())); acceptor.getFilterChain().addLast("executor", new ExecutorFilter(new OrderedThreadPoolExecutor(32))); //Allow the port to be reused even if the socket is in TIME_WAIT state acceptor.setReuseAddress(true); acceptor.getSessionConfig().setReuseAddress(true); acceptor.getSessionConfig().setReceiveBufferSize(1024); acceptor.getSessionConfig().setSendBufferSize(1024); // No Nagle's algorithm acceptor.getSessionConfig().setTcpNoDelay(true); acceptor.getSessionConfig().setSoLinger(-1); acceptor.setBacklog(10240); acceptor.setHandler(new CustomHttpIoHandler()); // customer handler acceptor.bind(new InetSocketAddress(PORT)); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
public class CustomHttpIoHandler implements IoHandler { private final Logger logger = LoggerFactory.getLogger(getClass()); private final Timer timer; private Random random = new Random(System.currentTimeMillis()); private final String SOAPENV_HEAD = ""; public CustomHttpIoHandler(){ timer = new Timer(true); } public void exceptionCaught(IoSession session, Throwable cause) throws Exception { if (!(cause instanceof IOException)) { cause.printStackTrace(); } session.close(true); } public void messageSent(IoSession session, Object message) throws Exception { } public void sessionClosed(IoSession session) throws Exception { } public void sessionCreated(IoSession session) throws Exception { } public void sessionIdle(IoSession session, IdleStatus status) throws Exception { session.close(true); } public void sessionOpened(IoSession session) throws Exception { session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 30); } public void messageReceived(IoSession session, Object message) throws Exception { HttpRequest req = (HttpRequest) message; doAsynchronousDelayedResponse(session, req); } /** * business logic for various percentage and behaviour * * @param session mina session * @param req Http request * @throws CharacterCodingException */ private void doAsynchronousDelayedResponse(final IoSession session, final HttpRequest req) throws CharacterCodingException { int delay = 0; Behaviour behaviour; int value = nextRandom(1, 100); if(value < = 50){ // 50% of responses return valid result within 0-3 secs (good response time & good result) delay = nextRandom(10, 3000); behaviour = Behaviour.GOOD_TIME_GOOD_RESULT; }else if(value > 50 && value < =60){ //10% of responses return expected error within 0-3 secs (good response time & expected error result) delay = nextRandom(10, 3000); behaviour = Behaviour.GOOD_TIME_ERROR_RESULT; }else if(value > 60 && value < = 90){ //30% of responses return valid result within 3-15 secs (fair response time & good result) delay = nextRandom(3000, 15000); behaviour = Behaviour.FAIR_TIME_GOOD_RESULT; }else if(value > 90 && value < =95){ //5% of responses return valid result within 15-190 secs (poor response time & good result) delay = nextRandom(15000, 190000); behaviour = Behaviour.POOR_TIME_GOOD_RESULT; }else if(value > 95 && value < =97){ //2.5% of responses return valid result after 190 seconds (bad response time & good result) delay = nextRandom(15000, 190000); behaviour = Behaviour.BAD_TIME_GOOD_RESULT; }else{ //2.5% of responses return 'no content' after 190 seconds (bad response time & bad result) delay = nextRandom(15000, 190000); behaviour = Behaviour.BAD_TIME_BAD_RESULT; } final MutableHttpResponse res = new DefaultHttpResponse(); res.setStatus(HttpResponseStatus.OK); res.setContentType("application/soap+xml; charset=utf-8"); // get corresponding response from behaviour StringBuffer sb = getResponseXML(behaviour); IoBuffer bb = IoBuffer.allocate(1024); bb.setAutoExpand(true); bb.putString(sb.toString(), Charset.forName("UTF-8").newEncoder()); bb.flip(); res.setContent(bb); logger.info("delay:" + delay + " stub:" + behaviour); timer.schedule(new TimerTask() { @Override public void run() { writeResponse(session, req, res); } }, delay); } /** * Write the http response * * @param session mina session * @param req HTTP Request * @param res HTTP Response */ private void writeResponse(IoSession session, HttpRequest req, MutableHttpResponse res) { res.normalize(req); WriteFuture future = session.write(res); if (!HttpHeaderConstants.VALUE_KEEP_ALIVE.equalsIgnoreCase( res.getHeader( HttpHeaderConstants.KEY_CONNECTION))) { future.addListener(IoFutureListener.CLOSE); } } /** * Generate next random number from min(inclusive) to max(inclusive) * @param min minimum number * @param max maximum number * @return random integer */ private int nextRandom(int min, int max){ return random.nextInt(max-min+1)+min; } /** * Indicate what kind of behaviour * * @author SteveChan */ public enum Behaviour{ GOOD_TIME_GOOD_RESULT, //return valid result within 0-3 secs GOOD_TIME_ERROR_RESULT, //return expected error within 0-3 secs FAIR_TIME_GOOD_RESULT, //return valid result within 3-15 secs POOR_TIME_GOOD_RESULT, //return valid result within 15-190 secs ( BAD_TIME_GOOD_RESULT, //return valid result after 190 seconds BAD_TIME_BAD_RESULT //return 'no content' after 190 seconds } /** * * @param stub indicate what Behaviour * @return StringBuffer with return xml content */ private StringBuffer getResponseXML(Behaviour stub){ StringBuffer sb = new StringBuffer(); if(stub.equals(Behaviour.GOOD_TIME_GOOD_RESULT) || stub.equals(Behaviour.FAIR_TIME_GOOD_RESULT) || stub.equals(Behaviour.POOR_TIME_GOOD_RESULT) || stub.equals(Behaviour.BAD_TIME_GOOD_RESULT)){ sb.append(SOAPENV_HEAD) .append("") // some content here .append("") .append(""); }else if(stub.equals(Behaviour.GOOD_TIME_ERROR_RESULT)){ sb.append(SOAPENV_HEAD) .append("") // some content here .append("") .append(""); }else{ //BAD_TIME_BAD_RESULT sb.append(SOAPENV_HEAD) .append("") // some content here .append("") .append(""); } if(logger.isDebugEnabled()){ logger.debug("return stardard soap response xml by " + stub ); logger.debug(sb.toString()); } return sb; } } |