blob: 8e6c0fd334048e5c55241380eef3e05af6999dbc [file] [log] [blame]
Using Libcloud in multi-threaded and async environments
=======================================================
Libcloud's primary task is to communicate with different provider APIs using
HTTP. This means most of the work is not CPU intensive, but performing all
those HTTP requests includes a lot of waiting which makes the library I/O
bound.
Most of the time you want to perform more operations in parallel or just
want your code to finish faster (for example starting a lot of servers or
periodically polling for node status).
Problems like this are usually solved using threads or async libraries such
as Twisted, Tornado or gevent.
This page contains some information and tips about how to use Libcloud in
such environments.
Libcloud and thread-safety
--------------------------
Important thing to keep in mind when dealing with threads is thread-safety.
Libcloud driver instance is **not** thread safe. This means if you don't want
to deal with complex (and usually inefficient) locking the easiest solution
is to create a new driver instance inside each thread.
Using Libcloud with gevent
--------------------------
gevent has an ability to monkey patch and replace functions in the Python
``socket``, ``urllib2``, ``httplib`` and ``time`` module with its own
functions which don't block.
You need to do two things when you want to use Libcloud with gevent:
* Enable monkey patching
.. sourcecode:: python
from gevent import monkey
monkey.patch_all()
* Create a separate driver instance for each Greenlet. This is necessary
because a driver instance reuses the same Connection class.
For an example see :doc:`Efficiently download multiple files using gevent </storage/examples>`.
Using Libcloud with Twisted
---------------------------
Libcloud has no Twisted support included in the core which means you need
to be careful when you use it with Twisted and some other async frameworks.
If you don't use it properly it can block the whole reactor (similar as
any other blocking library or a long CPU-intensive task) which means the
execution of other pending tasks in the event queue will be blocked.
A simple solution to prevent blocking the reactor is to run Libcloud
calls inside a thread. In Twisted this can be achieved using
``threads.deferToThread`` which runs a provided method inside the Twisted
thread pool.
The example below demonstrates how to create a new node inside a thread
without blocking the whole reactor.
.. literalinclude:: /examples/misc/twisted_create_node.py
:language: python