> On 24 Aug 2017, at 8:49 pm, Dave Williams <
flash...@gmail.com> wrote:
>
> I have an app running under mod_wsgi on a real apache2 instance which takes a LONG time to process requests. This is due to huge quantity of database operations in a single transaction and is fine for our application requirements.
> Due to database locking both the original request (and other requests) have to wait. These fail with gateway timeouts. To resolve this I simply increased the apache2.conf Timeout setting to the worst case number of seconds.
If using straight Apache/mod_wsgi (not mod_wsgi-express) they shouldn't fail with gateway timeouts. So can only assume when saying that error message it is based on what you are know seeing with mod_wsgi-express. The error would be different if using Apache/mod_wsgi directly and you configured it yourself.
> I now have moved to a docker environment using Graham Dumpleton's excellent mod_wsgi-express onbuild container. This uses defaults for apache2 and as a result I am back with the same errors.
FWIW, I really don't recommend onbuild Docker images. I am also not putting new effort into the mod_wsgi-docker image anymore as it isn't built to what I would regard as best practices. Unfortunately people are dependent on the way it worked and so can't change it. I have newer images I have been working on which do things in much better way.
The main problem with onbuild and the mod_wsgi-docker image is that it result in people running their container as root. This is really not a good idea.
> I have spent a morning wandering around the internet and cannot find out the "correct" way to increased the Timeout to the value I require.
> Clearly I could update the prepared httpd config file after it is created but this doesnt seem right.
>
> The mod_wsgi-express start-server help talks about various timeouts but I never needed to tweak anything on my "real" instance in this area. Are some of these relevant to my issue?
> I dont want to randomly start changing things.
>
> Some comments (eg Graham's blogs) indicate httpd settings propagate through (via SERVER_ARGS) and the mod_wsgi-start-server script shows it can be set up in a .whiskey/server_args file (but no required format given).
> The source code for mod_wsg-express is rather opaque in how it starts the httpd instance and under what environment or option switch settings.
You canoeist additional command line arguments for mod_wsgi-express in the .whiskey/server_args file. These will be added at the end of any builtin arguments added by the startup script and so can override prior options if need be. The arguments should be able to be on separate lines if you want.
In your case the main options you are going to want to play with are:
--request-timeout SECONDS
Maximum number of seconds allowed to pass before the
worker process is forcibly shutdown and restarted when
a request does not complete in the expected time. In a
multi threaded worker, the request time is calculated
as an average across all request threads. Defaults to
60 seconds.
--connect-timeout SECONDS
Maximum number of seconds allowed to pass before
giving up on attempting to get a connection to the
worker process from the Apache child process which
accepted the request. This comes into play when the
worker listener backlog limit is exceeded. Defaults to
15 seconds.
--socket-timeout SECONDS
Maximum number of seconds allowed to pass before
timing out on a read or write operation on a socket
and aborting the request. Defaults to 60 seconds.
--queue-timeout SECONDS
Maximum number of seconds allowed for a request to be
accepted by a worker process to be handled, taken from
the time when the Apache child process originally
accepted the request. Defaults to 30 seconds.
--response-socket-timeout SECONDS
Maximum number of seconds allowed to pass before
timing out on a write operation back to the HTTP
client when the response buffer has filled and data is
being forcibly flushed. Defaults to 0 seconds
indicating that it will default to the value of the
'socket-timeout' option.
You may also need to use:
--processes NUMBER The number of worker processes (instances of the WSGI
application) to be started up and which will handle
requests concurrently. Defaults to a single process.
--threads NUMBER The number of threads in the request thread pool of
each process for handling requests. Defaults to 5 in
each process.
--max-clients NUMBER The maximum number of simultaneous client connections
that will be accepted. This will default to being 1.5
times the total number of threads in the request
thread pools across all process handling requests.
Questions I would need answers to make recommends are:
* How long does a request actually take up to?
* How many processes are you running? It will be 1 if you didn't change it.
* How many threads are you running in that process for handling requests? It will be 5 if you didn't change it.
* How many concurrent requests do you expect?
For an I/O bound application, first thing you might do is increase the number of threads. So add to 'server_args' file:
--threads 20
This gives you more capacity to handle concurrent requests.
If you still have a various CPU bound activities, you should balance things out by increasing the number of processes at same time.
--threads 10
--processes 2
Either way, it allows you to have more requests in the Python application waiting directly on the database operation to finish.
If the number of concurrent requests exceeds capacity (threads*processes), then requests will queue up.
If those requests are queued for more than the queue timeout, they will be failed before even being handled and you will see the gateway timeout for those.
This first preference is to increase the capacity because timing out requests in the queue is important as far as recovering a server which temporarily gets stuck and too many requests backlog. If your clients are users, they have probably given up after a while and no point handling a request which has been sitting there a long time when you are already trying to catch up because you reached capacity.
If you still want to allow requests to be queue for longer, then use:
--queue-timeout 30
Make that too large such that requests backlog into the Apache child processes, then you may want to increase maximum number of clients if happy with that.
--max-clients 40
This defaults to 1.5*threads*processes. When you set it you need to work out a value yourself. It should be greater than threads*processes.
As to the Timeout directive, that is a base timeout applying to any single read or write operation on a socket. It can be modified using --socket-timeout, or for specific sub cases the --response-socket-timeout option.
You want to be a little more careful playing with that one. It really depends on how long your request is going to take and needs to be considered in relation to --request-timeout as well.
The request timeout is a notional cap on how long a request is allowed to run before it is failed. How it works is a bit tricky though. In a threaded process, the request timeout is actually an average across all request threads for active requests. So although it says 60 seconds, a request can actually run longer if there was no other requests running and so was still free capacity. It would only kick in at 60 seconds if you had concurrent requests all start at the same time and they all hit 60 seconds running time. This is why really need to understand how long your requests actually run for before can say what to do about it.
Graham