Saurabh Agrawal wrote:
-----Original Message-----
From: André Warnier [mailto:a...@ice-sa.com] Sent: Wednesday, March 20, 2013 3:27 PM
To: Tomcat Users List
Subject: Re: Tomcat Behavior on Multiple HTTP requests from same browser

Christopher Schultz wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Saurabh,

On 3/19/13 9:46 PM, Saurabh Agrawal wrote:
<Executor name="hybrisExecutor" namePrefix="hybrisHTTP" maxThreads="${tomcat.maxthreads}" minSpareThreads="${tomcat.minsparethreads}" maxIdleTime="${tomcat.maxidletime}"/>

<Connector
port="${tomcat.ajp.port}" maxHttpHeaderSize="8192" maxThreads="200"
protocol="org.apache.coyote.ajp.AjpProtocol" executor="hybrisExecutor" enableLookups="false" acceptCount="100" connectionTimeout="20000" URIEncoding="UTF-8" disableUploadTimeout="true" />

<Connector port="${tomcat.http.port}" maxHttpHeaderSize="8192" maxThreads="${tomcat.maxthreads}" protocol="org.apache.coyote.http11.Http11Protocol" executor="hybrisExecutor" enableLookups="false" acceptCount="100" connectionTimeout="20000" URIEncoding="UTF-8" disableUploadTimeout="true" />

Note that your <Executor> has maxThreads="200" and your <Connector>
uses that <Executor>: your ${tomcat.maxthreads} is being ignored.

That, and the default keepalive setting, are probably the keys here.
And the observation of Chuck about the HTTP and AJP connectors. Over which Connector do the test requests actually come in ?

Saurabh - The actual front end requests come on AJP port. We are using AJP 
protocol for communication between Apache and Tomcat.

Right. So then I suppose that Christopher's note is not applicable. Probablya he misread, because the way in which you pasted the configuration in the email makes it difficult to read, after a couple of cut-and-paste. As far as I can tell, the AJP connector refers to the Executor, and the Executor specifies maxThreads="${tomcat.maxthreads}".

The main point of Christopher was that you specify a "maxThreads" parameter in both of your Connectors, but because they both use the Executor, this parameter is being ignored in the <Connector>, and it is only the maxThreads in the Executor that counts.

It helps in load balancing across the application servers in cluster. There is a separate internal application (not exposed on internet) used by CMS team which is using HTTP connector. I hope that clarifies.

Yes.

And a question : is the "simulation" with the 10000 clients really comparable to what you expect in the reality ? For example, if the simulation requests one page per client, and then does nothing else with that page; but the real clients would get a page, and then immediately request the 50 thumbnail images referenced by that page, conditions would be really different, and keepalive would have a very different effect.

Saurabh - The way we have configured our user journeys are as follows:

User 1: Hits homepage, clicks football link on home page, makes a selection, adds to cart and checkout. So this is one user journey which triggers multiple requests.

Hi. Your usage of "user journey" is a bit obscure (to me at least) in the context of analysing a matter of tomcat request/response performance. I kind of understand what you mean, but it does not really provide the answer to the questions :
- is this what you are using in your tests ?
- are you doing this same series of requests for each of your 10000 "test 
clients" ?
- does this represent (more or less) what you are expecting later "in 
production" ?

The point here was to avoid a case where you would be "optimising" the parameters in function of a benchmark test, and then find out later that your production case is totally different, and your optimal benchmark settings are totally inappropriate for the production case.

> All our assets are served from L3 CDN. So the asset requests never come to the application server.

That, I do not understand. I do not understand what you mean by "assets" here, and I do not understand "L3 CDN". So I cannot tell of this is relevant or not to the problem.
Have pity for the people trying to help you here, who only know Tomcat and 
HTTP/AJP.
Try to use vocabulary that we understand, and you may get better help.

