Django App is laggy when Apache2 is used vice development server - django

The setup is:
Windows XP VM (Stuck with this for the time being - we're on an Intranet)
Apache 2,
mod_wsgi
django 1.4
virtualenv
We only have two users at most using this application simultaneously
Everything works but there is significant delay (10-20 seconds) between the browser's request and the response sent back by the server.
If I replace the Apache2 web server with the Django development server (which I do not want to do in production) the app is very responsive. So my assumption is that the problem is with Apache2 configuration or mod_wsgi configuration.
I am not an Apache expert and have spent hours looking for the right settings to configure the Apache2 web server but have failed to find anything that will improve the response.
Any assistance would be greatly appreciated.
Here are the settings that I have either changed or added to my httpd.conf:
# ThreadsPerChild: constant number of worker threads in the server process
ThreadsPerChild 10
# Changed MaxRequestsPerChild 0 to 1 for Django
MaxRequestsPerChild 1
# For Django KeepAlive should be OFF
KeepAlive Off
WSGIApplicationGroup %{GLOBAL}
#######################################
WSGIScriptAlias / "C:/virtual_env/sitar_env2/cissimp/cissimp/wsgi.py"
WSGIPythonPath C:/virtual_env/sitar_env2/Lib/site-packages;C:/virtual_env/sitar_env2/cissimp
Alias /static "C:/virtual_env/sitar_env2/cissimp/cissimp/static"
<Directory "C:/virtual_env/sitar_env2/cissimp/cissimp">
<Files wsgi.py>
Order allow,deny
Allow from all
</Files>
</Directory>
##########################################

Dont set:
MaxRequestsPerChild 1
You are effectively restarting Apache on every request which means having to load the whole Django application on every request. You should not do that.

Related

Django website very slow using Apache and mod_wsgi

so today I tried to host a website using django on a Ubuntu vServer using Apache and mod_wsgi.
First I tested it with a blank django project, and everything worked perfectly, but as soon as I put my django project on the server and set Apache up to run with that, the performance of the server dropped a lot. When accessing the website using apache, the response time is about 10 seconds per page, in contrast do about 100ms when using the django dev server.
I should mentiona that the server has 8GB of ram and a quad-code cpu. When running htop not even 1% CPU usage and about 50MB of ram are used. When im accessing the website, the cpu usage gets really high for a second, just before the website is loaded and then goes back to <1%
Does any body have any tips on what could be the cause of that? I've read that there may be problems with the some mpm workers, but i didnt really find the files i would need to adjust on my server.
The apache server config looks like this(paths changed):
<VirtualHost *:80>
. . .
Alias /static /home/sammy/myproject/static
<Directory /home/sammy/myproject/static>
Require all granted
</Directory>
<Directory /home/sammy/myproject/myproject>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess myproject python-home=/home/sammy/myproject/myprojectenv python-path=/home/sammy/myproject
WSGIProcessGroup myproject
WSGIScriptAlias / /home/sammy/myproject/myproject/wsgi.py
In my error.log file, i also get a lot of these errors:
Mon Nov 23 11:20:12.551962 2020] [wsgi:alert] [pid 26252:tid 140403038272448] (11)Resource temporarily unavailable: mod_wsgi (pid=26252): Couldn't create worker thread 2 in daemon process 'myproject'.
and
Exception ignored in: <bound method BaseEventLoop.del of <_UnixSelectorEventLoop running=False closed=False debug=False>>
Traceback (most recent call last):
File "/usr/lib/python3.6/asyncio/base_events.py", line 526, in del
NameError: name 'ResourceWarning' is not defined
Also, here is the "apachectl status" when idling: https://pastebin.com/D40pRNSY

Apache throws ERROR 500: Internal Server Error when GET from localhost/internal network

