| Article Index |
|---|
| 1. The Source Code |
| 2. A Simple Load Test |
When developing network based applications there is sometimes the need to debug the behaviour of application servers, frameworks and applications.
This article provides the source code of an general purpose server application to handle concurrent requests to be able to identify runtime and deadlock problems in underlaying or closed source components.
The server application has been customized to handle simple HTTP requests containing just a request header. Handling requests his way you should be able to handle 1000 requests per second with ease.
1. The Source Code
The following listing contains all source codes and configurations to run the server application.
/* * This customized code is based on an article published * at http://www.kieser.net/linux/java_server.html * * Title: Sample Server * Description: This utility will accept input from a socket, posting back * to the socket before closing the link. It is intended as a * template for coders to base servers on. * * Article: * * A multi-threaded socket-based server * * The problem is old - How to implement a multi-threaded, socket-based * server that will let you read and write to the client (for example a * telnet terminal. * * There are several problems with constructing such a server: * * You have to use threads because otherwise clients will be * queued up waiting for a connection. * * Many of the publically available examples (even some in some books) * do not work for I/O servers. They are mostly developed around reading * from a socket not writing to the socket as well. In our example we * give a working read/write code example. * * You need to avoid race conditions when starting up a thread at * times when connections are coming through thick and fast. * * The code below will implement just such a server. It is intended for a * head start, so is a template rather than a tutorial on how to write a * server in Java. We have decided on port 4444 to listen on in the example, * but you need to decide on a suitable port yourself. * * The server will run, establishing connections from the port and echoing * input received until it receives a line of input that is a full stop * only ".". * * Have fun! * */ package com.linux_support; import java.io.*; import java.net.*; import java.security.*; /** * * @author mario */ public class JEmergancyWebServer { // default port for incoming connections private static int port = 4444; // define the max number of connection to be handled (0 == unlimited) private static int maxConnections = 0; /** Main method. It will start the server application. * @param args the command line arguments */ public static void main(String[] args) { int i = 0; try { ServerSocket listener = new ServerSocket(port); Socket server; while ((i++ < maxConnections) || (maxConnections == 0)) { DoTheJob connection; server = listener.accept(); DoTheJob conn_c = new DoTheJob(server); Thread t = new Thread(conn_c); t.start(); } } catch (IOException ioe) { // print error messages to the standard output device System.out.println("IOException on socket listen: " + ioe); ioe.printStackTrace(); } } } class DoTheJob implements Runnable { private Socket server; private String line, input; DoTheJob(Socket server) { this.server = server; } public void run() { input = ""; try { // Get input from the client DataInputStream in = new DataInputStream(server.getInputStream()); PrintStream out = new PrintStream(server.getOutputStream()); //while((line = in.readLine()) != null && !line.equals(".")) { // handle simpe requests containing header data only. while ((line = in.readLine()) != null && !line.equals("")) { input = input + line + "\n"; // send the received line to the client //out.println("received line:" + line); } // print tht whole message to stdout input = input + "Status: 200\n"; String msg = "Overall message is: n\n" + input; System.out.println(msg); // send response to client out.println(msg); server.close(); } catch (IOException ioe) { System.out.println("IOException on socket listen: " + ioe); ioe.printStackTrace(); } } }
2. A Simple Load Test
To get an idea what the application is able to do we want to perform a simple load test.
The following list contains details regarding the maschine the load test has been run on. (It is no high performance hardware - it's a dual-core netbook)
vendor_id : GenuineIntel cpu family : 6 model : 23 model name : Genuine Intel(R) CPU U7300 @ 1.30GHz stepping : 10 cpu MHz : 800.000 bogomips : 2678.04
Here are the results of the load test:
$ ab -n1000 -c10 http://localhost:4444/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient) Completed 100 requests Completed 200 requests Completed 300 requests Completed 400 requests Completed 500 requests Completed 600 requests Completed 700 requests Completed 800 requests Completed 900 requests Completed 1000 requests Finished 1000 requests Server Software: Server Hostname: localhost Server Port: 4444 Document Path: / Document Length: 0 bytes Concurrency Level: 10 Time taken for tests: 0.993 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Non-2xx responses: 1000 Total transferred: 111000 bytes HTML transferred: 0 bytes Requests per second: 1007.40 [#/sec] (mean) Time per request: 9.927 [ms] (mean) Time per request: 0.993 [ms] (mean, across all concurrent requests) Transfer rate: 109.20 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.3 0 4 Processing: 1 10 7.2 7 55 Waiting: 0 10 7.1 7 55 Total: 2 10 7.1 7 56 Percentage of the requests served within a certain time (ms) 50% 7 66% 9 75% 11 80% 12 90% 18 95% 23 98% 37 99% 41 100% 56 (longest request)
With some knowledge of protocols and server programming you should be able to write a customized server by utilizing custom backend frameworks to test your applications.




