I also just put up another proposal to consider:

https://review.openstack.org/#/c/156711/

"""Sew over eventlet + patching with threads"""

It goes along the thread usage case, and seems useful to consider/think about (and if it's thrown away, that's ok IMHO, after all thats the point of these discussions) when making this kind of analysis and decision.

-Josh

Mike Bayer wrote:
I’ve spent most of the past week deeply reviewing the asyncio system,
including that I’ve constructed a comprehensive test suite designed to
discover exactly what kinds of latencies and/or throughput advantages or
disadvantages we may see each from: threaded database code, gevent-based
code using Psycopg2’s asynchronous API, and asyncio using aiopg. I’ve
written a long blog post describing a bit of background about non-blocking
IO and its use in Python, and listed out detailed and specific reasons why I
don’t think asyncio is an appropriate fit for those parts of Openstack that
are associated with relational databases. We in fact don’t get much benefit
from eventlet either in this regard, and with the current situation of
non-eventlet compatible DBAPIs, our continued use of eventlet for
database-oriented code is hurting Openstack deeply.

My recommendations are that whether or not we use eventlet or asyncio in
order to receive HTTP connections, the parts of our application that focus
on querying and updating databases should at least be behind a thread pool.
I’ve also responded to the notions that asyncio-style programming will lead
to fewer bugs and faster production of code, and in that area I think there
are also some misconceptions regarding code that’s designed to deal with
relational databases.

The blog post is at
http://techspot.zzzeek.org/2015/02/15/asynchronous-python-and-databases/ and
you’ll find links to the test suite, which is fully runnable, within that
post.

Victor Stinner<vstin...@redhat.com>  wrote:

Hi,

I wrote a second version of my cross-project specification "Replace eventlet with 
asyncio". It's now open for review:

https://review.openstack.org/#/c/153298/

I copied it below if you prefer to read it and/or comment it by email. Sorry, 
I'm not sure that the spec will be correctly formatted in this email. Use the 
URL if it's not case.

Victor

..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.

http://creativecommons.org/licenses/by/3.0/legalcode

=============================
Replace eventlet with asyncio
=============================

This specification proposes to replace eventlet, implicit async programming,
with asyncio, explicit async programming. It should fix eventlet issues,
prepare OpenStack for the future (asyncio is now part of the Python language)
and may improve overall OpenStack performances. It also makes usage of native
threads simpler and more natural.

Even if the title contains "asyncio", the spec proposes to use trollius. The
name asyncio is used in the spec because it is more well known than trollius,
and because trollius is almost the same thing than asyncio.

The spec doesn't change OpenStack components running WSGI servers like
nova-api.  Compatibility issue between WSGI and asyncio should be solved first.

The spec is focused on Oslo Messaging and Ceilometer projects. More OpenStack
components may be modified later if the Ceilometer port to asyncio is
successful. Ceilometer will be used to find and solve technical issues with
asyncio, so the same solutions can be used on other OpenStack components.

Blueprint: 
https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor

Note: Since Trollius will be used, this spec is unrelated to Python 3. See the
`OpenStack Python 3 wiki page<https://wiki.openstack.org/wiki/Python3>`_ to
get the status of the port.


Problem description
===================

OpenStack components are designed to "scale". There are differenet options
to support a lot of concurrent requests: implicit asynchronous programming,
explicit programming, threads, processes, and combination of these options.

In the past, the Nova project used Tornado, then Twisted and it is now using
eventlet which also became the defacto standard in OpenStack. The rationale to
switch from Twisted to eventlet in Nova can be found in the old `eventlet vs
Twisted
<https://wiki.openstack.org/wiki/UnifiedServiceArchitecture#eventlet_vs_Twisted>`_
article.

Eventlet issues
---------------

This section only gives some examples of eventlet issues. There are more
eventlet issues, but tricky issues are not widely discussed and so not well
known. Most interesting issues are issues caused by the design of eventlet,
especially the monkey-patching of the Python standard library.

Eventlet itself is not really evil. Most issues come from the monkey-patching.
The problem is that eventlet is almost always used with monkey-patching in
OpenStack.