I have a production server with apache and django installed using mod_wsgi.
The django application has a REST API that serves some info when a GET request is sent.
This has always worked fine on the develop server, were we ran django using manage.py in a screen. Now we created a production server with apache running django but this API returns Error 500 when running wget from localhost or other machines in the same network (using 192.168.X.X IP).
Here's the output from wget:
~$ wget localhost:80/someinfo
--2020-04-02 16:26:59-- http://localhost/someinfo
Resolving localhost (localhost)... 127.0.0.1
Connecting to localhost (localhost)|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 500 Internal Server Error
2020-04-02 16:26:59 ERROR 500: Internal Server Error.
It seems that the connection succeeds, so I guess it's not an apache problem. The error comes from the API response.
The error in apache error.log looks like this:
127.0.0.1 - - [02/Apr/2020:14:24:36 +0000] "GET /someinfo HTTP/1.1" 500 799 "-" "Wget/1.19.4 (linux-gnu)"
question: what is the number after 500? Sometimes is 799 and other times is 803.
But if the request is done using the public IP of the server from outside (i.e. from the browser) the API works fine and I see the correct information.
I already checked django's allowed hosts and it was accepting localhost, and the 192.168.X.X IP of the other machine. In the end I left django's settings.py like this:
#ALLOWED_HOSTS = ['localhost', '127.0.0.1', '192.168.1.101']
ALLOWED_HOSTS = ['*']
Note: 192.168.1.101 is the machine that tries to make the GET request.
The final goal of all this is to be able to make a GET request from a python script running in that machine (which already works if django runs via manage.py).
My apache.conf:
<VirtualHost *:80>
ServerAdmin webmaster#localhost
#DocumentRoot /var/www/html
Alias /static /home/myuser/myproject/django/static_root
<Directory /home/myuser/myproject/django/static_root>
Require all granted
</Directory>
<Directory /home/myuser/myproject/django/myproject_django>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess myproject python-home=/home/myuser/env python-path=/home/myuser/myproject/django
WSGIProcessGroup myproject
WSGIScriptAlias / /home/myuser/myproject/django/myproject_django/wsgi.py
</VirtualHost>
I tried running django via manage.py and the wget from localhost works just fine. The problem only appears when django is ran by apache.
I also tried the solution given in this post, but changing the line does not fix the error.
I have some doubts concerning this error:
how does apache run django?
does restarting apache2 service also restart django? (thus, reading again the settings.py)
Is there any other django settings file rather than the one I'm editing?
how can I see django logs? I don't have the console now so I can't see real time prints.
I appreciate a lot any help.
I finally managed to solve it myself.
It turns out wsgi handles requests from localhost or external IPs as different instance groups. So all I had to do is put
WSGIApplicationGroup %{GLOBAL}
in /etc/apache2/sites-available/000-default.conf

How to configure Apache to work with Django

I've followed the instructions on Django website for configuring Apache with my Django app on a CentOS 7 server. This included building mod_wsgi from sources to work with the installed python3.4.
Apache restarts without errors but when I hit my app with the URL
http://example.com/myapp/
I get a 503 error like:
Service Temporarily Unavailable
The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
Apache/2.2.15 (CentOS) Server at example.com Port 80
I'm not sure how I troubleshoot what's wrong here. Can anyone help?
Details of the config:
My django app lives at /mnt/net/django/myapp
I've added the file wsgi.conf to my apache conf.d directory and it looks like this:
#LoadModule wsgi_module modules/mod_wsgi.so
# use python34 pip installes mod_wsgi
LoadModule wsgi_module "/usr/lib64/python3.4/site-packages/mod_wsgi/server/mod_wsgi-py34.cpython-34m.so"
#WSGIPythonHome "/usr"
Alias /robots.txt /mnt/net/django/myapp/static/robots.txt
Alias /favicon.ico /mnt/net/django/myapp/static/favicon.ico
Alias /media /mnt/net/django/myapp/media/
Alias /static/ /mnt/net/django/myapp/static/
<Directory /mnt/net/django/myapp/static>
Order deny,allow
Allow from all
</Directory>
<Directory /mnt/net/django/myapp/media>
Order deny,allow
Allow from all
</Directory>
# Allows URLs like example.com/myapp to forward to django
WSGIScriptAlias /myapp /mnt/net/django/myapp/myappsite/wsgi.py process-group=example.com
# Use the virtual env for the myapp site
#WSGIPythonHome /mnt/net/django/myapp/env-myapp-py3-4
# Need to use WSGIDaemon
WSGIDaemonProcess example.com python-home=/mnt/net/django/myapp/env-myapp-py3-4 python-path=/mnt/net/django/myapp
#WSGIPythonPath /mnt/net/django/myapp
<Directory /mnt/net/django/myapp/myappsite>
<Files wsgi.py>
Order deny,allow
Allow from all
</Files>
</Directory>
How to use Django with Apache and mod_wsgi -- follow this: I have done it myself many times, it is very straight forward.
Tip: Create a document and record everything you do whilst setting this up, this way if it doesn't work then you can retrace your steps, but if it does work... Great, you have your very own guide to setting up an Apache server for Django.
Solved my problem (mostly)
The problem is that mod_wsgi with a daemon process tries to write a socket file into the apache logs directory and permissions are denied.
Solution is to tell apache another place to write the socket like this:
WSGISocketPrefix /var/run/wsgi

