4

Question :

  1. how can i know if my apache server has already run in multi-process & multi-thread mode ? because when i load tested it, it giving me same result time with different threads count. i run test with 25 threads and 50 threads.

  2. Is there any adjustment that i have to do in the Django code for the multi-thread / multi-process work?

  3. Am I have to change the MPM config (/conf/extra/httpd-mpm.conf) ?

below is my server detail and configuration :

Server redhat enterprise 6.9
Apache server 2.4.33
Postgre 9.6.6
Python 3.6
Virtualbox RAM 8Gb, 2 Core (4 vCpu).

my httpd.conf :

Listen 8000

LoadModule wsgi_module modules/mod_wsgi.so

Include conf/extra/httpd-vhosts.conf

WSGIScriptAlias / /home/applmgr/Harpa/HarpaBackend/harpa/wsgi.py
WSGIPythonHome /home/applmgr/Harpa/pyenv_sl
WSGIPythonPath /home/applmgr/Harpa/HarpaBackend
WSGIPassAuthorization On

<Directory /home/applmgr/Harpa/HarpaBackend/harpa>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

my httpd-vhosts.conf :

<VirtualHost *:8000>

    Alias /static /home/applmgr/Harpa/HarpaBackend/static
    <Directory /home/applmgr/Harpa/HarpaBackend/static>
        Require all granted
    </Directory>

    WSGIDaemonProcess harpa python-home=/home/applmgr/Harpa/pyenv_sl processes=15 threads=50 python-path=/home/applmgr/Harpa/HarpaBackend  
    WSGIProcessGroup harpa

    <Directory /home/applmgr/Harpa/HarpaBackend/harpa>
        <Files wsgi.py>
            Require all granted
        </Files>
    </Directory>
</VirtualHost>

ps -ef | grep httpd :

applmgr   2817     1  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2818  2817  0 14:18 ?        00:00:04 /opt/apache_http/bin/httpd -k start
applmgr   2819  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2820  2817  0 14:18 ?        00:00:03 /opt/apache_http/bin/httpd -k start
applmgr   2821  2817  0 14:18 ?        00:00:06 /opt/apache_http/bin/httpd -k start
applmgr   2822  2817  0 14:18 ?        00:00:03 /opt/apache_http/bin/httpd -k start
applmgr   2823  2817 26 14:18 ?        00:34:21 /opt/apache_http/bin/httpd -k start
applmgr   2824  2817  0 14:18 ?        00:00:06 /opt/apache_http/bin/httpd -k start
applmgr   2825  2817 47 14:18 ?        01:01:16 /opt/apache_http/bin/httpd -k start
applmgr   2826  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2827  2817 25 14:18 ?        00:33:00 /opt/apache_http/bin/httpd -k start
applmgr   2828  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2829  2817  0 14:18 ?        00:00:03 /opt/apache_http/bin/httpd -k start
applmgr   2830  2817  0 14:18 ?        00:00:03 /opt/apache_http/bin/httpd -k start
applmgr   2831  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2832  2817  0 14:18 ?        00:00:03 /opt/apache_http/bin/httpd -k start
applmgr   2833  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2834  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   2835  2817  0 14:18 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   3875  2817  0 14:23 ?        00:00:00 /opt/apache_http/bin/httpd -k start
applmgr   4979  2642  0 16:26 pts/1    00:00:00 grep httpd

./apachectl -V :

Server version: Apache/2.4.33 (Unix)
Server built:   Apr  9 2018 16:42:03
Server's Module Magic Number: 20120211:76
Server loaded:  APR 1.6.3, APR-UTIL 1.6.1
Compiled using: APR 1.6.3, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     event
threaded:     yes (fixed thread count)
forked:     yes (variable process count)
Server compiled with....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/opt/apache_http"
-D SUEXEC_BIN="/opt/apache_http/bin/suexec"
-D DEFAULT_PIDLOG="logs/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
3
  • That's a very high amount of threads & processes, and yes you do need to modify the MPM set for your setup. Start by reading some docs on that side of things; garron.me/en/blog/apache2-mpm-worker-prefork-php.html Commented Apr 16, 2018 at 8:50
  • 1
    It isn't just MPM settings, and playing with those can actually make things worse. In mod_wsgi it is better to rely on daemon mode, which OP is, and how your configure processes/threads there is separate from MPM settings. Commented Apr 16, 2018 at 10:27
  • @markwalker_ thanks i will look into that docs. Commented Apr 17, 2018 at 3:40

1 Answer 1

9

Setting a high number of threads in Python is usually a bad idea because of the Python GIL. And doing benchmark testing where you excessively overload the system is even worse as it jut exacerbates things and gives unreliable results. I'd recommend not running a Python web server which uses threading at over 40-60% capacity because once you push throughput higher, especially if more CPU bound, then things go rapidly down hill. Benchmarks which send max requests, do this very quickly and so are meaningless.

I would suggest watching the following two conference talk videos which goes into some of the issues.

As a general rule of thumb, do the following:

  • Use daemon mode.
  • Disable embedded mode using WSGIRestrictEmbedded On.
  • Use at most 5 threads per process, unless excessively I/O bound.
  • Use processes over threads, but don't get carried away with processes either.
  • Scale across multiple machines.
  • Instrument the WSGI server and application so now how it performs for real system.

For adding metrics to monitor mod_wsgi see:

If want to discuss metrics, use the mod_wsgi mailing list for latest information.


UPDATE 1

Also watch:

At the end of this it talks about various settings daemon mode you should look at and set. Also see the end of:

for some recommended defaults for daemon process settings.

Sign up to request clarification or add additional context in comments.

4 Comments

hi Graham, thanks for your reply. Is it proper if i set the processes to 10 and thread to 5 ? i have set the WSGIRestrictEmbedded On too. My target conccurent users is 200 users. I will take a look at the link you give, and please bear with me if i come back with another question.
How many processes/threads you need to use depends on how many concurrent requests (not users) you have. Users is not the same thing. Further, you also need to look at your response times. If all your requests were handled in less than 10ms, then theoretically your maximum throughput is 5000 requests per second with 10 processes and 5 threads, although reality means you will not get that much. So how quickly requests is handled is important. Long running requests are a problem. This is why you need metrics in place to understand what your application is doing.
Graham, if i set WSGIRestrictEmbedded On is it enough to make sure my server run in daemon mode ? and then by relying processes and thread in daemon mode, am i have to worry or tune the MPM ?
If you set WSGIRestrictEmbedded On, if you haven't setup daemon mode properly for an application requests will error. One of those videos I linked talks a bit about MPM settings. Requests are still proxied via the Apache child worker processes and so there must be enough capacity to proxy requests at the same time as handling static file assets. You also needs to set daemon process configuration to combat against backlogging and helping your app to recover when overloading occurs. I updated answer with another video which talks about that at end.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.