One of the problems I've noticed browsing through the server source is the lack of thread management in the code. The policy seems to be 'accept a connection, generate a thread, and forget about it'. This leaves the server open to connection flood or DoS attacks. Java threads are nice, and they help efficiency, but when there are to many of them, things get ugly.
I did some connection testing on Freenet and the server really starts to behave badly with numerous connections. The threads compete for processor time, so connections take longer to finish, thus there is more time for new connections, yielding more threads, and so on. A simple solution to this might be to use thread pooling. This worked very effectively in Gamora (a pet project of mine). Essentially, you maintain a pool of N threads, where N is the most you want running at any given time. As new jobs come in, they are issued to the pool manager, which assigns them to a thread, up to N. Beyond N, they are added to a run-queue and assigned as threads become available. The result is a non-blocking system that allows connections to continue to flow in, but places them on hold so that the system doesn't run away from you. If you pick your N right, high enough that your server is never idle, but low enough that the threads aren't thrashing, this actually improves performance considerably. Below is a patch against build 118 that executes all of its connections in a Thread pool with N=50. You'll need the ethread package, ftp://ftp.gamora.org/pub/gamora/ethreads. Just shove her in your classpath. Feel free to tinker, play, and flame the hell out of me. :) --------8<------------------------------------------------------ diff -urN Freenet/ConnectionHandler.java Freenet-ethread/ConnectionHandler.java --- Freenet/ConnectionHandler.java Sun Apr 9 10:48:36 2000 +++ Freenet-ethread/ConnectionHandler.java Tue Apr 11 19:35:33 2000 @@ -3,6 +3,8 @@ import java.net.*; import java.io.*; import java.io.EOFException; +import org.gamora.ethreads.*; + /* This code is part of the Java Adaptive Network Client by Ian Clarke. It is distributed under the GNU General Public Licence (GPL) @@ -16,9 +18,10 @@ * @author <a href="mailto:blanu at uts.cc.utexas.edu">Brandon Wiley</a> **/ -public class ConnectionHandler extends Thread +public class ConnectionHandler implements ERunnable { // Protected/Private Fields + private static EThread exec_instance; private static long ids=0; private long id; private Connection c; @@ -165,7 +168,7 @@ //I'm letting this force close now, maybe it should synchronize somehow (it can't sync to c.in anyways, since that is always waiting on a read in the RawMessage constructor). public void close() { closed = true; - this.interrupt(); + exec_instance.getThread().interrupt(); } /** @@ -182,7 +185,8 @@ **/ public boolean isOpen() { - return isAlive() && !closed; + return exec_instance!=null && !closed; + // return isAlive() && !closed; } public Address peer() { @@ -199,5 +203,9 @@ public Address local(ListeningAddress laddr) { return c.getMyAddress(laddr); + } + + public void setExecutionInstance(EThread e) { + exec_instance=e; } } diff -urN Freenet/Core.java Freenet-ethread/Core.java --- Freenet/Core.java Tue Apr 11 09:12:35 2000 +++ Freenet-ethread/Core.java Tue Apr 11 19:37:54 2000 @@ -4,6 +4,7 @@ import java.util.*; import java.net.*; import java.io.*; +import org.gamora.ethreads.*; /* This code is part of the Java Adaptive Network Client by Ian Clarke. @@ -40,6 +41,7 @@ public HandshakeHandler hh; public Listener listener; public boolean listen = true; // provides a way to turn off listening + public ThreadManager threads; public Core(ListeningAddress myAddress, MessageHandler mh, HandshakeHandler hh) { try { @@ -51,6 +53,8 @@ this.mh = mh; this.hh = hh; Logger.log("Core.java","Node running on "+listener,Logger.NORMAL); + threads=new ThreadPool(50); + threads.start(); } public void acceptConnections() @@ -70,7 +74,7 @@ throw new RuntimeException("Problem accepting next connection"); } c = new ConnectionHandler(conn, mh); - c.start(); + threads.run(c); } } @@ -119,7 +123,7 @@ } ConnectionHandler ch = new ConnectionHandler(c, mh); - ch.start(); // start listening on this connection + threads.run(ch); // start listening on this connection return ch; } _______________________________________________ Freenet-dev mailing list Freenet-dev at lists.sourceforge.net http://lists.sourceforge.net/mailman/listinfo/freenet-dev
