Christopher Schultz wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Peter,
On 5/8/2009 7:26 AM, Peter Crowther wrote:
Decrypt: parallel.
Send ack: parallel.
Increment counters: synced.
Write to log file: synced (or you'll have some very odd stuff happening).
I'd go further and suggest that you re-factor your design so that your
servlet is very simple. Something like this:
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
RequestCounter counter = ...; // get from app scope? Class-level?
RequestLogger logger = ...; // same here
RequestProcessor processor = ...; // same here
counter.count();
processor.processRequest(request, response, false);
logger.log(request, response);
}
Then its up to the RequestCounter to maintain its own synchonization (if
necessary) instead of your servlet having to know the semantics of
thread-safety, etc. Same with the logger. As someone mentioned, most
logging frameworks handle synchronization for you, and most of them can
buffer the output to their log files so that you are getting the best
performance you can.
I highly recommend using a logging framework, or developing something
that meets your needs that is self-contained, can accept log entries
from multiple concurrent clients (your servlets), and buffers output to
the log file to keep performance up.
I've been meaning to look into some more sophisticated logging
techniques, and this exercise has given me some good incentive to do so
sooner rather than later. However, it doesn't look at the moment like
disk writes are a limiting factor in this app's performance. My latest
thread dump indicates that the socket read is where most of the waits
are at. Because the requests are so small, I imagine that network
latency is a far bigger factor than gross throughput is.
I definitely should hook a profiler to the app so I can be sure of
what's taking the time, though.
What is it that processRequest actually does? Decryption? Hmm... is it
possible for you to save the decryption for later? You could have a
service that simply logs the notifications and then have a batch job
that later does the decryption and throws-out all the
incorrectly-encrypted data. Just another option.
Basically the entire job of this application (servlet) is to accept the
POSTs from the clients in the field, decrypt them, do a few sanity
checks on the raw data, and dump them into a file on disk (we call it a
"cache" file). There are separate apps that then continuously read the
data from the cache file and do all kinds of processing on it, stuff it
into a database, and check various values and trends for near-realtime
alerting purposes. Moving the decryption to a later step in the process
would be possible, but would require rewriting another application, for
probably very little net gain.
Early on in the design, we considered doing it all in one application,
but felt that this method gave us a little more overall reliability,
because one piece could go down without affecting the others, and then
it could catch up when it came back up. It also allowed us to profile
each section separately, making it a little easier to find the bottlenecks.
Finally... if you are logging all requests, is it necessary to keep a
daily and total request count? You can avoid the synchronization of
those counters entirely by ... not bothering to count them. Again,
retrospective counting is a possibility.
The counting isn't a core requirement of the application; I just put it
in a a way to help me monitor its progress during the day, to be sure it
hasn't locked up or lost a network connection somewhere along the way.
Incrementing a counter can't be much of a synchronization bottleneck,
and if I switch to an AtomicInteger, it should be even less of one.
Thanks for the comments!
D
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org