UWSGI + nginx for django app avoid pylibmc multi-thread concurrency problem?

Introduction

This week I came across this very interesting problem, it is better to start with some facts:

  • pylibmc not thread safe when used as a django memcached backend; running multiple instances of django directly in the shell will crash on hit with simultaneous requests.
  • when deploying with nginx + uWSGI, this problem with pylibmc is magically distributed.
  • if you switch the django cache backend to python-memcached , it will solve this problem too, but this question is not about that.

Development

start with the first fact, here is how I reproduced the pylibmc problem:

pylibmc crash

I have a django application that does a lot of memcached read and write, and there is this deployment strategy that I run several django processes in the shell, bind to different ports (8001, 8002) and use nginx to balance it.

I initiated two separate load tests for these two django instances using locust , and here is what happens:

fail_proof

In the above screenshot, they both crashed and reported exactly the same problem, something like this:

The statement "ptr-> query_id == query_id +1" failed for the function "memcached_get_by_key", probably for "error Programmer, request_id was not increased." at libmemcached / get.cc: 107

uWSGI to the rescue

So, in the above case, we learned that a multithreaded parallel request to memcached via pylibmc can cause a problem, it somehow does not bother uWSGI several workflows.

To prove this, I start uWSGI with the following parameters:

 master = true processes = 2 

This tells uWSGI to start two workflows, then I will tell nginx about the server about any static django files and route non-static uWSGI requests to find out what happens. With the server running, I run the same locust test against django in localhost and make sure that within a few seconds the number of requests is required to simultaneously request memcached, here is the result:

uwsgi_success

There are no signs of dead workflows in the uWSGI console, and the worker was not restarted, but looking at the top of the screenshot, there were necessarily parallel requests (5.6 req / s).

Question

I am very curious how uWSGI remove this, and I could not find out what in their documentation, to repeat, the question is:

How did uWSGI manage the workflow so that multi-threaded memcached requests do not cause a django crash?

Actually, I'm not even sure if this is the way uWSGI manages workflows that avoid this problem, or some other magic that comes with uWSGI that does the trick, I saw something called the memcached router in their documentation. that I did not quite understand, is this connected?

+6
source share
1 answer

Isn't that because you actually have two separate processes controlled by uWSGI? Since you are setting the process option instead of the employee option, so in fact you should have several uWSGI processes (I assume that the master + two employees due to the configuration you use). Each of these processes will have its own loaded pylibmc, so there is no sharing between the threads (you still haven't configured the threads for uWSGI).

+2
source

Source: https://habr.com/ru/post/983844/


All Articles