Ejecución de script Python. Rendimiento.

Vamos a comparar el rendimiento de distintas configuraciones de servidores web sirviendo páginas dinámicas programadas con Python, en concreto vamos a servir un CMS Mezzanine (Instala algunas páginas de demostración durente la instalación: Would you like to install some initial demo pages?).

Las configuraciones que vamos a realizar son las siguientes:

  • apache2 + Módulo wsgi
  • apache2 + gunicorn
  • apache2 + uwsgi
  • nginx + gunicorn
  • nginx + uwsgi

Tarea 1 (2 puntos)(Obligatorio): Documenta la instalación del módulo wsgi de apache2. Muestra los ficheros de configuración y muestra la ejecución del CMS.

Los paquetes necesarios son:

root@bob:/home/debian# apt install apache2 libapache2-mod-wsgi python-virtualenv python python-setuptools python-dev build-essential

Creamos un entorno virtual

debian@bob:~$ virtualenv mezzanine
Running virtualenv with interpreter /usr/bin/python2
New python executable in /home/debian/mezzanine/bin/python2
Also creating executable in /home/debian/mezzanine/bin/python
Installing setuptools, pkg_resources, pip, wheel...done.
debian@bob:~$ cd mezzanine/
debian@bob:~/mezzanine$ source bin/activate
(mezzanine) debian@bob:~/mezzanine$

En el entorno virtual instalamos mezzanine y creamos un proyecto

(mezzanine) debian@bob:~/mezzanine$ pip install mezzanine
(mezzanine) debian@bob:~/mezzanine$ mezzanine-project mezza

Una vez creado, ejecutamos:

(mezzanine) debian@bob:~/mezzanine$ cd mezza/
(mezzanine) debian@bob:~/mezzanine/mezza$ python manage.py collectstatic
(mezzanine) debian@bob:~/mezzanine/mezza$ python manage.py collecttemplates
(mezzanine) debian@bob:~/mezzanine/mezza$ python manage.py createdb
...
A site record is required.
Please enter the domain and optional port in the format 'domain:port'.
For example 'localhost:8000' or 'www.example.com'. 
Hit enter to use the default (127.0.0.1:8000):

Creating default site record: 127.0.0.1:8000 ...

Creating default account ...

Username (leave blank to use 'debian'): 
Email address: m.romeroangulo@gmail.com
Password: 
Password (again): 
Superuser created successfully.
Installed 2 object(s) from 1 fixture(s)

Would you like to install some initial demo pages?
Eg: About us, Contact form, Gallery. (yes/no): yes

Creating demo pages: About us, Contact form, Gallery ...

Installed 16 object(s) from 3 fixture(s)

Lo siguiente es indicar los ALLOWED_HOSTS en mezza/local_settings.py:

# Domains for public site
ALLOWED_HOSTS = ["172.22.200.103","127.0.0.1"]

Para configurar apache, copiamos el default a mezzanine.conf y cambiamos lo parámetros necesarios para que quede:

<VirtualHost *:80>
 DocumentRoot /home/debian/mezzanine/mezza/

Alias /static /home/debian/mezzanine/mezza/static

<Directory /home/debian/mezzanine/mezza/static>
 Require all granted
 </Directory>

<Directory /home/debian/mezzanine/mezza/mezza>
 <Files wsgi.py>
 Require all granted
 </Files>
 </Directory>

WSGIDaemonProcess mezzanine \
 python-home=/home/debian/mezzanine \
 python-path=/home/debian/mezzanine/mezza/:/home/vagrant
 WSGIProcessGroup mezzanine
 WSGIScriptAlias / /home/debian/mezzanine/mezza/mezza/wsgi.py

ErrorLog ${APACHE_LOG_DIR}/mezzanine.log
 CustomLog ${APACHE_LOG_DIR}/mezzanine.log combined
</VirtualHost>

Los siguientes pasos son:

root@bob:/etc/apache2/sites-available# a2dissite 000-default.conf 
Site 000-default disabled.
To activate the new configuration, you need to run:
 systemctl reload apache2
root@bob:/etc/apache2/sites-available# a2ensite mezzanine.conf 
Enabling site mezzanine.
To activate the new configuration, you need to run:
 systemctl reload apache2
root@bob:/etc/apache2/sites-available# systemctl reload apache2

Nos aseguramos que los permisos son los correctos:

root@bob:/etc/apache2/sites-available# chown -R www-data. /home/debian/mezzanine/

1.png

 

