Raining Sockets - High Performance IO in Java

Hosted by:
SourceForge.net Logo

Latest stable CORE is 1.1.10. This contains only core files
Pipelining and Persistent connections are implemented in 1.2pre3d. You may use the raining.core files without the HTTP Server.
For the non-blocking HTTP Server, see below.

NIO Http-Server Development Update:

Development version 1.2pre3d . This contains a minimal (but growing) working non-blocking HTTP Server that handles 202, 304, 40*, 50* responses. Worked on persistent connections and MT pipelining. (Done some testing).
Adding code for HTTP protocol as per RFC 2616
Intend to implement all MUST and most SHOULD requirements for a HTTP 1.1 compliant server.
To see day-by-day updates view the CHANGES file.
To test this use testserver.sh and testsb.sh.





Overview

Raining Sockets is a non-blocking sockets framework which eases the job of creating a highly scalable application that can receive and send over 10000 socket connections.

A user needs to instantiate a class that contains complete non-blocking IO code, override the event that he requires to customize, such as what to do with arrived (or arriving) data, or what to do when a write has completed. He is thus freed from the nitty gritties of NIO.

Prior to JDK 1.4, IO operations were blocking, which usually resulted in a thread-per-client model, meaning a large number of threads. This limited application scalability. For a detailed discussion of why, refer C10K problem.

Even the New IO model offers a low level interface to non-blocking IO which is not easy to master, despite all the information and books available. Raining aims to give a high level interface to the user, so that NB IO (NBIO) can be plugged into applications without worrying about details, bugs, proper handling of buffers/selector/channel/events etc.

The SocketBlaster (NIO based Load Tester) and Server (very basic NIO Server) program (both extended from NioSocket.java) have been successfully tested with 13000 connections on 2 Xeon machines.

The Raining HTTP Server is an NIO based HTTP Server that aims at implementing most of HTTP 1.1. This is under development and may be accessed in the 1.2 releases.

Raining Sockets is free to use and modify, even for commercial use (I would love to hear from you on its use at: rahulkumar@users.sourceforge.net ).

Components

Current Work:

I am currently working on Raining version 1.2. This will include 2 major feature enhancements:

These features would be overridable using interfaces.


Thus, with Raining Sockets v1.2 you would be able to use the framework for creating high performance HTTP applications straight off.

Expected Date of release for 1.2 is December 30, 2003 due to many other engagements.

If anyone's interested in seeing working code of 1.2, pls check 1.2pre or the Nightly update. . Would really appreciate some critical feedback.

TODO (Functional) , TODO (Coding/Low Level)
LGPL LICENSE
CHANGES (day by day updates)

Click here to go to the Project Raining Sockets hosted @ Sourceforge.net.

Goals

1. Be easy to extend. Should make high-performance socket application development a lot easier.
2. Be highly scalable. Scale to well over 10,000 connections.

A quick word on design

(This section added on Oct 24, 2003)
Raining consists of a simple, lightweight NIO implementation in a single class, NioSocket.java. I have kept object creation to a minimum in this class, and tried to minimize assumptions of applications that would extend it.

However, it is still fully functional, one can easily build a server or a client or proxy server from it, as can be seen in the provided examples.

The NIO provided by Java, does not provide for any protocol implementations. (Can anyone tell me why?) Thus, for any serious application, protocols (such as HTTP) need to be implemented.

Thus, the next step is to implement a protocol, and to build a layer over the basic NioSocket, into which Protocols and various handlers can be plugged in.

I shall also attempt to keep this layer fairly optimized, so that developers dont have to do so. At the very least I shall try to optimize String and Date (while logging) usage.

Note: This eventually will become a separate document

Status

Download Latest stable releases from here
As on Oct 9, 2003, V 1.1.9 has being tested with 13000 connections and held up.

As on Oct 8th, V 1.1.8 has been tested with 10000 and 15000 concurrent connections on 2 IBM X225 servers. It has held up. On very high loads i do get Connection Timed Out and some Connection Reset by Peers on the client machines.
I am trying to see if these are application problems or network configuration issues.

I still have to add file based NIO, allow user to specify timeouts, give more performance related info in the Socket Blaster. A lot of code cleanup is still required.

OLD Status:


As on Oct 6th, V 1.1.6 is being tested with tens of thousands of connections. Unfortunately, i am battling OS issues (too many files open, connection reset by peer), thus I cant post any results.

As on October 5th, the version released was 1.1.5. This contains many improvements and refinements in the NioSocket framework. It also contains a sample Load generator called SocketBlaster, a sample Server, an HttpClient which contains some of the HTTP Protocol, and a basic Proxy Server ..

REQUIREMENTS

The Java 2 SDK V 1.4.2 or higher is required to build Raining. This will not compile on 1.4.0.

You may also need to increase the max files settings on your Unix box, if you get a "no more open files" error.

DEPENDENCIES

To process the command line of the examples, i have used jakarta's commons cli. For building you need apache's ant, unless you choose to use make.sh or make.bat. Jar files are available in dependencies.tar.gz (as part of the 1.2 release).

BUILDING RAINING SOCKETS

Version 1.2 and above:

May be installed using ant 1.5 installation, or ant jar files (build.sh), or even just a compiler (make.sh).

$ ant
This compiles, creates a jar, creates source distributions, creates the javadocs etc.
Requires ant 1.5.1 to be installed.

$ build.sh
This requires ant.jar, crimson.jar and xalan.jar present in dependencies.tar.gz.

$ build.bat - untested. Dont try.

$ make.sh
If you dont like ants, use this. It compiles all files using javac or jikes. I use this for quick compilations. This is a general script that can be placed in the path. It assumes an "src" folder, and places the output in "build/classes" by default. I have also set this as makeprg in ".vimrc".

On Windows: make.bat
I can't test this since i dont have Windows anywhere. Pls check it before use, and mail me a working copy, if you dont mind.

Version 1.1.9 and lesser:

$ javac -O -g:none -target 1.4 NioSocket.java
or
$ jikes -O NioSocket.java

To build all the samples and clients:
$ javac -O -g:none *.java
OR
$ javac -O -g:none -target 1.4 *.java

TRYING THE EXAMPLES

If using 1.2, pls use the build files provided, and see the sample server.sh and sb.sh which use the updated package structure.

Version 1.1.9 and lesser:

Compile the examples:
$ javac -O -g:none *.java

The Http Client
$ java HttpClient
This will print out a help message that gives the arguments required.

The simplest usage is:
$ java HttpClient http://www.artima.com/

OR

$ java HttpClient -f file.txt


The Server
Start the server on port 80
$ java -server Server
OR
Start the server on port 80 to take a high number of concurrent connections
$ java -server -Xms500m -Xmx800m Server

Start the server on port 8080
$ java -server Server 8080


The SocketBlaster (load generator)
$ java -server SocketBlaster -n1000 -i30 http://localhost:8080/index.html

This connects the SocketBlaster to port 8080, and blasts the server with a 1000 connections every 30 seconds.

$ java -server -Xms700m -Xmx1200m SocketBlaster -n15000 -i90 http://172.16.1.9:80/index.html

This connects the SocketBlaster to port 80 of another machine, and blasts the server with a 15000 connections every 90 seconds.


The Proxy Server

Start Tomcat or any server on port 80.
$ cd $CATALINA_HOME/bin
$ ./startup.sh
$ cd -
Start the proxy server with port 80 as the parameter. It will listen on port 8080, and connect as a client to port 80.
$ java ProxyServer localhost 80
Start a telnet session connected to port 80.
$ telnet localhost 8080

Enter commands on the telnet, such as "GET /index.html HTTP/1.1"
The output frome tomcat will come onto your telnet session.

In case you intend blasting Tomcat with the SocketBlaster, pls increase the min and max processors, and the acceptConnections, else you will see major waits between connection accepts and replies.

QUICK EXAMPLE OF USAGE (Developers)

(For most accurate examples, pls see the actual sample files, since things have changed a bit since v 1.0.)
I have cut a few lines of HttpClient, to demonstrate how to use this file.

// extend the NioSocket class

public class HttpClient extends NioSocket {

   try {
       // instantiate my client and ask it to push the data.
       HttpClient h = new HttpClient (url);
       h.push();
       // call the start method so that selector polling can start
       NioSocket.start();
       } catch (Exception exc) { System.err.println( " Http 21 EXC:"+ exc.toString()); exc.printStackTrace(); } 

    }

     */
    public HttpClient (String Url) throws java.net.MalformedURLException, java.io.IOException, Exception {
        super(null, null);
    }
    // my own method to create data to push
    public void push () throws java.io.IOException, Exception {
        
            GETString = "GET "+path+" HTTP/1.1\r\n"+
            "Proxy-Authorization: "+proxyBase64 + "\r\n"+
            "Host: "+host+     "\r\n\r\n";

            super.create_client_socket( host1,port1, GETString);

    }
    /** we implement our own processing here.
     * e.g. we could write to disk or db.
     * Or we could pass a handle of a method, to invoke
     * we would do any blocking writes in a thread if we want
     * scalability.
     */
    public void handle_read_complete(String mdata){
        System.out.println(  mdata );
        System.out.println(  "Total:" + totalBytesRead);

    }


Please see the source code for complete details.

super.create_client_socket -
creates client sockets and pushes data to them in NB mode. You can then process the data in handle_read or handle_read_complete

super.create_server_socket -
creates server sockets and accepts data to them in NB mode. You can then process the data in handle_read or handle_read_complete or handle_write.

NioSocket.start -
Starts polling selectors and reading/writing/connecting/accepting as appropriate.

Credits

I have heavily referred to the asyncore.py module written by Sam Rushing.
Dr Brendan Gowing and Ron Hitchens for valuable feedback.
Ron Hitchen's NIO Book.
Linus and RSM for GNU/Linux, Bram Moolenaar for vim (all code edited in gvim 6.1)

Resources:

Medusa - Python Framework by Sam Rushing, maintained by A Kuchling. ,
Java NIO - O'Rielly, Ron Hitchens
c10k
ACE
http://www.cs.wustl.edu/~schmidt/PDF/dispatching.pdf
http://www.cs.wustl.edu/~schmidt/PDF/proactor.pdf
RFC 2616
RFC 2068
RFC 822

Some small chit-chat on coding guidelines

I dislike camelCase and Hungarian notation. I have reverted to using lower_case_with_underscores which is easier on the eye, and the fingers.


Copyright (c) 2003, Rahul K ). (rahulkumar at users dot sourceforge dot net )
This software has been abandoned. If you wish to continue development, please take the source and do so.
Other treats: my (favorite) SQL Client: SQLMinus.
Want Java tips and snippets streaming on your screensaver ? Try Java Snippets Screensaver.
$Id: index.php,v 1.1 2003/10/24 09:46:28 rahul_kumar Exp rahul $

SourceForge.net Logo