[openstack-dev] [oslo] Asyncio and oslo.messaging
Angus Salkeld
angus.salkeld at RACKSPACE.COM
Mon Jul 7 18:11:16 UTC 2014
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 03/07/14 05:30, Mark McLoughlin wrote:
> Hey
>
> This is an attempt to summarize a really useful discussion that Victor,
> Flavio and I have been having today. At the bottom are some background
> links - basically what I have open in my browser right now thinking
> through all of this.
>
> We're attempting to take baby-steps towards moving completely from
> eventlet to asyncio/trollius. The thinking is for Ceilometer to be the
> first victim.
Has this been widely agreed on? It seems to me like we are mixing two
issues:
1) we need to move to py3
2) some people want to move from eventlet (I am not convinced that the
volume of code changes warrants the end goal - and review load)
To achieve "1)" in a lower risk change, shouldn't we rather run eventlet
on top of asyncio? - i.e. not require widespread code changes.
So we can maintain the main loop API but move to py3. I am not sure on
the feasibility, but seems to me like a more contained change.
- -Angus
>
> Ceilometer's code is run in response to various I/O events like REST API
> requests, RPC calls, notifications received, etc. We eventually want the
> asyncio event loop to be what schedules Ceilometer's code in response to
> these events. Right now, it is eventlet doing that.
>
> Now, because we're using eventlet, the code that is run in response to
> these events looks like synchronous code that makes a bunch of
> synchronous calls. For example, the code might do some_sync_op() and
> that will cause a context switch to a different greenthread (within the
> same native thread) where we might handle another I/O event (like a REST
> API request) while we're waiting for some_sync_op() to return:
>
> def foo(self):
> result = some_sync_op() # this may yield to another greenlet
> return do_stuff(result)
>
> Eventlet's infamous monkey patching is what make this magic happen.
>
> When we switch to asyncio's event loop, all of this code needs to be
> ported to asyncio's explicitly asynchronous approach. We might do:
>
> @asyncio.coroutine
> def foo(self):
> result = yield from some_async_op(...)
> return do_stuff(result)
>
> or:
>
> @asyncio.coroutine
> def foo(self):
> fut = Future()
> some_async_op(callback=fut.set_result)
> ...
> result = yield from fut
> return do_stuff(result)
>
> Porting from eventlet's implicit async approach to asyncio's explicit
> async API will be seriously time consuming and we need to be able to do
> it piece-by-piece.
>
> The question then becomes what do we need to do in order to port a
> single oslo.messaging RPC endpoint method in Ceilometer to asyncio's
> explicit async approach?
>
> The plan is:
>
> - we stick with eventlet; everything gets monkey patched as normal
>
> - we register the greenio event loop with asyncio - this means that
> e.g. when you schedule an asyncio coroutine, greenio runs it in a
> greenlet using eventlet's event loop
>
> - oslo.messaging will need a new variant of eventlet executor which
> knows how to dispatch an asyncio coroutine. For example:
>
> while True:
> incoming = self.listener.poll()
> method = dispatcher.get_endpoint_method(incoming)
> if asyncio.iscoroutinefunc(method):
> result = method()
> self._greenpool.spawn_n(incoming.reply, result)
> else:
> self._greenpool.spawn_n(method)
>
> it's important that even with a coroutine endpoint method, we send
> the reply in a greenthread so that the dispatch greenthread doesn't
> get blocked if the incoming.reply() call causes a greenlet context
> switch
>
> - when all of ceilometer has been ported over to asyncio coroutines,
> we can stop monkey patching, stop using greenio and switch to the
> asyncio event loop
>
> - when we make this change, we'll want a completely native asyncio
> oslo.messaging executor. Unless the oslo.messaging drivers support
> asyncio themselves, that executor will probably need a separate
> native thread to poll for messages and send replies.
>
> If you're confused, that's normal. We had to take several breaks to get
> even this far because our brains kept getting fried.
>
> HTH,
> Mark.
>
> Victor's excellent docs on asyncio and trollius:
>
> https://docs.python.org/3/library/asyncio.html
> http://trollius.readthedocs.org/
>
> Victor's proposed asyncio executor:
>
> https://review.openstack.org/70948
>
> The case for adopting asyncio in OpenStack:
>
> https://wiki.openstack.org/wiki/Oslo/blueprints/asyncio
>
> A previous email I wrote about an asyncio executor:
>
> http://lists.openstack.org/pipermail/openstack-dev/2013-June/009934.html
>
> The mock-up of an asyncio executor I wrote:
>
> https://github.com/markmc/oslo-incubator/blob/8509b8b/openstack/common/messaging/_executors/impl_tulip.py
>
> My blog post on async I/O and Python:
>
> http://blogs.gnome.org/markmc/2013/06/04/async-io-and-python/
>
> greenio - greelets support for asyncio:
>
> https://github.com/1st1/greenio/
>
>
> _______________________________________________
> OpenStack-dev mailing list
> OpenStack-dev at lists.openstack.org
> http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iQEcBAEBAgAGBQJTuuLsAAoJEFrDYBLxZjWotFwH/1PYbrXFYb+gYNCWBAtGJ3mi
wHdHIonIjcD3Zpnvs3o5BJDbugSlfdKzHRjSy9dQG5LyuihiFNK3AFQu/ldfJEdS
/QiLIaCQYI/13AwWA9+8A/TYpoyVJytVaXm3uBp2fMhy02TYWOweh02gifUZ7CBp
3hRzGQE4EmHr0YpgQRupIDpE50GzflB8fySXyfm3Cme7vcCivyMOHexsxKe3Bm2o
LxfMRPvUOqZ9MaJ6XFTy8SieNA4kMdZYmrm4pu5nrALXwxZ1dAtpD4jcjLK7Jh5T
P+eZHcQTe7bYSlk+LMchfHpAlTuLTySHv/LB6wvt2ljSM4AAmABKOKwAjFFL66k=
=O09e
-----END PGP SIGNATURE-----
More information about the OpenStack-dev
mailing list