Python Falcon and Asynchronous Operations

I am writing an API using a combination of python3 + falcon.

There are many places in the methods where I can send the answer to the client, but because of some heavy code that performs DB, i / o, etc. operations, it must wait for the end of the heavy part.

For instance:

class APIHandler: def on_get(self, req, resp): response = "Hello" #Some heavy code resp.body(response) 

I could send "Hello" in the first line of code. I want to run the heavy code in the background and send a response, regardless of when the heavy part ends.

Falcon does not have async features built in, but they mention that it can be used with something like gevent. I did not find any documentation on how to combine the two.

+5
source share
3 answers

I use Celery for asynchronous work. I do not know about gevent. Take a look at this http://celery.readthedocs.org/en/latest/getting-started/introduction.html

+3
source

Client libraries have different support for asynchronous operations, so a solution often comes to which the asynchronous approach is best supported by your specific client client (s), in combination with the WSGI server that you would like to use. See also below for some of the most common options ...

For libraries that do not support the asynchronous interaction model, either initially, or through some kind of subclass mechanism, tasks can be delegated to the thread pool. And for particularly lengthy tasks (i.e., the order of a few seconds or minutes), celery is not a bad choice.

A brief overview of some of the most common asynchronous options for WSGI (and Falcon ):

  • Twisted. . Favors a clear asynchronous style and is probably the most mature option. For integration with WSGI infrastructure such as Falcon, twisted.web.wsgi and crochet .
  • asyncio. Shares a lot of ideas from Twisted, but leverages the power of Python 3 to provide a cleaner interface. Long-term, this is perhaps the cleanest option, but requires the evolution of the WSGI interface (see. Also, the expansion of the pulsar on the PEP-3333 as one of the possible approaches). The asynchronous ecosystem is relatively young at the time of this writing; the community is still experimenting with a wide range of approaches to interfaces, templates, and tools.
  • eventlet. Favors an implicit style that seeks to do synchronous viewing of asynchronous code. One way is to use I / O modules using monkeys in the standard library. Some people don't like this approach because it masks the asynchronous mechanism, which makes extreme cases more difficult to debug.
  • gevent. Like an eventlet, albeit a bit more modern. Both uWSGI and Gunicorn support gevent workgroups that render the standard library harmless.

Finally, it may be possible to extend Falcon to support twisted.web or asyncio (ala aiohttp) support, but I don't think anyone else has tried this.

+6
source

I think there are two different approaches here:

  • Task manager (e.g. celery)
  • Asynchronous implementation (e.g. gevent)

What you achieve with each of them is different. With Celery, you can run all the code needed to compute a response synchronously, and then run any other operation in the background (for example, saving to logs). So the answer should be faster.

With gevent, what you achieve is to run different instances of your handler in parallel. So, if you have one request, you will not see any difference in response time, but if you have thousands of simultaneous requests, the performance will be much better. The reason for this is that without gevent, when your code performs an I / O operation, it blocks the execution of this process, while with gevent, the CPU can continue to execute other requests while waiting for the I / O operation.

Setting up gevent is much easier than installing Celery. If you use gunicorn, you simply install gevent and change the worker type to gevent. Another advantage is that you can parallelize any operation that is required in the response (for example, retrieving the response from the database). In celery, you cannot use the result of the Celery task in your answer.

What I would recommend is to start using gevent and consider adding Celery later (and having both of them) if:

  • The output of the task that you will process using Celery is not required in the answer
  • You have another machine for your celery tasks, or using your server has some peaks and some downtime (if your server is 100% all the time, you will not get anything good from using Celery)
  • The amount of work your celeryn tasks will perform is worth the overhead of using celery
+2
source

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


All Articles