> We have not  set keep alive explicitly anywhere in tomcat.
>
What Chuck was telling you in an earlier message, is that even if you do not set it explicitly, it is set to some default non-zero value by Tomcat.
Look at this page in the on-line documentation :
http://tomcat.apache.org/tomcat-7.0-doc/config/ajp.html#Standard_Implementations

So, by default (unless you explicitly define it),

keepAliveTimeout :      

The number of milliseconds this Connector will wait for another AJP request before closing the connection. The default value is to use the value that has been set for the connectionTimeout attribute.

and

connectionTimeout       

The number of milliseconds this Connector will wait, after accepting a connection, for the request URI line to be presented. The default value for AJP protocol connectors is -1 (i.e. infinite).

So, by default, the keepAliveTimeout is set to "infinite".

So now, read very carefully, because this describes a very specific set of circumstances, which are not really applicable to you, but it is just for basic understanding.

/If/ your clients were connecting directly to a Tomcat basic HTTP Connector (named BIO), and you did not set any explicit keepAliveTimeout or connectionTimeout
and /If/ you were not using an Executor
/Then/ what would happen is this :
1) the client opens a connection to the server's HTTP connector, requesting a "keepalive" connection (that is what browsers do by default in HTTP 1.1)
2) the server, by default, considers this connection as "persistent"
3) the server (in this case, the Connector) allocates a Thread to this connection, and this Thread now listens to what the client is going to say
4) the client sends one request on this connection
5) the allocated Thread receives the request, processes the request, and sends the response. Then it waits, to see if another request comes on the same connection. And if the client keeps the connection open, but does not send any additional request on that connection, the Thread will wait theoretically forever (because that is what the documentation says about the default value of these parameters). So /in this particular case/, you would have one Tomcat Thread that is now dedicated to this connection, doing nothing, but being unavailable to process any other request from any other client.

In other words, /in the particular set of conditions above/, if you wanted to avoid this situation, then you should set the keepAliveTimeout *explicitly*, to some reasonable value.

What is a reasonable value ?
That depends very much on your application.

Let's imagine a counter-example, and suppose that the connection was not a keepalive connection. In that case, for each new request of the client, the client would have to create a *new* TCP connection to the server, to send one request and receive one response. Then the server would close the connection, and for the next request the client would again need to open a new connection. That would be fine if a client was only sending a single request from time to time, because then you would not be tying up resources on the server, that can be better used for something else. But it would be inefficient if the client always retrieves a first html page, and then in that page there are 10 embedded images that the client also needs to retrieve. The client would then have to open and close 10 consecutive times a new connection, each time to retrieve one single image. So if you know that your application is so that a client will always need to retrieve several "objects" one after the other in a short interval, it is better to use one single connection to do this, and thus to ask for a "persistent" or "keep-alive" connection.

You should set the keepAliveTimeout to a time sufficient so that the client has the time to request all the additional objects that it wants, before the server closes the connection. But it should not be too long, because otherwise the Thread is going to wait a long time after the client has sent his last request, before the Thread decides that it has waited long enough, closes the connection, and returns to the pool of available Threads, to do something else. So in the practice today, with normal Internet connection speeds, and normal clients and servers, a keepAliveTimeout of maximum 5 seconds is probably more than enough.
And for that, you should set it /explicitly/ to 5000 (milliseconds).

Now your case is a bit different, because
- you are not using the HTTP BIO connector (you use AJP)
- in front of your Tomcat, is an Apache httpd server. This server has its own keep-alive settings which apply to the connection of the client with Apache httpd. And these keep-alive settings are a bit different from the Tomcat ones (for example, there is a keep-alive timeout, but also a MaxKeepAliveRequests) - between Apache httpd and Tomcat, there is the mod_jk module in Apache, and that module uses its own timeouts (as set in workers.properties), and in addition it uses itself a pool of connections to Tomcat, and this pool of connections has its own rules for keeping alive a connection between Apache and Tomcat.

But the basic principles above apply, and may explain why you are seeing what appears to be one Thread dedicated to one client, forever.











---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to