Tarea 2 (2 puntos)(Obligatorio): Documenta la instalación y configuración de gunicorn y apache2. Muestra mezzanine funcionando y una comprobación de que, efectivamente, se está usando gunicorn.

La instalación de mezzanine es igual que el punto anterior.

Ahopra instalamos gunicorn en el entorno virtual:

debian@stuart:~/mezzanine$ source bin/activate
(mezzanine) debian@bob:~/mezzanine$ pip install gunicorn

Salimos del entorno virtual y creamos el fichero de configuración del nuevo sitio:

debian@stuart:~/mezzanine/mezza$ cd /etc/apache2/sites-available/
debian@stuart:/etc/apache2/sites-available$ sudo nano gunicorn.conf
<VirtualHost *:80>

DocumentRoot /home/debian/mezzanine/mezza
ProxyPass /static/ !
ProxyPass / http://127.0.0.1:8080/
<Directory /home/debian/mezzanine/>
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/mezzanineerror.log
CustomLog ${APACHE_LOG_DIR}/mezzanineaccess.log combined

</VirtualHost>

Habilitamos los siguientes módulos:

debian@stuart:/etc/apache2/sites-available$ sudo a2enmod proxy proxy_http cache

Añadimos a ALLOWED _HOSTS la 127.0.0.1

root@stuart:/home/debian/mezzanine/mezza# nano mezza/local_settings.py 

ALLOWED_HOSTS = ["172.22.200.101","127.0.0.1"]

Deshabilitamos el sitio de mezzanine y habilitamos el nuevo

debian@stuart:~$ sudo a2dissite 000-default
Site 000-default already disabled
debian@stuart:~$ sudo a2dissite mezzanine
Site mezzanine disabled.
To activate the new configuration, you need to run:
 systemctl reload apache2
debian@stuart:~$ sudo a2ensite gunicorn
Enabling site gunicorn.
To activate the new configuration, you need to run:
 systemctl reload apache2
debian@stuart:~$ sudo systemctl reload apache2

Para que se inicie gunicorn:

root@stuart:/home/debian/mezzanine/mezza# /home/debian/mezzanine/bin/gunicorn -w 2 -b :8080 mezza.wsgi:application
[2018-02-06 17:46:01 +0000] [2674] [INFO] Starting gunicorn 19.7.1
[2018-02-06 17:46:01 +0000] [2674] [INFO] Listening at: http://0.0.0.0:8080 (2674)
[2018-02-06 17:46:01 +0000] [2674] [INFO] Using worker: sync
[2018-02-06 17:46:01 +0000] [2678] [INFO] Booting worker with pid: 2678
[2018-02-06 17:46:01 +0000] [2679] [INFO] Booting worker with pid: 2679

2.png

Tarea 3 (2 puntos)(Obligatorio): Documenta la instalación y configuración de uwsgi y apache2. Muestra mezzanine funcionando y una comprobación de que, efectivamente, se está usando wusgi.

Con la misma instalción de antes, paramos el comando ejecutado para lanzar gunicorn e instalamos uwsgi con pip en el entorno virtual

debian@stuart:/home/debian/mezzanine/mezza# source ../bin/activate
(mezzanine) debian@stuart:/home/debian/mezzanine/mezza# pip install uwsgi

Creamos el fichero de configuración de uwsgi:

(mezzanine) debian@stuart:~/mezzanine/$ nano uwsgi.ini

[uwsgi]
http = :8080
chdir = /home/debian/mezzanine/mezza
wsgi-file = mezza/wsgi.py
processes = 4
threads = 2
logger = file:/home/debian/mezzanine/mezza/uwsgi.log

Recagramos los ficheros estaticos:

python manage.py collectstatic
python manage.py collecttemplates

Habilitamos los siguientes módulos:

debian@stuart:~/mezzanine$ sudo a2enmod proxy proxy_http

El virtualhost lo modificamos para que quede:

<VirtualHost *:80>

DocumentRoot /home/debian/mezzanine/mezza
Alias /static /home/debian/mezzanine/mezza/static
ProxyPass /static/ !
ProxyPass / http://127.0.0.1:8080/
<Directory /home/debian/mezzanine/mezza/static>
Require all granted
Options FollowSymLinks
</Directory>
ErrorLog ${APACHE_LOG_DIR}/mezzanineerror.log
CustomLog ${APACHE_LOG_DIR}/mezzanineaccess.log combined

</VirtualHost>

Reiniciamos apache para aplicar los cambios:

debian@stuart:~/mezzanine$ sudo service apache2 reload

Y comprobamos la configuración:

