Am 02.02.2016 um 18:01 schrieb Luca Toscano:
Hi Rainer,

thank you 100 times for this email, it was really helpful! Comments inline:

2016-02-02 17:12 GMT+01:00 Rainer Jung <rainer.j...@kippdata.de
<mailto:rainer.j...@kippdata.de>>:


    The number of worker threads per process is constant during the
    lifetime from the process creation to its end. It is equals to
    ThreadsPerChild and the sole purpose of this configuration item.

This information is not completely trivial to establish simply reading
the documentation, even if all the information are there. Reading
mod_worker's doc can lead to think about this option, but there is
always the space for some doubts..

You are right and it should be made clear in the docs, that all those MPMs work on a fixed number of threads per process basis. If they need to grow, they can only grow by producing new processes (with each again having the same fixed number of threads).

    AsyncRequestWorkerFactor  comes into the image, because in contrast
    to the traditional MPMs prefork, worker and winnt, event does not
    have a 1:1 relation between worker threads and client connections.
    Event is designed to scale better than those in terms of
    connections. It should handle a lot more connections with the same
    number of threads. How can this work? It works by freeing the worker
    threads from the connection handling in certain situations where the
    thread would actually simply wait until it can write back the next
    part of the response or until the next request on the same
    connection arrives. But this design results in some over commitment.
    What happens if by bad luck over time we accepted lots of
    connections, which were mostly idle and then suddenly many of them
    start activity which needs a worker thread for each of them. Then it
    might happen, that we do not have enough worker threads in the
    process that accepted the connections. We don't have a way to move
    such connections to another child process. Once the connection is
    accepted it stays with the same process.


The only thing that I would like to expand a bit would be: "in certain
situations where the thread would actually simply wait until it can
write back the next part of the response or until the next request on
the same connection arrives.", but as Eric told me on #httpd-dev it is a
bit complicate to summarise in few sentences (an easy one is keep
alive). It might not be needed in the documentation, but it would be
good for the people interested in an in depth look without reading the code.

Maybe the mod_status output can be a guidline about interesting states. Have a look at the table part visible under

http://www.apache.org/server-status

The last three columns are all under "Async connections". Thos are connection states which would need a fixed worker thread in the old style MPMs (not event), but need no worker thread for event MPM:

- writing
Writing back the answer to the client, but the TCP write buffer is full, because the connection to the client is too slow so packets pile up. When the next write would block, we instead free the worker thread and wait for that connection to get writable again. Not 100% sure, but I think this only happens when we serve static content. Not in the case of a proxy.

- keep-alive
The response is finished and we wait for the next request to arrive, more precisely for the first packet of the next request.

- closing
Sometimes we need to do a lingering close. That means we want to send back an error or similar, but the error condition happened, before we have read the whole request from the client. If we would simply write back the response and then close the connection, the client - still trying to send the rest of the request -would get a connection reset and could not read our answer. So in such cases, we try to read the rest of the request although we are not interested any more in it, simply to allow the client to consume our response after completing sending the request. There's a time limit for this lingering close but it can take relatively long time. The waits for the next packets from the clients here again happen without a dedicated worker thread.

These three cases are connections, that are not really idle, but need to wait for something to happen. During the waits we free the worker thread (decouple from the connection and allow it to work on another one).

Looking further at the status output, roughly the number "Connections total" would be equals to the sum of the three "Async connections" count plus "Threads busy". In theory this is not rue, because the numbers are retrieved while the output is generated, so some of them change during counting others (the numbers are not retrieved in an atomic way).

If you see in the "accepting" column a "no", it either means, that our over commitment limit is reached, or - more often - that this process is scheduled to end because it has reached it MaxConnectionsPerChild, or we have to many idle processes (MaxSpareThreads) or someone issued "apachectl graceful" etc.

The rest of the explanation is simply great, very easy and
straightforward. I would really like to add some of it to the how it
works section because I think it would help a lot of people.

    ...

    HTH a bit w.r.t. AsyncRequestWorkerFactor (and also hoping that I
    didn't make mistakes in explaining).


Same thing for the second part of the email, I believe that the
directive AsyncRequestWorkerFactor should get more information, maybe
with a little section explaining some directions to take for tuning it.

I want to re-state my point: httpd's documentation contains often all
the information needed but sometimes it misses the necessary background
for the people not heavily involved in the httpd community to get the
whole picture straight away.

Fully agreed.

I'll work on a small patch for the mod_event's documentation, and I'll
send it to the mailing list to get some feedback to get your opinion.

Thanks a bunch!

Rainer

Reply via email to