You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Thom Park <tp...@inprise.com> on 2000/11/10 02:05:22 UTC

Dispatcher internals?

hello,

Is there any documentation that describes how the tomcat dispatcher
works?
I'm trying to track the flow of control of the request down to the
actual thread running the servlet, the problem
is that I'm still missing something.

Can anyone give a thumbnail sketch of the process execution order?

I'd appreciate any help

thanks,

Thom

"You are in a maze of twisty little passages, all alike"


Re: Dispatcher internals?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Thom Park wrote:

> Craig,
>
> thanks for your patience - I understand now what's going on - the key to my way of
> thinking is that the *requests* are executed on the thread as opposed to the
> *servlet*. It makes sense to me now - akin to riding a bicycle as opposed to a
> bicycle riding you.
>

:-)

>
> On an aside, and this might not be the right place to discuss this. I notice on the
> web.dtd (2.2) that context envs (and ejb-refs and resource-refs) are scoped at the
> Web-app level, not the servlet-level. This seems to me that you cannot have
> java:comp entries for unique to any given servlet as they are all 'global' to the
> web-app.

> Was this the intent of the spec? The reason I ask is that the java:comp entries in
> 'EJB-land' are spec'ed at the Bean level as opposed to the Jar level.
>

Yes, this was intentional.

The "unit" of component-ness in a web application is the application itself.  Whether
the web app has 1 servlet or 1000 servlets is an implementation detail -- <env-entry>,
<resource-ref>, and <ejb-ref> elements define configuration information for the
application as a whole.

If you need to configure things for individual servlets, you can use servlet
initialization parameters in your <servlet> elements.

>
> Just curious...
>
> -Thom
>

Craig





Re: Dispatcher internals?

Posted by Thom Park <tp...@inprise.com>.
Craig,

thanks for your patience - I understand now what's going on - the key to my way of
thinking is that the *requests* are executed on the thread as opposed to the
*servlet*. It makes sense to me now - akin to riding a bicycle as opposed to a
bicycle riding you.

On an aside, and this might not be the right place to discuss this. I notice on the
web.dtd (2.2) that context envs (and ejb-refs and resource-refs) are scoped at the
Web-app level, not the servlet-level. This seems to me that you cannot have
java:comp entries for unique to any given servlet as they are all 'global' to the
web-app.

Was this the intent of the spec? The reason I ask is that the java:comp entries in
'EJB-land' are spec'ed at the Bean level as opposed to the Jar level.

Just curious...

-Thom


"Craig R. McClanahan" wrote:

