Billah, Tashrif; Bouix, Sylvain; Nicholas, Spero; Mathalon, Daniel; Light, Gregory; Plotly/Dash based web application for checking quality of EEGs, https://github.com/AMP-SCZ/eeg-qc-dash/, 2022, DOI: 10.5281/zenodo.6326487
We have had many app crashes. We attributed the crashes to the development server Plotly uses as default: Flask. Hence, we took up the task of installing uWSGI server. These changes were necessary for a Dash app to run via a uWSGI server. The app visibly runs faster through uWSGI server as expected.
uWSGI was installed according to official documentation:
wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz
tar -zxvf uwsgi-latest.tar.gz
cd uwsgi-*
export PATH=~/miniconda3/bin/:$PATH
make
Notice that we used the main Python for uWSGI install, not an environment Python.
The latter does not have one dynamic library that is required to link with uWSGI.
Accordingly, you should run pip install -r eeg-qc-dash/requirements.txt
on the main Python.
Regardless of Flask or uWSGI server, the following environment variables are defined on the terminal:
export DASH_DEBUG=False
export DASH_URL_BASE_PATHNAME=/eegqc/
export EEG_QC_PHOENIX=/data/predict/data_from_nda/
export PATH=~/uwsgi-2.0.20/:~/miniconda3/bin/:$PATH
export PYTHONHOME=~/mininconda3/
cd ~/eeg-qc-dash/
Afterward, while it is just ./app.py
for Flask, uWSGI has a bit of intricate method for launching the app.
It can be done in two ways.
In this method, Nginx speaks http protocol to uWSGI. It can be slow.
The following section was added to /etc/nginx.conf
:
location /eegqc/ {
proxy_pass http://localhost:8050/;
}
And uWSGI server was launched as follows:
$ uwsgi --http :8050 --wsgi-file wsgi.py --master --processes 1 --threads 1
In this method, Nginx speaks wsgi protocol to uWSGI. It is fast.
References: digitalocean and uwsgi-docs
location /eegqc/ {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8050;
}
$ uwsgi --socket :8050 --wsgi-file wsgi.py --master --processes 1 --threads 1
location /eegqc/ {
include uwsgi_params;
uwsgi_pass unix:///run/uwsgi.sock;
}
$ uwsgi --socket /run/uwsgi.sock --wsgi-file uwsgi.py --master --processes 1 --chmod-socket=666
/tmp/uwsgi.sock
could not be discovered by Nginx apparently because of this issue.
So we used /run/uwsgi.sock
. Now it could be discovered but SELinux prevented Nginx from writing into it:
$ tail -f /var/log/messages
Oct 25 15:15:39 rc-predict setroubleshoot: SELinux is preventing nginx from connectto access on the unix_stream_socket /run/uwsgi.sock. For complete SELinux messages run: sealert -l 262f5c36-68ca-4eeb-a9ff-661a2f94a64e
To circumvent this permission deficit, we had to add a policy to SELinux according to Extend the httpd_t Domain Permissions.
The httpd_can_network_connect
bool was set to 1 as usual.
* The default uWSGI logging was extensive. It may be helpful to limit that as:
--logformat "%(addr) {%(vars) vars in %(pktsize) bytes} [%(ctime)] %(method) %(uri) => generated %(rsize) bytes in %(msecs) msecs (%(proto) %(status))"
*
Windows client from Chrome and Edge browsers was generating invalid request block size: 4132 (max 4096)...skip
error.
We solved this by using --buffer-size 8192 argument.
*
The app was failing to render hundreds of images in a web page.
We solved this by increasing the number of processes used: --processes 4
Before, we explored the idea of increasing the number of open connections: --listen 128
but that did not work.