Java Forum / General / October 2005
Servlet serialization question
Larry Coon - 25 Oct 2005 22:36 GMT It's possible that this question is off-topic, depending on the correct answer. If so, apologies in advance.
I have an HttpServlet running in Tomcat. The doGet() method takes a non-trivial amount of time to complete, and I noticed that the HttpServlet object is only instantiated once -- if multiple requests come in at the same time, they are serialized.
If I want them to run in parallel, is it Tomcat's responsibility (to instantiate multiple instances of the HttpServlet), or the Servlet's responsibility (to create a thread and do the work there when a requuest comes in, so it can get back to listening for new requests as soon as possible)?
I spent a good amount of time looking through Tomcat's documentation for a configuration setting (such as max # instances to invoke), but I didn't see anything. Of course, I could have just been looking in the wrong place, so if anybody can get me pointed in the right direction, I'd appreciate it.
praveen - 26 Oct 2005 05:07 GMT Larry, Although there is only one instance of the servlet created, each request is handled by a seperate thread and hence the requests are processed in parallel i.e. multiple threads will execute in the servlet instance's service method. If you need to process only one request at a time and thereby serialize requests, the HttpServlet needs to implement the SingleThreadModel interface. In this case, the servlet container may either instantiate multiple instances of the servlet or serialize requests to a particular instance. But use of this interface is not recommended as it results in a performance hit. Also, this interface has been deprecated in Servlet 2.4.
Larry Coon - 26 Oct 2005 15:00 GMT
> Larry, > Although there is only one instance of the servlet created, each [quoted text clipped - 8 lines] > But use of this interface is not recommended as it results in a > performance hit. Also, this interface has been deprecated in Servlet Thanks for the reply. Actually, it's the other way around -- I saw that it was serializing requests, and I want them to be processed in parallel.
Is Tomcat supposed to be creating one instance of the Servlet and sharing that one instance among multiple threads (which obviously wouldn't make sense), or is it supposed to be creating one instance of the Servlet for each thread? Via logging, I was able to verify that only one instance of the Servlet was being instantiated no matter how many requests came in. I also verified (by logging start/stop times) that it was indeed serializing the requests -- the one instance of the servlet was handling the requests, one at a time.
I guess one possibility is that it's bottlenecking on some resource, but if that was the case, I'd still see multiple instances of the Servlet being instantiated, right?
praveen - 26 Oct 2005 16:38 GMT Larry, As per Servlet 2.4 Specification - SRV.2.2, For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration. However, for a servlet implementing the SingleThreadModel interface, the servlet container may instantiate multiple instances to handle a heavy request load and serialize requests to a particular instance.
So, the threads corresponding to the various requests operate on that single instance. Now, depending upon the scheduling algorithm running on the server, the threads gain access to the instance.
In your case, probably, one thread is getting enough time to complete its processing inside the doGet method of the servlet before another thread could get its turn. Hence, it seems as if the threads are being serialized. But actully, the threads are running in parallel.
Larry Coon - 26 Oct 2005 17:19 GMT > Larry, > As per Servlet 2.4 Specification - SRV.2.2, [quoted text clipped - 11 lines] > Now, depending upon the scheduling algorithm running on the server, the > threads gain access to the instance. Sorry for being obtuse here, but I don't quite understand the interaction between threads and instances of the servlet. If there is one instance per servlet definition, then multiple threads would be pointless -- since the servlet has state variables, then it would HAVE to serialize requests. Therefore it wouldn't matter if there was one thread or multiple threads. What am I missing?
> In your case, probably, one thread is getting enough time to complete > its processing inside the doGet method of the servlet before another > thread could get its turn. Hence, it seems as if the threads are being > serialized. > But actully, the threads are running in parallel. That's definitely not the case. My servlet does some JDBC work, and for testing, I just put in a statement to make the database server wait five minutes before returning the result. I then launced five calls to the servlet at once, logging the start & stop times for each. They definitely ran serially.
But it would make sense if (as I wrote above) multiple threads were created but the servlet instance serialized them. This seems consistent with my observations, but again, it leaves me wondering about the purpose of having multiple threads calling a single servlet instance.
praveen - 26 Oct 2005 18:56 GMT Larry, With regards to state variables, if there are instance variables in your servlet, then they are definitely NOT thread-safe as there is only one copy of the instance variables per instance of the servlet and all of the threads share this copy.
Local variables, on the other hand are thread-safe as each thread gets its own copy of the local variables.
Hence, one must never use instance variables in a servlet.
Coming to your servlet execution being performed serially, this should NOT be the case at all, especially if the wait period is that long. If you could post the code and mention the operating environment, I could test it and let you know the results from my side.
Larry Coon - 26 Oct 2005 19:34 GMT > Larry, > With regards to state variables, if there are instance variables in > your servlet, then they are definitely NOT thread-safe as there is only > one copy of the instance variables per instance of the servlet and all > of the threads share this copy. Yes, here is where I got screwed up -- I do have instance variables for a JDBC Connection & Statement, and also for an XML Transformer. The intent of the servlet is to maintain a database connection and wait for a request. A request is a (Sybase) stored proc name and proc arguments. It uses the Statement to invoke the proc, and transforms the ResultSet into XML to return to the client.
My assumption was that it would create a pool of servlet instances if necessary, but that's (now obviously) not the case.
> Local variables, on the other hand are thread-safe as each thread gets > its own copy of the local variables. > > Hence, one must never use instance variables in a servlet. A lesson now learned. :-)
> Coming to your servlet execution being performed serially, this should > NOT be the case at all, especially if the wait period is that long. > If you could post the code and mention the operating environment, I > could test it and let you know the results from my side. The code does database access that's specific to our environment, so I don't think that would be practical (otherwise I would have posted an SCCEE with the original question).
But I did try your earlier suggestion, and made it implement SingleThreadModel. I was hoping that it would then create a pool of servlet instances, but it still used just one and serialized the calls. I read in here:
<http://www.novocode.com/doc/servlet-essentials/chapter4a.html#ch_4_1>
the following: "If a server gets concurrent requests for such a Servlet it could e.g. serialize the calls or create multiple instances of the Servlet which form a Servlet pool."
I didn't see anything about how to make it do one or the other (i.e., create multiple instances rather than serialize them).
Pete Barrett - 26 Oct 2005 19:14 GMT >Sorry for being obtuse here, but I don't quite understand the >interaction between threads and instances of the servlet. If [quoted text clipped - 3 lines] >it wouldn't matter if there was one thread or multiple threads. >What am I missing? There's only one instance of the servlet, but the service() *method* of the servlet (which in turn calls doPost(), doGet(), and so forth) will be called concurrently from different threads. It's the programmer's responsibility to ensure that access to state variables is correctly serialised.
So the answer to what you're missing - probably a few synchronized blocks!<g>
>That's definitely not the case. My servlet does some JDBC work, >and for testing, I just put in a statement to make the database >server wait five minutes before returning the result. I then >launced five calls to the servlet at once, logging the start & >stop times for each. They definitely ran serially. It's possible that the database driver may be doing the serialisation in this case (that's part of its job). Or it could be that you've got Tomcat set up to run single-threaded. What I've said above, and praveen's said previously, is what's *supposed* to happen under normal circumstances. I've never bothered to check whether it is in fact the case, but I do make sure my servlet methods are thread safe!
>But it would make sense if (as I wrote above) multiple threads >were created but the servlet instance serialized them. This >seems consistent with my observations, but again, it leaves me >wondering about the purpose of having multiple threads calling >a single servlet instance. Pete Barrett
Larry Coon - 26 Oct 2005 19:39 GMT > There's only one instance of the servlet, but the service() *method* > of the servlet (which in turn calls doPost(), doGet(), and so forth) [quoted text clipped - 4 lines] > So the answer to what you're missing - probably a few synchronized > blocks!<g>
:-) Actually, a synchronized block would just cause it to serialize, and since that's the behavior I'm observing, I'm guessing that the JDBC methods are synchronized. (Ah, as you say below, I just noticed.)
> It's possible that the database driver may be doing the serialisation > in this case (that's part of its job). Or it could be that you've got > Tomcat set up to run single-threaded. I've got Tomcat essentially straight-out-of-the-box, so if it's something in the set-up, then it's doing so by default. As I wrote to paraveen, I tried using SingleThreadModel but it still serialzed them rather than creating a pool of them, and I don't know how to configure this behavior.
> What I've said above, and > praveen's said previously, is what's *supposed* to happen under normal > circumstances. I've never bothered to check whether it is in fact the > case, but I do make sure my servlet methods are thread safe! Yeah, it sounds like my first task is to get rid of my instance variables.
praveen - 27 Oct 2005 05:22 GMT > As I wrote to paraveen, I tried using SingleThreadModel but it still serialzed > them rather than creating a pool of them, and I don't know how to > configure this behavior. Larry, As far my knowledge goes, this behaviour is not configurable. It is dependent on the container implementation and hence becomes vendor-specific.
Larry Coon - 28 Oct 2005 18:09 GMT > Larry, > As far my knowledge goes, this behaviour is not configurable. It is > dependent on the container implementation and hence becomes > vendor-specific. That explains why I wasn't able to find anything about it in the Tomcat docs. :-)
Thanks praveen and Pete for your help.
praveen - 29 Oct 2005 16:52 GMT Enjoyed discussing this topic, Thanks. :)
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|