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]

Reply via email to