> Thom Park wrote:
>
> > Craig,
> >
> > thanks for your response, it helped further my understanding of how servlets
> > work. I'm afraid my choice of language made my intent unclear.
> >
> > I'm trying to determine whether a servlet, once activated stays in same
> > thread until it 'dies'.
> >
> > As far as I can tell, a request comes in via one of hte TcpConnectors, this
> > request is then passed to a worker thread for actual processing.
> >
>
> We may still have a terminology issue, but a servlet does not "stay in" a
> thread.  A request, on the other hand, does "stay in" a thread throughout its
> lifetime.
>
> Consider two simultaneous requests to the same servlet.  There will be only one
> instance of the servlet class itself (assuming you don't implement
> SingleThreadModel -- and you should not, for reasons covered in previous
> discussions on this mailing list).  However, two request threads will be active,
> within the doGet() or doPost() method of this servlet, at the same time.
>
> One side effect of this rule is that instance variables in your servlet are
> shared across all requests, but local variables (those defined inside the
> doGet() or doPost() method) are not shared.  Because of this, you should *never*
> store information that is specific to a particular request in an instance
> variable in your servlet.
>
> >
> > If two requests from two separate users come in for the same servlet how is
> > this processed? Are there two separate instances of the servlet running
> > on two threads or are the requests queued against the same execution thread.
>
> The servlet specification defines the rules for how many instances are used.  In
> nearly all cases, there will be one and only one instance of your servlet, per
> servlet definition (i.e. a <servlet> entry in web.xml).
>
> >
> > If so, how does tomcat know how to route the request(s) to the appropriate
> > thread (I suspect it's processed via the Mapper components) but I've yet to
> > find anything like a 'task scheduler' for want of a better word.
> >
>
> The mapper is used to select which servlet to execute (based on matching the
> request URI against the rules you have defined) -- however, it is not used to
> select which thread to use.  The actual techniques used vary depending on which
> version of Tomcat you are running (and which connector you use) -- I will
> describe how Tomcat 4.0 does this because I'm more familiar with it.
>
> When Tomcat 4.0 is first started, a number of threads are created that run
> inside the HttpProcessor class (org.apache.catalina.http.HttpProcessor).
> Essentially, this is a "thread pool" of threads waiting to handle requests.
> These threads sit waiting for work to be assigned to them, in the await()
> method.
>
> When a request comes in, it is received by the server socket in HttpConnector,
> which then picks an available processor and assigns this request to it -- and
> then goes back and listens for the next request.  Because the processor is
> running in another thread, it starts running simultaneously (and it is
> *literally* simultaneously on a multi-processor box when your JVM supports
> native threads :-).  Because more requests can be received (and assigned to
> processors) before the first one is complete, it is easy to see how you can have
> multiple requests running at the same time.  And, if several of these requests
> ask for the same servlet, you will have several threads active running the same
> servlet doGet() or doPost() method.
>
> When a particular request is completed (by a processor thread), one of two
> things happens:
>
> * If the client requested a persistent HTTP/1.1 connection,
>   the processor waits for the next transaction from that client.
>
> * If the request is not persistent, or the persistent connection
>   was closed, the processor goes back into the "available"
>   pool, waiting to be assigned to a new request by
>   HttpConnector.
>
> In Tomcat 4.0, at least, the "complex" part of this whole thing is how a request
> gets assigned to a thread.  Once that happens, you can forget about threads a
> bit, and simply follow the lifetime of a particular request through the
> remainder of the code.
>
> >
> > On an aside, at which point in a the request processing is the servlet
> > actually loaded and, would this loading operation execute on the same thread
> > as the request is being serviced on?
> >
>
> The servlet spec again defines the rules.  Before the first request is handed to
> your servlet, the init() method must be called *exactly* once.  This can happen
> either at server startup time (if you use a <load-on-startup> element) or the
> first time a particular servlet is requested.
>
> >
> > Again, much of this confusion is caused by my lack of intimacy with the
> > servlet model and tomcat internals, I'm trying to find out as much as I can
> > from the source line but I keep getting lost in different code paths. I
> > beleive that once I am able to link up the request point with the processing
> > engine I should be able to find my way from there.
> >
>
> A read through the servlet spec
> (http://java.sun.com/products/servlet/download.html) will help you tremendously
> in understanding the servlet model, and the reason that Tomcat does things the
> way it does will become much more clear.  It's also important to be familiar
> with how multithreading works in Java for this to be understandable.
>
> >
> > -Thom
> >
>
> Craig


Re: Dispatcher internals?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Thom Park wrote:

> Craig,
>
> thanks for your response, it helped further my understanding of how servlets
> work. I'm afraid my choice of language made my intent unclear.
>
> I'm trying to determine whether a servlet, once activated stays in same
> thread until it 'dies'.
>
> As far as I can tell, a request comes in via one of hte TcpConnectors, this
> request is then passed to a worker thread for actual processing.
>

We may still have a terminology issue, but a servlet does not "stay in" a
thread.  A request, on the other hand, does "stay in" a thread throughout its
lifetime.

Consider two simultaneous requests to the same servlet.  There will be only one
instance of the servlet class itself (assuming you don't implement
SingleThreadModel -- and you should not, for reasons covered in previous
discussions on this mailing list).  However, two request threads will be active,
within the doGet() or doPost() method of this servlet, at the same time.

One side effect of this rule is that instance variables in your servlet are
shared across all requests, but local variables (those defined inside the
doGet() or doPost() method) are not shared.  Because of this, you should *never*
store information that is specific to a particular request in an instance
variable in your servlet.

>
> If two requests from two separate users come in for the same servlet how is
> this processed? Are there two separate instances of the servlet running
> on two threads or are the requests queued against the same execution thread.

The servlet specification defines the rules for how many instances are used.  In
nearly all cases, there will be one and only one instance of your servlet, per
servlet definition (i.e. a <servlet> entry in web.xml).

>
> If so, how does tomcat know how to route the request(s) to the appropriate
> thread (I suspect it's processed via the Mapper components) but I've yet to
> find anything like a 'task scheduler' for want of a better word.
>

The mapper is used to select which servlet to execute (based on matching the
request URI against the rules you have defined) -- however, it is not used to
select which thread to use.  The actual techniques used vary depending on which
version of Tomcat you are running (and which connector you use) -- I will
describe how Tomcat 4.0 does this because I'm more familiar with it.

When Tomcat 4.0 is first started, a number of threads are created that run
inside the HttpProcessor class (org.apache.catalina.http.HttpProcessor).
Essentially, this is a "thread pool" of threads waiting to handle requests.
These threads sit waiting for work to be assigned to them, in the await()
method.

When a request comes in, it is received by the server socket in HttpConnector,
which then picks an available processor and assigns this request to it -- and
then goes back and listens for the next request.  Because the processor is
running in another thread, it starts running simultaneously (and it is
*literally* simultaneously on a multi-processor box when your JVM supports
native threads :-).  Because more requests can be received (and assigned to
processors) before the first one is complete, it is easy to see how you can have
multiple requests running at the same time.  And, if several of these requests
ask for the same servlet, you will have several threads active running the same
servlet doGet() or doPost() method.

When a particular request is completed (by a processor thread), one of two
things happens:

* If the client requested a persistent HTTP/1.1 connection,
  the processor waits for the next transaction from that client.

* If the request is not persistent, or the persistent connection
  was closed, the processor goes back into the "available"
  pool, waiting to be assigned to a new request by
  HttpConnector.

In Tomcat 4.0, at least, the "complex" part of this whole thing is how a request
gets assigned to a thread.  Once that happens, you can forget about threads a
bit, and simply follow the lifetime of a particular request through the
remainder of the code.

>
> On an aside, at which point in a the request processing is the servlet
> actually loaded and, would this loading operation execute on the same thread
> as the request is being serviced on?
>

The servlet spec again defines the rules.  Before the first request is handed to
your servlet, the init() method must be called *exactly* once.  This can happen
either at server startup time (if you use a <load-on-startup> element) or the
first time a particular servlet is requested.

>
> Again, much of this confusion is caused by my lack of intimacy with the
> servlet model and tomcat internals, I'm trying to find out as much as I can
> from the source line but I keep getting lost in different code paths. I
> beleive that once I am able to link up the request point with the processing
> engine I should be able to find my way from there.
>

A read through the servlet spec
(http://java.sun.com/products/servlet/download.html) will help you tremendously
in understanding the servlet model, and the reason that Tomcat does things the
way it does will become much more clear.  It's also important to be familiar
with how multithreading works in Java for this to be understandable.

>
> -Thom
>

Craig



Re: Dispatcher internals?

Posted by Thom Park <tp...@inprise.com>.
Craig,

thanks for your response, it helped further my understanding of how servlets
work. I'm afraid my choice of language made my intent unclear.

I'm trying to determine whether a servlet, once activated stays in same
thread until it 'dies'.

As far as I can tell, a request comes in via one of hte TcpConnectors, this
request is then passed to a worker thread for actual processing.

If two requests from two separate users come in for the same servlet how is
this processed? Are there two separate instances of the servlet running
on two threads or are the requests queued against the same execution thread.
If so, how does tomcat know how to route the request(s) to the appropriate
thread (I suspect it's processed via the Mapper components) but I've yet to
find anything like a 'task scheduler' for want of a better word.

On an aside, at which point in a the request processing is the servlet
actually loaded and, would this loading operation execute on the same thread
as the request is being serviced on?

Again, much of this confusion is caused by my lack of intimacy with the
servlet model and tomcat internals, I'm trying to find out as much as I can
from the source line but I keep getting lost in different code paths. I
beleive that once I am able to link up the request point with the processing
engine I should be able to find my way from there.

-Thom


"Craig R. McClanahan" wrote:

> Thom Park wrote:
>
> > hello,
> >
> > Is there any documentation that describes how the tomcat dispatcher
> > works?
> > I'm trying to track the flow of control of the request down to the
> > actual thread running the servlet, the problem
> > is that I'm still missing something.
> >
> > Can anyone give a thumbnail sketch of the process execution order?
> >
>
> Are you talking about the insides of the servlet container?  If so, your
> best bet is the source code of the container :-)
>
> Let's assume that you have the following code in a servlet A:
>
>     RequestDispatcher rd =
>       getServletContext().getRequestDispatcher("/foo");
>     rd.include(request, response);    // Include servlet B
>
> What happens is that the container returns you an object (an
> implementation of the RequestDispatcher interface) that has looked up
> which servlet will serve the request (based on the context-relative
> path).  Then, when you call it, the following happens:
>
> * Servlet A calls the rd.include() method
>
> * The container modifies the request as described
>   in the Servlet Spec (adding query parameters and
>   request attributes as needed)
>
> * The container calls the service() method
>   of servlet B
>
> * Servlet B generates its output and returns
>   (to the container that called it)
>
> * The container then returns (to servlet A)
>
> * Servlet A can proceed to add more output
>   if it wants to.
>
> Note that the call path is exactly the same on a forward() call,
> although details of modifying the request and response are different.
> In particular, servlet A will get control back -- there is no such thing
> as a global GOTO in Java -- so you will need to put a "return" statement
> after the "rd.forward()" call.
>
> >
> > I'd appreciate any help
> >
> > thanks,
> >
> > Thom
> >
>
> Craig McClanahan


Re: Dispatcher internals?

Posted by "Craig R. McClanahan" <Cr...@eng.sun.com>.
Thom Park wrote:

> hello,
>
> Is there any documentation that describes how the tomcat dispatcher
> works?
> I'm trying to track the flow of control of the request down to the
> actual thread running the servlet, the problem
> is that I'm still missing something.
>
> Can anyone give a thumbnail sketch of the process execution order?
>

Are you talking about the insides of the servlet container?  If so, your
best bet is the source code of the container :-)

Let's assume that you have the following code in a servlet A:

    RequestDispatcher rd =
      getServletContext().getRequestDispatcher("/foo");
    rd.include(request, response);    // Include servlet B

What happens is that the container returns you an object (an
implementation of the RequestDispatcher interface) that has looked up
which servlet will serve the request (based on the context-relative
path).  Then, when you call it, the following happens:

* Servlet A calls the rd.include() method

* The container modifies the request as described
  in the Servlet Spec (adding query parameters and
  request attributes as needed)

* The container calls the service() method
  of servlet B

* Servlet B generates its output and returns
  (to the container that called it)

* The container then returns (to servlet A)

* Servlet A can proceed to add more output
  if it wants to.

Note that the call path is exactly the same on a forward() call,
although details of modifying the request and response are different.
In particular, servlet A will get control back -- there is no such thing
as a global GOTO in Java -- so you will need to put a "return" statement
after the "rd.forward()" call.

>
> I'd appreciate any help
>
> thanks,
>
> Thom
>

Craig McClanahan