(mezzanine) debian@stuart:~/mezzanine$ uwsgi --ini uwsgi.ini
[uWSGI] getting INI configuration from uwsgi.ini

3.png

Tarea 4 (2 puntos): Documenta la instalación y configuración de gunicorn y nginx. Muestra mezzanine funcionando y una comprobación de que, efectivamente, se está usando gunicorn.

Se van a necesitar los siguientes paquetas:

root@stuart:/home/debian# apt install nginx virtualenv

Nos vamos al directorio /var/www y creamos un entorno virtual

root@stuart:/home/debian# cd /var/www/
root@stuart:/var/www# virtualenv mezzanine
root@stuart:/var/www# source mezzanine/bin/activate

Instalamos mezzanine y gunicorn y creamos el proyecto

(mezzanine) root@stuart:/var/www# pip install mezzanine gunicorn
(mezzanine) root@stuart:/var/www# mezzanine-project maria

En el fichero settings.py permitimos las conexiones:

(mezzanine) root@stuart:/var/www/mezzanine# nano maria/maria/settings.py

ALLOWED_HOSTS = ["*"]

Ejecutamos los siguientes comandos:

(mezzanine) root@stuart:/var/www/mezzanine/maria# python manage.py collectstatic

(mezzanine) root@stuart:/var/www/mezzanine/maria# python manage.py createdb

 

Nos aseguramos de que los permisos sean los correctos:

root@stuart:/var/www# chown -R www-data. mezzanine/

Modificamos el sitio por defecto para que quede así:

server {
 location /static {
 root /var/www/mezzanine/maria;
 }

location / {
 proxy_pass http://127.0.0.1:8080;
 }
}

Creamos una unidad en /etc/systemd/system/mezzanine.service:

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/mezzanine/maria
ExecStart=/var/www/mezzanine/bin/gunicorn -w 2 -b :8080 maria.wsgi:application

[Install]
WantedBy=multi-user.target

Ejecutamos lo siguiente:

systemctl daemon-reload
systemctl enable mezzanine.service
systemctl start mezzanine.service

Comprobamos que está activo:

root@stuart:/var/www/mezzanine# systemctl status mezzanine.service
● mezzanine.service - gunicorn daemon
 Loaded: loaded (/etc/systemd/system/mezzanine.service; enabled; vendor preset: enabled)
 Active: active (running) since Sun 2018-02-11 18:56:24 UTC; 7s ago
 Main PID: 1789 (gunicorn)
 Tasks: 3 (limit: 4915)
 CGroup: /system.slice/mezzanine.service
 ├─1789 /var/www/mezzanine/bin/python2 /var/www/mezzanine/bin/gunicorn -w 2 -b :8080 maria.wsgi:application
 ├─1793 /var/www/mezzanine/bin/python2 /var/www/mezzanine/bin/gunicorn -w 2 -b :8080 maria.wsgi:application
 └─1795 /var/www/mezzanine/bin/python2 /var/www/mezzanine/bin/gunicorn -w 2 -b :8080 maria.wsgi:application

Feb 11 18:56:24 stuart systemd[1]: Started gunicorn daemon.
Feb 11 18:56:24 stuart gunicorn[1789]: [2018-02-11 18:56:24 +0000] [1789] [INFO] Starting gunicorn 19.7.1
Feb 11 18:56:24 stuart gunicorn[1789]: [2018-02-11 18:56:24 +0000] [1789] [INFO] Listening at: http://0.0.0.0:8080 (178
Feb 11 18:56:24 stuart gunicorn[1789]: [2018-02-11 18:56:24 +0000] [1789] [INFO] Using worker: sync
Feb 11 18:56:24 stuart gunicorn[1789]: [2018-02-11 18:56:24 +0000] [1793] [INFO] Booting worker with pid: 1793
Feb 11 18:56:24 stuart gunicorn[1789]: [2018-02-11 18:56:24 +0000] [1795] [INFO] Booting worker with pid: 1795

4.png

 

Tarea 5 (2 puntos): Documenta la instalación y configuración de uwsgi y nginx. Muestra mezzanine funcionando y una comprobación de que, efectivamente, se está usando wusgi.

Paramos el servicio con gunicorn

root@stuart:~# systemctl stop mezzanine.service

Instalamos uwsgi y las dependencias:

root@stuart:~# apt install build-essential python-dev
root@stuart:~# cd /var/www/mezzanine/
root@stuart:/var/www/mezzanine# source bin/activate
(mezzanine) root@stuart:/var/www/mezzanine# pip install uwsgi

