In the Tomcat container, do all the filters associated to a servlet and the servlet itself use the same thread? i.e, will doFilter() be run in the same thread as a servlet's service() method? Thanks in advance.
I suspect the question is more: Can I use ThreadLocal objects to pass data between filters and to servlets? In which case the answer is, absolutely. App servers do this themselves to track security, transaction, connection and other request information.
Just make sure you clean out your ThreadLocal in a finally block in the same code that sets the ThreadLocal.
As already noted by other, the servlets themselves may or may not be synchronized, but that is orthogonal to the concept of thread state; i.e. how many threads execute against object foo vs. can I put state in the thread and have it seen by object foo. The answer to the second question is always yes.
The only time the answer would be 'no' is if you made use of any asynchronous communication:
Dispatched the call via AsyncContext
mixed in EJBs and started making use of #Asynchronous or the TimerService
These involve the app server starting new threads not associated with the original request thread so any ThreadLocal state will not travel with the new thread. It is also why those APIs do not allow security and transaction context of the caller to be propagated to the method invoked as the caller and method are in different threads.
Advanced note, InheritableThreadLocal typically does not work as async calls are typically done by the server against a thread pool rather than creating child threads of the caller thread.
Yes, each request is performed in a single thread, including all filters and the target servlet.
Yeah, each request is performed within a single servlet instance.Servlet container receives each request and start a new thread which contains the HttpServletRequest and HttpServletResponse. This thread process the request in the service method of the servlet instance and will be destroyed as soon as the service method completes.
Related
Is it possible to disable the reuse of the ServletRequest instance for each request? It looks like the instance is reused multiple times (maybe bound per TCP session?)
What you can see in the spec :
3.13 Lifetime of the Request Object
Each request object is valid only within the scope of a servlet’s service method, or
within the scope of a filter’s doFilter method, unless the asynchronous processing
is enabled for the component and the startAsync method is invoked on the request
object. In the case where asynchronous processing occurs, the request object remains
valid until complete is invoked on the AsyncContext. Containers commonly recycle
request objects in order to avoid the performance overhead of request object
creation. The developer must be aware that maintaining references to request objects
for which startAsync has not been called outside the scope described above is not
recommended as it may have indeterminate results.
In case of upgrade, the above is still true
Containers commonly recycle
request objects in order to avoid the performance overhead of request object
creation
It is container-specific.
In this case it is specific to Jetty.
Jetty recycles the org.eclipse.jetty.server.Request object between requests.
This is normal, is within the definition of the Servlet Spec, and many containers do this.
Be careful of your usage of the HttpServletRequest / ServletRequest / Request object outside of the dispatch from the container.
If you are using it from an AsyncContext you should only use it when you are called by the container, not any other point or from any other thread (unless you are 100% certain you are handling the threading properly, and are ready to handle one of the thousands of corner cases with AsyncContext from a non-container thread)
I understand that the Servlet Containers will use "Thread per request" model, but my question is, will the thread handling the request do all the below steps ?
Obtain thread from pool to handle request and and pass http request and http response objects to Servlet service method.
Invoke service/dao/ logic which could potentially involve delay since I/O operation is done in DB.
Return the Http response
Return the thread to the Container Thread pool
My main questions is, if somehow the I/O operation on step 2 takes a huge amount of time, will the Servlet container run out of threads from the pool ? Or does the Container use one thread/threads just to handle the request and then delegates the work to another thread to do the rest of the work ? Also I heard that nowadays they are changing the model to a Threaded Model with NIO operations? Thank you.
will the same thread be used for everything ?
TL;DR - No.
Once the Servlet Container (Catalina) spins up the thread per request, that thread is deallocated/exited right after that request-response cycle is finished (that is, corresponding HTTP request handler Servlet method returns).
If your service (DAO/logic/whatever) layer will block the thread, which eventually blocks the web layer (doGet(), doPost() or etc.), browser will go idle, awaiting the response (time is either default or configured), and Catalina (Servlet Container) will block that thread only (other requests may arrive successfully);
I/O (or to be specific Request-Response) timeout will be either default (which is 60 seconds, but it depends on the Tomcat version), or configured by yourself;
Design of the architecture, to delegate discrete incoming HTTP Message to separate threads, has a sole and simple purpose - to process the Request-Response cycles in isolation.
Head First Servlets & JSP:
The Container automatically creates a new Java thread for every servlet request it receives. When the servlet’s done running the HTTP service method for that client’s request, the thread completes (i.e. dies).
Update to your updated question
my question is, will the thread handling the request do all the below steps?
TL;DR - No again.
Servlet Objects live in container, which is a completely separate thread.
When the HTTP message (request, in this case) hits the Servlet-mapped endpoint, this happens:
Servlet Container creates HttpServletResponse and HttpServletRequest objects;
Container allocates(creates) a new thread for that request and response objects (Important: in order to isolate client-server communication.);
Container then passes those request and response objects to the servlet thread;
Container then calls the Servlet API's service() method and depending on what is the type of incoming message (GET, POST, etc.), it invokes corresponding method (doGet(); doPost(); etc.);
Container DOES NOT CARE whatever levels or layers of architecture you have - DAO, Repository, Service, Cherry, Apple or whatever. It will wait until the corresponding HTTP request handler method finishes (accordingly, if something blocks it, container will block that thread);
When the handler method returns; thread is deallocated.
Answering your further questions
My main questions is, if somehow the I/O operation on step 2 takes a huge amount of time, will the Servlet container run out of threads from the pool ?
Theoretically it can; however, that means, that it should block all the 200 threads at the same time and this time (if the default configuration is maintained) it will not accept any other requests (until some thread deallocates).
This, however, can be configured with maxThreads attribute and you can choose what should be the threshold number of request processing threads allowed in Tomcat.
Or does the Container use one thread/threads just to handle the request and then delegates the work to another thread to do the rest of the work?
We have answered this above.
Also I heard that nowadays they are changing the model to a Threaded Model with NIO operations?
NIO specific configuration and it can facilitate poller threads, which are used to simultaneously handle multiple connections per thread; however, this is a big and completely different topic. For the further reading, have a look a this and this.
PLEASE, make sure that your future posts are not too broad, containing 10 different questions in a single post.
I'm trying to cache values in a ConcurrentHashMap in the Session. In order to avoid race conditions and ensure that my map is created before any threads attempt to use it, I use HttpSessionListener.sessionCreated() to add the map to the Session:
#Override
public void sessionCreated(HttpSessionEvent event) {
event.getSession()
.setAttribute(MY_CACHE_KEY, new ConcurrentHashMap());
}
Is this code guaranteed to complete before any other threads access the session (via request.getSession() for example)?
I looked at the HttpSessionListener JavaDoc and the Servlet 4.0 Spec. and there don't seem to be any guarantees about thread safety.
The Serlvet Spec. references session thread-safety a few times, but none of these references related to session listeners and session creation as I understand them:
7.7.1 Threading Issues
Multiple servlets executing request threads may have active access to the same session object at the same time. The container must ensure that manipulation of internal data structures representing the session attributes
is performed in a thread safe manner. The Developer has the responsibility for thread safe access to the attribute objects themselves. This will protect the attribute collection inside the HttpSession object from concurrent access,
eliminating the opportunity for an application to cause that collection to become corrupted. Unless explicitly stated elsewhere in the specification (for example Section 7.7.1, “Threading Issues” on page 7-67 for session objects), objects vended from the request or response must be assumed to be non thread safe. This includes, but is not limited to the PrintWriter returned from
ServletResponse.getWriter() and the OutputStream returned from ServletResponse.getOutputStream().
11.5 Listener Instances and Threading
The container is required to complete instantiation of the listener classes in a Web application prior to the start of execution of the first request into the application. The container must maintain a reference to each listener instance until the last request is serviced for the Web application.
Attribute changes to ServletContext and HttpSession objects may occur concurrently. The container is not required to synchronize the resulting notifications to attribute listener classes. Listener classes that maintain state are responsible for the integrity of the data and should handle this case explicitly.
It seems obvious that sessionCreated() must complete before threads have access to the session, but "obviously correct code" has been unsafe for multithreading before.
This ambiguity doesn't exist for ServletContextLister.contextInitialized() since it is guaranteed to complete before Servlet initialization and Servlet.init() is guaranteed to be single-threaded and occur before any requests.
I've tested Tomcat at least and it does ensure that sessionCreated() completes before request.getSession() returns. I tested by putting a breakpoint in sessionCreated() and sending a request which called request.getSession(). This request didn't complete until I continued from the breakpoint. However, one Servlet container implementation's behavior isn't really conclusive proof that all containers/servers behave this way.
I have few questions. As far as I know, every request to a container becomes a HttpServletRequest. More request-> more instances of HttpServletRequest. Then, when a request object calls a servlet called 'abc', an instance of 'abc' servlet is created. Let's say same time 3 requests come to 'abc' servlet ,then
(1) I want to know ,does it mean, 3 instances of 'abc' servlet per each request are created? or requests are queued till one request to the servlet is done.
Then let's say,3 request to 'abc' servlet do some database processes which could be insertions and retrieves at the same time. Then
(2) does one request should be in the queue until other request's servelt completes the task (synchronize)or all servelets do their DB task as multi threads as seperate tasks(not sinchronized) ?
(3). If they work as not synchronized, how can we make those tasks synchronized (lets say, only one particular task-save some thing to DB) and queued ? to do so, is it better to implement the servlet SingleThreadModel or use a method which is in a class created according to singleton pattern ? Then how it affect to the performance of the container?
In short,how can we run a particular task synchronized for all requests ?
I read this as well. That article says about servlets. Lets say the task of a servlet is handed over to another class, then I would like to know how about using singleton pattern on this?
A container may create a pool of servlet instances (an excerpt from a servlet spec below explains the details). It may use three different instances for three concurrent requests or may use one for all three. Your servlets thus need to be thread safe and shouldn't have state in their member variables. The SingleThreadModel marker interface will signal to container not to use same instance of the servlet for more than one concurrent request (thus making your servlet thread-safe) but it won't prevent the container from creating multiple instances and using them simultaneously. makes sense? if your operation requires synchronization then you handle it in your Model classes, not your Controller. So basically synchronize (or queue things up) elsewhere is the answer. Let the servlets take the command and just run with it without putting too much thoughts into the process.
UPDATE. A very basic example of explicit operation synchronization for your case (not that I like it, just to illustrate the point) would be to have a singleton service handling your operation with its main do() method declared as synchronized. Ideally, though, you would delegate database concurrency to your database and persistence layer (transactions, optimistic concurrency).
CORRECTION as per the servlets spec:
In the default case of a servlet not implementing SingleThreadModel and not hosted in a
distributed environment, the servlet container must use only one instance of a servlet class
per servlet definition.
In the case of a servlet that implements the SingleThreadModel interface, the servlet
container may instantiate multiple instances of that servlet so that it can handle a heavy
request load while still serializing requests to a single instance.
With that said, you would have only one instance of your servlet unless you use that single thread model marker.
1) No, only instance of servlet exists per server
2) No, each request is separate thread
Your server could shouldn't contain any instance variables (or) static variables, then synchronization won't be any issue because each thread will have it's own copy of local variables and execution sequence.
3) You can make servlet synchronized by prefixing synchronized the doGet(), doPost() methods are with the help of synch block. But it is bad practice.
Refer this SO Wiki link for complete discussion.
to synchronize a particular task, Let me suggest 2 ways.
use java synchronized block. You should consider what object is suitable for the lock object.
use database lock. Such as select * from xxx for update
I am running into a situation where I use ThreadLocal static variable to hold a bean that contains various metrics values from different classes during the lifecycle of the request. In a filter I create the bean and set it in a thread local variable and remove it from the thread local variable in the same filter after request has been processed. What I am running into is that the bean containing values from other requests! The only explanation for this is the thread being shared to process multiple requests at the same time. So the question in the title.
While one thread will generally process a single request (speaking about tomcat, for sure), the thread may process multiple requests over time but not w/o finishing the existing request, unless using include/forward alikes.
I'd VERY strognly recommend you to use attribute (setAttribute()) of the said request w/ your bean and use it for profiling. If you can't provide the request to various methods... well you are stuck w/ the ThreadLocal [which is not so bad solution].
Alternatively you can post the code how you install/remove the threadLocal bean.
Keep in mind that you have to to some managing the of that bean as well (it will not be available outside the request).
Edit: forgot to ask: do you use try/finally calling doFilter(...)?
the code should be like that
installBean();
try{
chain.doFilter(req, resp);
}finally{
Bean b = deinstallBean();
useTheMetrics(b);
//potentially, process exception, etc
}
It could also be that your filter is not always called in the sequence you expect it to be. Threads are reused to process multiple requests one after another, so if the removal of the value in the ThreadLocal does not happen, it will still be there when the thread processes its next request.
Yes, you can assume that a single thread will process each request.
Use a finally block to clear (set to null) the ThreadLocal in the filter after processing the rest of the chain. That will prevent data from previous requests from being mingled with the current request.