Django project doesn't show up with Apache and mod_wsgi

I've installed Apache and mod_wsgi on windows xp service pack 3 and added these line to my httpd.conf :
WSGIScriptAlias / "C:/Documents and Settings/X/My Documents/Downloads/Foo/Foo/wsgi.py"
WSGIPythonPath "C:/Documents and Settings/X/My Documents/Downloads/Foo"
<Directory "C:/Documents and Settings/X/My Documents/Downloads/Foo/Foo">
<Files wsgi.py>
Require all granted
</Files>
</Directory>
but when I open localhost on my firefox, it shows Apache's It Works! message, what should I do to run my project on localhost ?
EDIT :
I checked and recognized that my project's path is not included in PYTHONPATH. Isn't the line WSGIPythonPath ... expected to add the address to PYTHONPATH ?
Alright, so my setup is in linux so this is not tested on windows, but:
I did not see your LoadModule statement
File: httpd.conf
LoadModule wsgi_module modules/mod_wsgi.so
modwsgi wont work without that.
Also: the your grant statement seems a bit suspicious.
In the wsgi configuration guide suggests using a Directory directive for allowing this access to your mod_wsgi application.
<Directory "C:/Documents and Settings/X/My Documents/Downloads/Foo/Foo/">
Order allow,deny
Allow from all
</Directory>
Finally:
Make your life easy down the road.
configure apache in worker mode
configure mod_wsgi in daemon mode.
profit
Might I suggest watching this PyCon talk Making Apache suck less for hosting Python web applications from 'the-man' Graham. I wish I knew all of that stuff years ago.
Note: To figure out if you have apache in mpm worker mode.
httpd.exe -V
look for the "Server MPM" value of worker.
Django runs on port 8000 so you'll want to do two things. First, you need to run the server by entering into your console python manage.py runserver. Second, you need to direct your browser to localhost:8000.
As an aside, you don't need Apache to run a simple, local development environment. Django has its own server built in that you can leverage.

Running apache bloodhound on apache2 web server