Creamos el uwsgi.ini en la carpeta del proyecto:

[uwsgi]
http = :8080
chdir = /var/www/mezzanine/maria
wsgi-file = maria/wsgi.py
processes = 4
threads = 2
logger = file:/var/www/mezzanine/maria/uwsgi.log

Creamos una unidad de systemd en /etc/systemd/system/uwsgi.service

[uwsgi]
http = :8080
chdir = /var/www/mezzanine/maria
wsgi-file = maria/wsgi.py
processes = 4
threads = 2
logger = file:/var/www/mezzanine/maria/uwsgi.log
root@stuart:~# cat /etc/systemd/system/uwsgi.service 
[Unit]
Description=uWSGI Python
After=syslog.target 
 
[Service]
ExecStart=/var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini
User=www-data
Group=www-data
 
[Install]
WantedBy=multi-user.target
Ejecutamos:
systemctl daemon-reload
systemctl enable uwsgi.service
systemctl start uwsgi.service

Comprobamos el estado:

root@stuart:~# systemctl status uwsgi.service 
● uwsgi.service - uWSGI Python
 Loaded: loaded (/etc/systemd/system/uwsgi.service; enabled; vendor preset: enabled)
 Active: active (running) since Sun 2018-02-11 19:29:26 UTC; 21min ago
 Main PID: 4293 (uwsgi)
 Tasks: 10 (limit: 4915)
 CGroup: /system.slice/uwsgi.service
 ├─4293 /var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini
 ├─4297 /var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini
 ├─4298 /var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini
 ├─4299 /var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini
 ├─4300 /var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini
 └─4301 /var/www/mezzanine/bin/uwsgi --ini /var/www/mezzanine/maria/uwsgi.ini

Feb 11 19:29:26 stuart systemd[1]: uwsgi.service: Main process exited, code=killed, status=9/KILL
Feb 11 19:29:26 stuart systemd[1]: Stopped uWSGI Python.
Feb 11 19:29:26 stuart systemd[1]: uwsgi.service: Unit entered failed state.
Feb 11 19:29:26 stuart systemd[1]: uwsgi.service: Failed with result 'timeout'.
Feb 11 19:29:26 stuart systemd[1]: Started uWSGI Python.
Feb 11 19:29:26 stuart uwsgi[4293]: [uWSGI] getting INI configuration from /var/www/mezzanine/maria/uwsgi.ini

5.png

Estudio de rendimiento

Ahora utilizando el script benchmark.py, realiza las pruebas de rendiemento para cada una de las configuraciones anteriores.

Tarea 6 (5 puntos): Entrega la configuración del script de pruebas para cada una de las configuraciones. Entrega los datos obtenidos y la gráfica que has generado.

IMPORTANTE: Hay que tener el paquete apache2-utils instalado, ya sea para para apache o nginx.

apache2 + Módulo wsgi

CONN =[1,10,25,50,75,100]
TITULO="apache2 + wsgi"
DURATION="10"
IP="127.0.0.1"
URLS=["contact/legals","blog","about/team"]
SERVERS=[]
 984,22 933,196666667 1024,346667 987,696666667 982,09 994,3166673

apache2 + gunicorn

CONN =[1,10,25,50,75,100]
TITULO="apache2 + gunicorn"
DURATION="10"
IP="127.0.0.1"
URLS=["contact/legals","blog","about/team"]
SERVERS=[]
 1049,96666667 1922,19666667 1998,57666667 2181,106667 2121,27 2140,85

apache2 + uwsgi

CONN =[1,10,25,50,75,100]
TITULO="apache2 + uwsgi"
DURATION="10"
IP="127.0.0.1"
URLS=["contact/legals","blog","about/team"]
SERVERS=[]
956,856666667 1993,55666667 1940,57666667 1964,89 2193,02 1955,27666667

nginx + gunicorn

CONN =[1,10,25,50,75,100]
TITULO="nginx + gunicorn"
DURATION="10"
IP="127.0.0.1:8080"
URLS=["contact/legals","blog","about/team"]
SERVERS=[]
1131,68666667 2425,35666667 2243,516667 2314,37 2143,24 2143,29

nginx + uwsgi

CONN =[1,10,25,50,75,100]
TITULO="nginx + uwsgi"
DURATION="10"
IP="127.0.0.1"
URLS=["contact/legals","blog","about/team"]
SERVERS=[]
995,09 2449,33666667 2438,35666667 2740,51 2423,016667 2459,80666667

Gráfica:

23.png

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *