Search code examples
pythoneventlet

Evenlet semaphore, how to limit calls to a particular subprocess?


I need to create a semaphore to restrict the parallel count of a particular subprocess. I am using gunicorn with eventlet workers and allow many simultaneous connections. Mostly these are waiting on remote data. However, they all enter a processing phase at some point and this involves calling a subprocess. This subprocess though should not be run too often in parallel as it is memory/CPU hungry.

Is threading.Semaphore correctly monkey_patch'd and usable with eventlet inside gunicorn?


Solution

  • As I understand the problem:

    • one gunicorn process (this is crucial) spawns N green threads
    • each worker may spawn one or more subprocesses
    • you want to limit total number of subprocesses

    In this case, yes, semaphore will work as expected.

    However, if you have more than one process, they will have separate instances of semaphore and you would observe more subprocesses. In this case, I recommend to move subprocess responsibilities to a separate application, running on same machine and call it via API you like (RPC/socket/message queue/dbus/etc). You could design the system like this:

    user -> gunicorn (any number of processes)
    gunicorn -> one subprocess manager
    manager -> N subprocesses
    

    The manager listens for jobs from gunicorn, spawns a subprocess if needed, maybe reuses existing subprocesses. You may like a job queue system like Beanstalk, Celery, Gearman. Or you may wish to build a custom solution on top of existing message transports like NSQ, RabbitMQ, ZeroMQ.