I am trying to run to apache bloodhound tracker on apache2 web server. I am using 0.7 version of the blood hound. I followed the website https://issues.apache.org/bloodhound/wiki/BloodhoundInstall
Blood hound is running on port 8000.
But the problem is I am not able to run the blood hound on port 80, so that if I hit bloodhound.mydomain.com, I should get bloodhound. I have mentioned my apache2 webserver setting file as specified in the website
/etc/apache2/sites-available/bloodhound
<VirtualHost *:8080>
WSGIDaemonProcess bh_tracker user=ubuntu python-path=/home/ubuntu/bloodhound-0.7/installer/bloodhound/lib/python2.7/site-packages
WSGIScriptAlias /bloodhound /home/ubuntu/bloodhound-0.7/installer/bloodhound/site/cgi-bin/trac.wsgi
<Directory /home/ubuntu/bloodhound-0.7/installer/bloodhound/site/cgi-bin>
WSGIProcessGroup bh_tracker
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
<LocationMatch "/bloodhound/[^/]+/login">
AuthType Digest
AuthName "ubuntu"
AuthDigestDomain /bloodhound
AuthUserFile /home/ubuntu/bloodhound-0.7/installer/bloodhound/environments/main/bloodhound.htdigest
Require valid-user
</LocationMatch>
</VirtualHost>
After adding the above file, its not running on either of the ports 8000 and also 8080 also.
How do I make it run. Kindly help me. By the way I am using ubuntu ec2 instance.
By golly I think I've figured it out! I've been stuck right about where you are on my own Bloodhound port configuration for days.
n3storm is correct: the whole magic of setting up mod_wsgi is that you no longer need to manually start bloodhound with that
tracd port=8080 /ridiculously/long/path/to/bloodhound/installer/bloodhound/environments/main
command. Instead, mod_wsgi runs all that python for you the moment your web browser requests http://[host]:8080/bloodhound, meaning your Bloodhound server is ready to serve the moment it's turned on.
The pain is how many interlocking config files are involved, and how many tiny things can break down the whole process. I don't really know python, I just barely understand Apache, and I'm 70% confident I've accidentally opened some gaping security that I don't understand, but here's my understanding of the mod_wsgi + Apache + Bloodhound domino chain. Paths are for my Apache 2.4 installation on Ubuntu 14.04.1 LTS:
1. You load http://[host]:8080/bloodhound
For this to work, I needed to edit /etc/apache2/ports.conf so that Apache is actually listening on port 8080. So add the line
Listen 8080
to /etc/apache2/ports.conf
Now visiting http://[host]:8080/bloodhound should at least show you something from Apache. For me, it was a HTTP Error 403: Forbidden page, and next up is my home remedy for the Error 403 blues!
2. Apache triggers bloodhound.conf
FULL PATH: /etc/apache2/sites-available/bloodhound.conf
Technically, Apache is looking in /etc/apache2/sites-enabled/ for a matching VirtualHost rule but you set this up by creating/editing .conf files in /sites-availabe/ and then activating them with the Apache command
a2ensite [sitename].conf
So. Apparently, Apache 2.4 changed its access control syntax for .conf files. So, to stop the Error 403ing, I changed
Order deny,allow
Allow from all
in /etc/apache2/sites-available/bloodhound.conf to
Require all granted
And then once again you should restart Apache with
sudo apachectl graceful
or
sudo /etc/init.d/apache2 graceful
or maybe
sudo service apache2 restart
I'm not sure, they all seem to work equally but I suppose the graceful ones are nice because they don't shut down your server or something important like that.
3. bloodhound.conf triggers trac.wsgi
FULL PATH: /ridiculously/long/path/to/bloodhound/installer/bloodhound/site/cgi-bin/trac.wsgi
After figuring out that ton of other things, I realized that, in the end, the default script that Bloodhound generates worked fine for me:
import os
def application(environ, start_request):
if not 'trac.env_parent_dir' in environ:
environ.setdefault('trac.env_path', '/usr/local/bloodhound/installer/bloodhound/environments/main')
if 'PYTHON_EGG_CACHE' in environ:
os.environ['PYTHON_EGG_CACHE'] = environ['PYTHON_EGG_CACHE']
elif 'trac.env_path' in environ:
os.environ['PYTHON_EGG_CACHE'] = \
os.path.join(environ['trac.env_path'], '.egg-cache')
elif 'trac.env_parent_dir' in environ:
os.environ['PYTHON_EGG_CACHE'] = \
os.path.join(environ['trac.env_parent_dir'], '.egg-cache')
from trac.web.main import dispatch_request
return dispatch_request(environ, start_request)
4. trac.wsgi serves up the HTML files for Bloodhound
Isn't the internet just magical?
By using Apache mod_wsgi you don't need Bloodhound running apart anymore. Is mod_wsgi what makes Bloodhound running. You should use standard apache port in this case.
Also, I guess you should use a ServerName directive at Virtualhost (or is it you only serve one host?)