The implementation of the monkey-patching is fragile. It's easy to forget to
patch a function or have issues when the standard library is modified. The
eventlet port to Python 3 showed how the patcher highly depends on the standard
library. A recent eventlet change (v0.16) "turns off __builtin__ monkey
patching by default" to fix a tricky race condition: see `eventlet recursion
error after RPC timeout
<https://bugs.launchpad.net/oslo.messaging/+bug/1369999>`_ and `Second
simultaneous read on fileno can be raised on a closed socket #94
<https://github.com/eventlet/eventlet/issues/94>`_ issues. Modules implemented
in C cannot be fully monkey-patched. Recent example: the `Fix
threading.Condition with monkey-patching on Python 3.3 and newer #187
<https://github.com/eventlet/eventlet/pull/187>`_ change forces to use the
Python implementation of ``threading.RLock``, because the C implementation
doesn't use the monkey-patched ``threading.get_ident()`` function to get the
thread identifier, but directly a C function.

Depending on the import order, modules may or may not be monkey-patched. It's a
common trap with eventlet. Monkey-patching makes writing unit tests harder.

Some libraries must be modified to support eventlet monkey-patching. Because
they have to use original modules, not patched modules, for example. Some
patched functions behave differently, which causes issues
in applications using them. Example of an OpenStack issue report to the qpid
mailing list, `QPID and eventlet.monkey_patch()
<https://mail-archives.apache.org/mod_mbox/qpid-dev/201211.mbox/%3c509ac7c4.5030...@redhat.com%3E>`_:
"The lock-up occurs because select() returns that the pipe is ready to be read
from before anything has been written to the pipe".

Since eventlet uses threads, "green" threads, concurrent code must be carefully
written to avoid race condition. The section `Explicit async versus implicit
async programming`_ below explains this problem.

See also drawbacks in the `Eventlet`_ section.


Explicit async versus implicit async programming
------------------------------------------------

Implicit asynchronous code causes a new kind of race condition issues which are
difficult to understand and to fix. It is hard to guess where the scheduler may
switch tasks. The source code of a function should be carefully read to check
if it may yield control to another coroutine or not. A function of an external
module may be modified later to use a blocking function.

When asyncio coroutines access data shared with other coroutines, it's possible
to avoid locks is most cases.

Read the "Ca(sh|che Coherent) Money" section of the `Unyielding
<https://glyph.twistedmatrix.com/2014/02/unyielding.html>`_ article (Glyph,
February 2014): it explains how a simple log (call to a ``log()``
function) can introduce subtle race conditions. It explains how explicit
asychronous programming reduces the risk of introducing bugs. With eventlet, if
log() becomes asynchronous, you have no reminder that you have to take care of
race conditions during a review of the change. With asyncio, you must add
"yield from" before log(): it's a nice reminder to say "hey, be careful: your
code becomes asynchronous."

Disagreements:

* Michael Bayer disagrees with Glyph's post. Threads are used virtually
  everywhere in software, for decades. They aren't perfect but they are
  certainly not as awful as Glyph describes.

See also general articles about asynchronous programming:

* `Async I/O and Python
  <http://blogs.gnome.org/markmc/2013/06/04/async-io-and-python/>`_ by Mark
  McLoughlin (June 2013)
* `Some Thoughts on Asynchronous Programming
  
<http://python-notes.curiousefficiency.org/en/latest/pep_ideas/async_programming.html>`_
  by Nick Coghlan: A good rundown of the general problem


Asyncio and Trollius
--------------------

asyncio is a new module introduced in the standard library of Python 3.4 (March
2014), it was designed (`PEP 3156
<https://www.python.org/dev/peps/pep-3156/>`_) to be a compatible with existing
frameworks like Twisted or Tornado. The main difference with Twisted is that
coroutines are first class citizen.

Advantages:

* Explicit asynchronous programming reduces the risk of race conditions: the
  developer can identify easily where a function (coroutine) can be
  interrupted.
* asyncio is maintained by the Python project and rely on existing modules of
  the standard library like select, selectors or concurrent.futures. No
  need for assembler code (as greenlet).
* asyncio has a good design

Drawbacks:

* asyncio requires Python 3.3 or newer, while OpenStack must support Python
  2.7. This issue was solved with the Trollius project, see below.
* asyncio is young and may have more bugs than other projects. However the
  project is actively developed and its community is active.

Trollius has a large test suite of 883 tests. It is tested on Linux, Windows,
Mac OS X, FreeBSD, etc. asyncio is tested in a continuous integration
infrastruction by buildbots on even more operation systems and various
architectures. At the beginning of February 2015, there are 47 open "issues"
(bugs, enhancements, feature requests, etc.) and 262 closed issues in Python
and Tulip issue trackers. Only one open issue is a bug: `Cancelling wait()
after notification leaves Condition in an inconsistent state
<http://bugs.python.org/issue22970>`_, but ``asyncio.Condition`` is not widely
used.

Trollius is released more often than Python: each time a major bug fixed or a
new cool feature is added. See the `Trollius changelog
<http://trollius.readthedocs.org/changelog.html>`_.

See also `Oslo/blueprints/asyncio
<https://wiki.openstack.org/wiki/Oslo/blueprints/asyncio>`_.


Proposed change
===============

First part (done): add support for trollius coroutines
------------------------------------------------------

Prepare OpenStack (Oslo Messaging) to support trollius coroutines using
``yield``: explicit asynchronous programming. Eventlet is still supported,
used by default, and applications and libraries don't need to be modified at
this point.

Already done:

* Write the trollius project: port asyncio to Python 2
* Stabilize trollius API
* Add trollius dependency to OpenStack
* Write the aioeventlet project to provide the asyncio API on top of eventlet
* Stabilize aioeventlet API
* Add aioeventlet dependency to OpenStack
* Write an aioeventlet executor for Oslo Messaging: code written, change
  approved, but not merged yet (need aioeventlet dependency)

Second part (to do): rewrite code as trollius coroutines
--------------------------------------------------------

Switch from implicit asynchronous programming (eventlet using greenthreads) to
explicit asynchronous programming (trollius coroutines using ``yield``). Need
to modify OpenStack Common Libraries and applications. Modifications can be
done step by step, the switch will take more than 6 months.

The first application candidate is Ceilometer. The Ceilometer project is young,
developers are aware of eventlet issues and like Python 3, and Ceilometer don't
rely so much on asynchronous programming: most time is spent into waiting the
database anyway.

The goal is to port Ceilometer to explicit asynchronous programming during the
cycle of OpenStack L.

Some applications may continue to use implicit asynchronous programming. For
example, nova is probably the most complex part beacuse it is and old project
with a lot of legacy code, it has many drivers and the code base is large.

To do:

* Ceilometer: add trollius dependency and set the trollius event loop policy to
  aioeventlet
* Ceilometer: change Oslo Messaging executor from "eventlet" to "aioeventlet"
* Redesign the service class of Oslo Incubator to support aioeventlet and/or
  trollius.  Currently, the class is designed for eventlet. The service class
  is instanciated before forking, which requires hacks on eventlet to update
  file descriptors.
* In Ceilometer and its OpenStack depedencencies: add new functions which
  are written with explicit asynchronous programming in mind (ex: trollius
  coroutines written with ``yield``). It doesn't make sense to port all Python
  libraries to asyncio. Only libraries which are part of performance bottleneck
  and doing I/O operations may be ported to asyncio. There is always the
  option of running blocking operations in ``loop.run_in_executor()`` to use
  a pool of threads.
* Rewrite Ceilometer endpoints (RPC methods) as trollius coroutines.
* Add a new storage implementation compatible with asyncio. Maybe using
  asyncio-mongo?

Questions:

* The quantity of code which need to be ported to asynchronous programming is
  unknown right now.
* We should be prepared to see deadlocks. OpenStack was designed for eventlet
  which implicitly switch on blocking operations. Critical sections may not be
  protected with locks, or not the right kind of lock.
* For performances, blocking operations can be executed in threads. OpenStack
  code is probably not thread-safe, which means new kinds of race conditions.
  But the code executed in threads will be explicitly scheduled to be executed
  in a thread (with ``loop.run_in_executor()``), so regressions can be easily
  identified.
* This part will take a lot of time. We may need to split it into subparts
  to have milestones, which is more attractive for developers.


Last part (to do): drop eventlet
--------------------------------

Replace aioeventlet event loop with trollius event loop, drop aioeventlet and
drop eventlet at the end.

This change will be done on applications one by one. This is no need to port
all applications at once. The work will start on Ceilometer, as a follow up
of the second part.

To do:

* Port remaining code to trollius
* Write a "trollius" executor for Oslo Messaging
* Ceilometer: Add a blocking call to ``loop.run_forever()`` in the ``main()``
  function
* Ceilometer: Replace "aioeventlet" executor with "trollius" executor
* Ceilometer: Use the standard trollius event loop policy
* Service class: launcher.wait() must now call ``loop.run_forever()``
* Ceilometer: drop the eventlet dependency

Optimization, can be done later:

* Oslo Messaging: watch directly the underlying file descriptor of sockets,
  instead of using a busy loop polling the notifier
* Ceilometer: use libraries supporting directly trollius to be able to run
  parallel tasks (ex: send multiple requests to a database)

Later: replace trollius with asyncio
------------------------------------

When a project will be fully Python 3 compatible and OpenStack will be ready to
drop Python 2 support, it will be possible to replace trollius with asyncio.

Trollius has been designed to be able to easily convert a code base from
trollius to asyncio. For example, ``From(obj)`` just returns ``obj``: it's a
no-op just to be able to replace the ``yield From(...)`` pattern with ``yield
from ...``.

Before that, it may be possible to import asyncio instead of trollius, since
the API is the same, except of the syntax of coroutines.


Alternatives
------------

Use directly asyncio, not trollius
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Trollius is just a "temporary" solution until OpenStack port to Python 3
completes and OpenStack decides to drop Python 2 support.

Libraries only start to support asyncio, supporting trollius may require extra
effort (the effort is not well quantified right now, it may be easier than
expected).

An alternative is to directly replace eventlet with asyncio, without a
temporary step using trollius.

The first requirement is to have an application fully Python 3 compatible.
Unlikely, eventlet is not yet fully Python 3 compatible. Before eventlet 0.15,
released in july 2014, it was not possible to install eventlet on Python 3. So
eventlet was a blocker point to port OpenStack components to Python 3. The
eventlet port to Python 3 is now almost done, see the `Eventlet`_ section
below.

The second requirement is to drop Python 2 application. It may not be
acceptable right now for the whole OpenStack, but it might be acceptable for
some specific applications. RHEL 7 require SCL (Software Collection Library) to
get Python 3.3. Debian Wheezy (latest Debian stable) only provides Python 3.2
which lacks support of ``yield from`` syntax, required by asyncio.

See the `OpenStack Python 3 wiki page
<https://wiki.openstack.org/wiki/Python3>`_ to get the status of the port.


Eventlet
~~~~~~~~

Keep eventlet which is already used.

eventlet is based on greenlet which allows to interrupt any function and
restart it later, as coroutines but implicitly.

Advantages:

* Code just looks sequential, no need for extra effort to write async code.
* Almost all OpenStack component are already using eventlet.

Drawbacks:

* See the `Eventlet issues`_ section
* The developer cannot know where its function will be interrupted. Basically,
  it can be interrupted anywhere. Writing code without race conditions requires
  deep knownledge of how Python and eventlet are implemented.
* Race conditions are unlikely and so are usually only seen on production.
  It's hard to reproduce them. More generally, eventlet is not reliable.
* Not compatible with Python 3. This issue is almost fixed: eventlet 0.16
  mostly work on Python 3 with monkey-patching. Example of remaining issue:
  `Fix threading.Condition with monkey-patching on Python 3.3 and newer
  (PR#187)<https://github.com/eventlet/eventlet/pull/187>`_.
* In january 2015, Eventlet still doesn't support support IPv6:
  `IPv6 support #8<https://github.com/eventlet/eventlet/issues/8>`_
  (issue open since January 2013)

See also the `Eventlet Best Practices
<https://review.openstack.org/#/c/154642>`_ spec.


Threads
~~~~~~~

Advantages:

* Native threads: implemented in the kernel
* No requirement of non-blocking sockets or asynchronous functions: just use
  any kind of blocking function.
* The code is sequential, no callback hell

Drawbacks:

* Programing with threads (native threads or green threads) is hard because the
  code can be interrupted anywhere. It is harder to write "thread-safe" code
  (ex: protecting shared data with locks) than to write asyncio code.
* CPython (the reference Python implementation) has a Global Interpreter Lock
  ("GIL") which reduces the performances of native threads. Only one Python
  instruction can be executed at the same time. The GIL is released for I/O
  operation. PyPy has a STM project to drop it, but this project is
  experimental and it is not yet faster than CPython with GIL.

The `C10K program<http://www.kegel.com/c10k.html>`_ showed that asynchronous
event-driven is the more efficient than threads to handle concurrent requests,
at least for web servers.

The `Unyielding<https://glyph.twistedmatrix.com/2014/02/unyielding.html>`_
article explains how bad are threads and that threads should be avoided. Native
threads should be avoided, but also implicit coroutines like the green threads
of eventlet.

Disagreements:

* Michael Bayer added: "Improving upon GIL has nothing to do with async
  programming. Both the GIL, and explicit async, squeeze all operations through
  a single CPU serially. The GIL does not block on IO. There are no performance
  gains to be had in this regard by async."

asyncio uses native threads. For example, by default, resolving a hostname
calls the ``getaddrinfo()`` function which is blocking: the function is
executed in a thread pool using ``loop.run_in_executor()``. There are
asynchronous DNS resolvers available to avoid threads when resolving hostnames.
More generally, any blocking function can be executed with
``loop.run_in_executor()`` in asyncio to not block the event loop.

David Beazley identified performances issues related to the GIL: see
`Understanding the Python GIL<http://www.dabeaz.com/GIL/>`_. Splitting a
CPU-bound task into multiple threads may slow down the task instead of making
it faster, just because of the GIL. CPU-bound code is the worst case for the
GIL. The GIL has been rewritten in Python 3.2 to enhance performances. The
optimization will not be backported to Python 2.7.


Data model impact
-----------------

NA

REST API impact
---------------

NA

Security impact
---------------

NA

Notifications impact
--------------------

NA

Other end user impact
---------------------

NA

Performance Impact
------------------

The performance impact of rewrite coding as trollius coroutines is unknow yet.
If there is a overhead of using coroutines, it is expected to be low.

We can expect better performances with fully asynchronous clients. See for
example `API Hour benchmark
<https://github.com/Eyepea/API-Hour#quickndirty-http-benchmarks-on-a-kitchen-table>`_
which compares synchronous and asynchronous code for DB requests (using aiopg)
and JSON serialization in a web server: asynchronous code can handle much more
client requests in 30 seconds.

Disagreements:

* Michael Bayer is concerned on performance overhead of coroutines. On the
  microbenchmark `bench_generator.py
  
<https://bitbucket.org/haypo/asyncio_staging/src/2f89fbdc7c12bd2541071648018ab9d484d79703/bench_generator.py>`_,
  consuming a generator takes 951 ns whereas calling a function takes 228 ns:
  consuming a generator is 4.2x slower than calling a function. Basically, the
  microbenchmark measures the time to raise an exception (``StopIteration``)
  and then to catch it: 723 nanoseconds. A database query typically takes 50 ms
  or less.


Other deployer impact
---------------------

NA

Developer impact
----------------

To write efficient code, developers have to learn how to write asyncio code,
but only on functions which must be asynchronous.

Only projects which chose to use asyncio will have to be modified. Other
projects are free to continue to use eventlet.


Implementation
==============

Assignee(s)
-----------

Assignee is for moving these guidelines through the review process to
something that we all agree on. The expectation is that these become
review criteria that we can reference and are implemented by a large
number of people. Once approved, will also drive collecting volunteers
to help fix in multiple projects.

Primary assignee:
  Victor Stinner<vstin...@redhat.com>

Work Items
----------

Work items or tasks -- break the feature up into the things that need
to be done to implement it. Those parts might end up being done by
different people, but we're mostly trying to understand the time-line
for implementation.

Recently merged changes:

* `Add aioeventlet dependency<https://review.openstack.org/#/c/138750/>`_
* `Add a new aioeventlet executor<https://review.openstack.org/#/c/136653/>`_:
  already approved


Dependencies
============

The implementation requires a new dependency: the ``aioeventlet`` module. It is
already added to global requirements.

The ``trollius`` module was already added to global requirements.


Testing
=======

NA


Documentation Impact
====================

NA


Comparison of eventlet and asyncio code
=======================================

Call a function
---------------

eventlet::

    evenlet.spawn(func, arg)

asyncio::

    loop.call_soon(func, arg)

Schedule a function in 10 seconds
---------------------------------

eventlet::

    eventlet.spawn_after(10, func, arg)

asyncio::

    loop.call_later(10, func, arg)

Asynchronous task
-----------------

eventlet::

    def async_multiply(arg):
        # interrupt the execution of the current greenthread
        eventlet.sleep(1.0)
        return arg * 2

    def func():
        gt = eventlet.spawn(async_multiply, 5)
        # block the current greenthread
        result = gt.wait()
        print("5 * 2 = %s" % result)

asyncio::

    @asyncio.coroutine
    def async_multiply(arg):
        # interrupt the execution of the current task
        yield from asyncio.sleep(1.0)
        return arg * 2

    @asyncio.coroutine
    def func():
        # block the current coroutine
        result = yield from async_multiply(5)
        print("5 * 2 = %s" % result)


asyncio
=======

Trollius: asyncio port to Python 2
----------------------------------

asyncio requires Python 3.3 and newer. asyncio was ported to Python 2 in a new
project called `trollius<http://trollius.readthedocs.org/>`_. Changes made in
asyncio are merged in trollius, trollius is a branch of the mercurial
repository of tulip (asyncio upstream).

The major difference between Trollius and Tulip is the syntax of coroutines:

==================  ======================
Tulip               Trollius
==================  ======================
``yield from ...``  ``yield From(...)``
``yield from []``   ``yield From(None)``
``return``          ``raise Return()``
``return x``        ``raise Return(x)``
``return x, y``     ``raise Return(x, y)``
==================  ======================

It is possible to write code working with trollius and asyncio in the same code
base if coroutines are not used, but only callbacks and futures. Some libraries
already support asyncio and trollius like AutobahnPython (Websockets and WAMP),
Pulsar and Tornado.

Another option is to provide functions returning ``Future`` objects, so the
caller can decide to use callback using ``fut.add_done_callback(callback)`` or
to use coroutines (``yield From(fut)`` for Trollius, or ``yield from fut`` for
Tulip). This option is used by the `aiodns<https://github.com/saghul/aiodns>`_
project for example.

On Python 3.3 and newer, Trollius supports also asyncio coroutines. The
trollius module is compatible with asyncio, the opposite is false.

Trollius works on Python 2.6-3.5.


aioeventlet: asyncio API on top of eventlet
-------------------------------------------

In OpenStack, eventlet cannot be replaced with asyncio in all projects in a
single commit. The OpenStack development is made with small and limited
changes. To have a smooth transition, the `aioeventlet project
<http://aioeventlet.readthedocs.org/>`_ was written to support the asyncio API
on top of eventlet. It makes possible to add support for asyncio coroutines to
an existing OpenStack component without having to replace immediatly its
``main()`` function with the blocking call ``loop.run_forever()``.

aioeventlet supports waiting for a task from a greenthread (``yield_future()``)
and waiting for a greenthread from a task (``wrap_greenthread()``).


Databases
---------

asyncio database drivers
~~~~~~~~~~~~~~~~~~~~~~~~

List of database drivers compatible with asyncio:

* MongoDB: `asyncio-mongo<https://bitbucket.org/mrdon/asyncio-mongo>`_
* MySQL: `aiomysql<https://github.com/aio-libs/aiomysql>`_ (based on PyMySQL)
* PostgreSQL: `aiopg<http://aiopg.readthedocs.org/>`_
* PostgreSQL: `psycotulip<https://github.com/fafhrd91/psycotulip>`_ (based on 
psycopg2)
* memcached: `aiomemcache<https://github.com/fafhrd91/aiomemcache>`_
* redis: `aioredis<http://aioredis.readthedocs.org/>`_
* redis: `asyncio-redis<http://asyncio-redis.readthedocs.org/>`_


SQLAchemy
~~~~~~~~~

The aiopg project includes a subset of SQLAlchemy which works with asyncio:
`aiopg.sa<https://github.com/aio-libs/aiopg/tree/master/aiopg/sa>`_.

While most SQLAlchemy functions could be modified to support asyncio, the most
important problem is the lazy loading in the ORM. For example, ``user =
session.query(User).get(1)`` doesn't run any database query, but the following
``user.addresses`` instruction runs a query.

Until SQLAlchemy fully support asyncio, explicit or implicit database queries
can be executed in ``loop.run_in_executor()`` to run them in a thread pool, to
not block the asyncio event loop.

See also the `Performance Impact`_ section: Michael Bayer is concerned by the
performance overhead of coroutines. He spent a lot of time to optimize
SQLAlchemy.


WSGI and HTTP servers
=====================

The WSGI protocol is synchronous and so incompatible with asyncio. There are
"hacks" to support asyncio coroutines with WSGI, like monkey-patching.

Using asyncio, there are other efficient ways to write an HTTP server without
WSGI: see the HTTP server included in aiohttp for example. The problem is that
many OpenStack components rely on the WSGI protocol to support middlewares.
Replacing WSGI protocol is not at option right now.

For these reasons, this spec doesn't concern OpenStack components running WSGI
servers. First, the WSGI protocol should be enhanced or replaced with
something having a native support for asynchronous programming.

Asynchronous WSGI:

* gunicorn: see ``gaiohttp`` worker
* `Pulsar: Asynchronous WSGI
  <http://pythonhosted.org/pulsar/apps/wsgi/async.html>`_
* `uwsgi: uWSGI asynchronous/non-blocking modes
  <http://uwsgi-docs.readthedocs.org/en/latest/Async.html>`_
* `bottle: Greenlets to the rescue
  <http://bottlepy.org/docs/dev/async.html>`_
* etc.


History
=======

aioeventlet project (3rd try, patch now merged!):

* December 3, 2014: two patches posted to requirements:
  `Add aioeventlet dependency<https://review.openstack.org/#/c/138750/>`_
  and `Drop greenio dependency<https://review.openstack.org/#/c/138748/>`_.
* Novembre 23, 2014: two patches posted to Oslo Messaging:
  `Add a new aioeventlet executor<https://review.openstack.org/#/c/136653/>`_
  and `Add an optional executor callback to dispatcher
  <https://review.openstack.org/#/c/136652/>`_
* November 19, 2014: First release of the aioeventlet project

OpenStack Kilo Summit, November 3-7, 2014, at Paris:

* `Python 3 in Oslo<https://etherpad.openstack.org/p/kilo-oslo-python-3>`_:

  * add a new greenio executor to Oslo Messaging
  * port eventlet to Python 3 (with monkey-patching)

* `What should we do about oslo.messaging?
  <https://etherpad.openstack.org/p/kilo-oslo-oslo.messaging>`_: add the new
  greenio executor

* `Python 3.4 transition<https://etherpad.openstack.org/p/py34-transition>`_

greenio executor for Oslo Messaging (second try):

* July 29, 2014: Doug Hellmann proposed the blueprint
  `A 'greenio' executor for oslo.messaging
  <https://blueprints.launchpad.net/oslo.messaging/+spec/greenio-executor>`_,
  approved by Mark McLoughlin.
* July 24, 2014: `Add greenio dependency<https://review.openstack.org/108637>`_
  merged into openstack/requirements
* July 22, 2014: Patch `Add a new greenio executor
  <https://review.openstack.org/#/c/108652/>`_ proposed to Oslo Messaging
* July 21, 2014: Release of greenio 0.6 which is now compatible with Trollius
* July 21, 2014: Release of Trollius 1.0
* July 14, 2014: Patch `Add a 'greenio' oslo.messaging executor (spec)
  <https://review.openstack.org/#/c/104792/>`_ merged into openstack/oslo-specs.
* July 7, 2014: Patch `Fix AMQPListener for polling with timeout
  <https://review.openstack.org/#/c/104964/>`_ merged into Oslo Messaging
* July 2014: greenio executor, `[openstack-dev] [oslo] Asyncio and 
oslo.messaging
  <http://lists.openstack.org/pipermail/openstack-dev/2014-July/039291.html>`_

trollius executor for Oslo Messaging (first try):

* June 20, 2014: Patch `Add an optional timeout parameter to Listener.poll
  <https://review.openstack.org/#/c/71003/>`_ merged into Oslo Messaging
* May 28, 2014: Meeting at OpenStack in action with Doug Hellman, Julien
  Danjou, Mehdi Abaakouk, Victor Stinner and Christophe to discuss the plan to
  port OpenStack to Python 3 and switch from eventlet to asyncio.
* April 23, 2014: Patch `Allow trollius 0.2
  <https://review.openstack.org/#/c/79901/>`_ merged into
  openstack/requirements
* March 21, 2014: Patch `Replace ad-hoc coroutines with Trollius coroutines
  <https://review.openstack.org/#/c/77925/>`_ proposed to Heat. Heat coroutines
  are close to Trollius coroutines. Patch abandonned, need to be rewritten,
  maybe with aioeventlet.
* February 20, 2014: The full specification of the blueprint was written:
  `Oslo/blueprints/asyncio
  <https://wiki.openstack.org/wiki/Oslo/blueprints/asyncio>`_
* February 8, 2014: Patch `Add a new dependency: trollius
  <https://review.openstack.org/#/c/70983/>`_ merged into
  openstack/requirements
* February 27, 2014: Article `Use the new asyncio module and Trollius in 
OpenStack
  <http://techs.enovance.com/6562/asyncio-openstack-python3>`_ published
* February 4, 2014: Patch `Add a new asynchronous executor based on Trollius
  <https://review.openstack.org/#/c/70948/>`_ proposed to Oslo Messaging,
  but it was abandonned. Running a classic Trollius event loop in a dedicated
  thread doesn't fit well into eventlet event loop.

First discussion around asyncio and OpenStack:

* December 19, 2013: Article `Why should OpenStack move to Python 3 right now?
  <http://techs.enovance.com/6521/openstack_python3>`_ published
* December 4, 2013: Blueprint `Add a asyncio executor to oslo.messaging
  <https://blueprints.launchpad.net/oslo.messaging/+spec/asyncio-executor>`_
  proposed by Flavio Percoco and accepted for OpenStack Icehouse by Mark
  McLoughlin


See also
========

Threads on the openstack-dev mailing list:

* `[oslo] Progress of the port to Python 3
  
<http://lists.openstack.org/pipermail/openstack-dev/2015-January/053846.html>`_
  (Victor Stinner, Jan 6 2015)

* `[oslo] Add a new aiogreen executor for Oslo Messaging
  
<http://lists.openstack.org/pipermail/openstack-dev/2014-November/051337.html>`_
  (Victor Stinner, Nov 23 2014)

* `[oslo] Asyncio and oslo.messaging
  <http://lists.openstack.org/pipermail/openstack-dev/2014-July/039291.html>`_
  (Mark McLoughlin, Jul 3 2014)

  * `SQLAlchemy and asynchronous programming
    <http://lists.openstack.org/pipermail/openstack-dev/2014-July/039480.html>`_
    by Mike Bayer (author and maintainer of SQLAlchemy)

* `[Solum][Oslo] Next Release of oslo.messaging?
  <http://lists.openstack.org/pipermail/openstack-dev/2014-March/030304.html>`_
  (Victor Stinner, Mar 18 2014)

* `[solum] async / threading for python 2 and 3
  
<http://lists.openstack.org/pipermail/openstack-dev/2014-February/027685.html>`_
  (Victor Stinner, Feb 20 2014)

* `Asynchrounous programming: replace eventlet with asyncio
  
<http://lists.openstack.org/pipermail/openstack-dev/2014-February/026237.html>`_
  (Victor Stinner, Feb 4 2014)

__________________________________________________________________________
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

__________________________________________________________________________
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

__________________________________________________________________________
OpenStack Development Mailing List (not for usage questions)
Unsubscribe: openstack-dev-requ...@lists.openstack.org?subject:unsubscribe
http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev

Reply via email to