You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2013/08/03 18:00:41 UTC
[5/7] git commit: Port "Using Libcloud in multi-threaded and async
environments" documentation section.
Port "Using Libcloud in multi-threaded and async environments" documentation
section.
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/b6be3e70
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b6be3e70
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b6be3e70
Branch: refs/heads/trunk
Commit: b6be3e70e1fe31281f537c74c9b435e52264e20c
Parents: 318ed78
Author: Tomaz Muraus <to...@apache.org>
Authored: Sat Aug 3 17:52:50 2013 +0200
Committer: Tomaz Muraus <to...@apache.org>
Committed: Sat Aug 3 17:52:50 2013 +0200
----------------------------------------------------------------------
docs/examples/misc/twisted_create_node.py | 34 ++++++++++
docs/index.rst | 3 +-
...-in-multithreaded-and-async-environments.rst | 69 ++++++++++++++++++++
3 files changed, 105 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b6be3e70/docs/examples/misc/twisted_create_node.py
----------------------------------------------------------------------
diff --git a/docs/examples/misc/twisted_create_node.py b/docs/examples/misc/twisted_create_node.py
new file mode 100644
index 0000000..e0109e1
--- /dev/null
+++ b/docs/examples/misc/twisted_create_node.py
@@ -0,0 +1,34 @@
+from __future__ import absolute_import
+
+from pprint import pprint
+
+from twisted.internet import defer, threads, reactor
+from libcloud.compute.types import Provider
+from libcloud.compute.providers import get_driver
+
+
+@defer.inlineCallbacks
+def create_node(name):
+ node = yield threads.deferToThread(_thread_create_node,
+ name=name)
+ pprint(node)
+ reactor.stop()
+
+
+def _thread_create_node(name):
+ Driver = get_driver(Provider.RACKSPACE)
+ conn = Driver('username', 'api key')
+ image = conn.list_images()[0]
+ size = conn.list_sizes()[0]
+ node = conn.create_node(name=name, image=image, size=size)
+ return node
+
+
+def stop(*args, **kwargs):
+ reactor.stop()
+
+d = create_node(name='my-lc-node')
+d.addCallback(stop)
+d.addErrback(stop)
+
+reactor.run()
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b6be3e70/docs/index.rst
----------------------------------------------------------------------
diff --git a/docs/index.rst b/docs/index.rst
index 09cff04..be5f382 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -23,14 +23,15 @@ resources:
* :doc:`Load Balancers as a Service </loadbalancer/index>`
* :doc:`DNS as a Service </dns/index>`
-
.. toctree::
:glob:
+ :maxdepth: 2
:hidden:
compute/*
storage/*
loadbalancer/*
dns/*
+ other/*
.. _`Apache 2.0 license`: https://www.apache.org/licenses/LICENSE-2.0.html
http://git-wip-us.apache.org/repos/asf/libcloud/blob/b6be3e70/docs/other/using-libcloud-in-multithreaded-and-async-environments.rst
----------------------------------------------------------------------
diff --git a/docs/other/using-libcloud-in-multithreaded-and-async-environments.rst b/docs/other/using-libcloud-in-multithreaded-and-async-environments.rst
new file mode 100644
index 0000000..26e1edb
--- /dev/null
+++ b/docs/other/using-libcloud-in-multithreaded-and-async-environments.rst
@@ -0,0 +1,69 @@
+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 Efficiently download multiple files using gevent.
+
+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 bellow demonstrates how to create a new node inside a thread
+without blocking the whole reactor.
+
+.. literalinclude:: /examples/misc/twist_create_node.py
+ :language: python
+
+