Hmm, I would suggest you stop having continuos connections. 30 seconds is a lot of time, maybe you should re-establish connections on request. I know re-establishing costs 3 additional tcp packets, but it negligible since you have small packets sent seldomly. I assume your chat is an applet, since you wouldn't need 2 threads otherwise. Since your applet is running in browser you could try to use the browsers connection (via loading document in a hidden frame from the applet, executing javascript in the loaded document that calls a method in the applet). This way you'll need no own threads at all. If you don't like the solution (which I would fully understand) you could still switch to polling with 1 thread on the server side: On timer in applet you use your 1 thread connection and send the request the server reads the request and sends the response after the request the client reads the response and idles :-) Its pretty similar to the http protocol in this case. If you use above advice with reestablishing connections you can get rid of threads and switch to thread-pools which will give you a performance boost of factor 10 or more.
regards Leon On 10/2/06, Peter Warren <[EMAIL PROTECTED]> wrote:
I have an application that links users so they can chat. My client operates within a browser. To be firewall friendly and avoid client server sockets listening for incoming requests, I implemented the client so that it makes http requests and sits and waits (maybe for minutes on end) until it gets a response. And each client has 2 threads that are constantly waiting for an http response from 2 different urls (which ties up 2 servlet threads). I knew full well that this would be thread heavy on the tomcat server side but thought I'd try it out. The server is tomcat 5.5.20 running on Windows XP Pro with 1GB of RAM. After some preliminary load testing, I find I'm able to handle about 500 simulated users (each sending a message every 30 seconds) concurrently communicating before getting connection refused messages. I would like to improve that. So with each client having 2 threads constantly waiting on servlet requests, that's 2 servlet threads per client or 1000 threads on the server, which seems like a lot to me. With 500 clients communicating every 30 seconds, fairly evenly distributed, that's about 16 requests per second. It seems like I should be able to do better than that. Initially when running my load test, I ran into OutOfMemoryErrors: unable to create new native thread. Lowering the thread stack size in Tomcat's configuration dialog seemed to help. Now the limiting issue is that my clients receive "connection timed out" and "read timed out" messages. On the client I see the following stacks: java.net.ConnectException: Connection timed out: connect at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.PlainSocketImpl.doConnect(Unknown Source) at java.net.PlainSocketImpl.connectToAddress(Unknown Source) at java.net.PlainSocketImpl.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at java.net.Socket.connect(Unknown Source) at sun.net.NetworkClient.doConnect(Unknown Source) at sun.net.www.http.HttpClient.openServer(Unknown Source) at sun.net.www.http.HttpClient.openServer(Unknown Source) at sun.net.www.http.HttpClient.<init>(Unknown Source) at sun.net.www.http.HttpClient.New(Unknown Source) at sun.net.www.http.HttpClient.New(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.plainConnect(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.connect(Unknown Source) at com.seekspeak.applet.URLTalker.initConnection(URLTalker.java:44) at com.seekspeak.applet.URLTalker.send(URLTalker.java:50) at com.seekspeak.test.load.RecipientTest$RefreshThread.run(RecipientTest.java:206) java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(Unknown Source) at java.io.BufferedInputStream.fill(Unknown Source) at java.io.BufferedInputStream.read1(Unknown Source) at java.io.BufferedInputStream.read(Unknown Source) at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source) at sun.net.www.http.HttpClient.parseHTTP(Unknown Source) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So urce) at java.net.HttpURLConnection.getResponseCode(Unknown Source) at com.seekspeak.applet.URLTalker.send(URLTalker.java:54) at com.seekspeak.test.load.Communicator$ListenThread.run(Communicator.ja va:217) In the catalina log, the only problem I see is this stack: Oct 1, 2006 7:59:01 PM org.apache.catalina.core.StandardWrapperValve invoke WARNING: Servlet.service() for servlet invoker threw exception java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:747) at org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:777) at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:115) at org.apache.coyote.http11.InternalInputBuffer.doRead(InternalInputBuffer.java:712) at org.apache.coyote.Request.doRead(Request.java:418) ... CPU-wise the server never breaks a sweat, rarely rising above 5% cpu. My load test client is running on a separate machine from the server. My question is: how can I best improve the performance? Is the server really refusing client connections or is the load test bogging down and reporting spurious messages (the load test uses many threads as well)? Is the high # of threads on the server a problem? Would running on Linux or another OS help? Is there a way for me to minimize the # of servlet threads required? Since my servlet threads don't really do anything but sit around blocking until being notified to complete the client's request, it seems like I could just have a small number of threads and keep a map of open http connections. When necessary I could just have one of these threads find the appropriate client connection, send output, and then close the connection. Since Tomcat operates on a single thread per servlet request model, my issue is that doing the above will require substantial changes to tomcat's Http11Protocol and like PoolTcpEndpoint classes. I'd really prefer to avoid monkeying with the tomcat code if possible. And yes, peer to peer would be much less resource intensive, but I'm trying to make an easy to install and run web app. I don't want clients trying to open server sockets on ports that might be blocked by firewalls. Thanks for any thoughts, Peter --------------------------------------------------------------------- To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
--------------------------------------------------------------------- To start a new topic, e-mail: users@tomcat.apache.org To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]