I am deploying a Flask app using uWSGI running in a docker container. In the app, which has 4 workers, there are some in-memory dictionaries that store "cached values" used by the application to prevent the need to query the DB everytime. These dicts are created when the workers are initialized and I am trying to use uWSGI's Signal Framework to force an update of the caches in all workers.
My initial idea was:
Example:
def update_dicts(sig):
# Update dictionaries here
print('Received signal {}: updating dicts in worker {}'.format(sig, uwsgi.worker_id()))
uwsgi.register_signal(100, "workers", update_dicts)
and trigger the signal in any worker when needed:
uwsgi.signal(100)
However, even with the signal targeting "workers", the signal is received and handled by only one worker, as if it had "worker" as target.
I also tried registering one signal for each worker (using target "workerN") and triggering all of them, but the signals are being sent to any worker, and not to the specified worker:
# Each worker executes this
# Signal registrations: 111, 112, 113, 114
uwsgi.register_signal(110 + uwsgi.worker_id(), "worker{}".format(uwsgi.worker_id()), update_service_dicts)
# To trigger the signals:
for i in [1,2,3,4]:
uwsgi.signal(110 + i)
Application's log:
[uwsgi-signal] signum 113 registered (wid: 3 modifier1: 0 target: worker3)
[uwsgi-signal] signum 112 registered (wid: 2 modifier1: 0 target: worker2)
[uwsgi-signal] signum 114 registered (wid: 4 modifier1: 0 target: worker4)
[uwsgi-signal] signum 111 registered (wid: 1 modifier1: 0 target: worker1)
Mon Jun 5 18:17:51 2017 - error managing signal 112 on worker 4
Received signal 111: updating dicts in worker 1.
Received signal 113: updating dicts in worker 3.
Received signal 114: updating dicts in worker 4.
Triggering another time:
Mon Jun 5 18:18:01 2017 - error managing signal 111 on worker 4
Mon Jun 5 18:18:01 2017 - error managing signal 113 on worker 4
Mon Jun 5 18:18:01 2017 - error managing signal 112 on worker 4
Received signal 114: updating dicts in worker 4.
Am I missing something here or are these targets not yet implemented?
I am currently using the following uwsgi configurations:
[uwsgi]
die-on-term = true
http = 0.0.0.0:9090
mount = /=/path/to/my/app/file.py
callable = app
chdir = /path/to/my/app/
; enable the stats server on port 9191
stats = 0.0.0.0:9191
; log configuration
logto = /var/log/uwsgi/uwsgi.log
; spawn 2 threads in 4 processes (concurrency level: 8)
processes = 4
threads = 2
; drop privileges
uid = pmais
gid = pmais
; Loads apps independently to solve error related to DB connection:
; "SSL error: decryption failed or bad record mac uwsgi"
; Reference: http://stackoverflow.com/a/22753269
lazy-apps = true
catch-exceptions = true
I had similar problems and changed the signalling to 'active-workers' instead of 'workers', as the signalling queue may overflow if non-active workers are signalled. See also https://github.com/unbit/uwsgi/issues/775
def update_dicts(sig):
# Update dictionaries here
print('Received signal {}: updating dicts in worker {}'.format(sig, uwsgi.worker_id()))
uwsgi.register_signal(100, "active-workers", update_dicts)
Also be aware that using 'lazy-apps' will load the app in the workers, possibly registering the signal multiple times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With