title: Nameko for Microservices
url: http://lucumr.pocoo.org/2015/4/8/microservices-with-nameko/
hash_url: ab01c9532d507c86951542839a45c026

<p>In December some of the tech guys at <a class="reference external" href="http://www.onefinestay.com/">onefinestay</a> invited me over to London to do some
general improvements on their their <a class="reference external" href="http://nameko.readthedocs.org/en/latest/">nameko</a> library.  This collaboration
came together because nameko was pretty similar to how I generally like to
build certain infrastructure and I had some experience with very similar
systems.</p>
<p>So now that some of those improvements hit the release version of nameko I
figured it might be a good idea to give some feedback on why I like this
sort of architecture.</p>

<h2>Freeing your Mind</h2>
<p>Right now if you want to build a web service in Python there are many
tools you can pick from, but most of them live in a very specific part of
your stack.  The most common tool is a web framework and that will
typically provide you with whatever glue is necessary to connect your own
code to an incoming HTTP request that comes from your client.</p>
<p>However that's not all you need in an application.  For instance very
often you have periodic tasks that you need to execute and in that case,
your framework is often not just not helping, it's also in your way.  For
instance because you might have built your code with the assumption that
it has access to the HTTP request object.  If you now want to run it from
a cronjob that request object is unavailable.</p>
<p>In addition to crons there is often also the wish to execute something as
the result of the request of a client, but without blocking that request.
For instance imagine there is an admin panel in which you can trigger some
very expensive data conversion task.  What you actually want is for the
current request to finish but the conversion task to keep on working in
the background until your data set is converted.</p>
<p>There are obviously many existing solutions for that.  Celery comes to
mind.  However they are typically very separated from the rest of the
stack.</p>
<p>Having a system which treats all of this processes the same frees up your
mind.  This is what makes microservices interesting.  Away with having
HTTP request handlers that have no direct relationship with message queue
worker tasks or cronjobs.  Instead you can have a coherent system where
any component can talk through well defined points with other parts of the
system.</p>
<p>This is especially useful in Python where traditionally our support for
parallel execution has been between very bad to abysmal.</p>

<h2>Enter Nameko</h2>
<p>Nameko is an implementation of this idea.  It's very similar in
architecture to how we structure code at Fireteam.  It's based on
distributing work between processes through AMQP.  It's not just AMQP
though.  Nameko abstracts away from that and allows you to write your own
transports, while staying true to the AMQP patterns.</p>
<p>Nameko does a handful of things and you can build very complex systems
with it.  The idea is that you build individual services which can emit
events to which other services can subscribe to or they can directly
invoke each other via RPC.  All communication between the services happens
through AMQP.  You don't need to manually deal with any connectivity of
those.</p>
<p>In addition to message exchange, services also use a lifecycle management
to find useful resources through dependency injection.  That sounds like a
mouthful but is actually very simple.  Because services are classes, you
can add special attributes to them which will be resolved at runtime.  The
lifetime of the value resolved can be customized.  For instance it becomes
possible to attach a property to the class which can provide access to a
database connection.  The lifetime of that database connection can be
automatically managed.</p>
<p>So how does that look in practice?  Something like this:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">nameko.rpc</span> <span class="kn">import</span> <span class="n">rpc</span>

<span class="k">class</span> <span class="nc">HelloWorldService</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;helloworld&#39;</span>

    <span class="nd">@rpc</span>
    <span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;Hello, {}!&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</pre></div>
<p>This defines a basic service that provides one method that can be invoked
via RPC.  Either another service can do that, or any other process that
runs nameko can also invoke that, for as long as they connect to the same
AMQP server.  To experiment with this service, Nameko provides a shell
helper that launches an interactive Python shell with an <tt class="docutils literal">n</tt> object that
provides RPC access:</p>
<div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">n</span><span class="o">.</span><span class="n">rpc</span><span class="o">.</span><span class="n">helloworld</span><span class="o">.</span><span class="n">hello</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;John&#39;</span><span class="p">)</span>
<span class="go">u&#39;Hello, John!&#39;</span>
</pre></div>
<p>If the AMQP server is running, <tt class="docutils literal">rpc.helloworld.hello</tt> contacts the
<tt class="docutils literal">helloworld</tt> service and resolves the <tt class="docutils literal">hello</tt> method on it.  Upon
calling this method a message will be dispatched via the AMQP broker and
be picked up by a nameko process.  The shell will then block and wait for
the result to come back.</p>
<p>A more useful example is what happens when services want to collaborate on
some activity.  For instance it's quite common that one service wants to
respond to the changes another service performs to update it's own state.
This can be achieved through events:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">nameko.events</span> <span class="kn">import</span> <span class="n">EventDispatcher</span><span class="p">,</span> <span class="n">event_handler</span>
<span class="kn">from</span> <span class="nn">nameko.rpc</span> <span class="kn">import</span> <span class="n">rpc</span>

<span class="k">class</span> <span class="nc">ServiceA</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;servicea&#39;</span>
    <span class="n">dispatch</span> <span class="o">=</span> <span class="n">EventDispatcher</span><span class="p">()</span>

    <span class="nd">@rpc</span>
    <span class="k">def</span> <span class="nf">emit_an_event</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">dispatch</span><span class="p">(</span><span class="s">&#39;my_event_type&#39;</span><span class="p">,</span> <span class="s">&#39;payload&#39;</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">ServiceB</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;serviceb&#39;</span>

    <span class="nd">@event_handler</span><span class="p">(</span><span class="s">&#39;servicea&#39;</span><span class="p">,</span> <span class="s">&#39;my_event_type&#39;</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">handle_an_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">payload</span><span class="p">):</span>
        <span class="k">print</span> <span class="s">&#39;service b received&#39;</span><span class="p">,</span> <span class="n">payload</span>
</pre></div>
<p>The default behavior is that one service instance of each service type
will pick up the event.  However nameko can also route an event to every
single instance of every single service.  This is useful for in-process
cache invalidation for instance.</p>

<h2>The Web</h2>
<p>Nameko is not just good for internal communication however.  It uses
Werkzeug to provide a bridge to the outside world.  This allows you to
accept an HTTP request and to ingest a task into your service world:</p>
<div class="highlight"><pre><span class="kn">import</span> <span class="nn">json</span>
<span class="kn">from</span> <span class="nn">nameko.web.handlers</span> <span class="kn">import</span> <span class="n">http</span>
<span class="kn">from</span> <span class="nn">werkzeug.wrappers</span> <span class="kn">import</span> <span class="n">Response</span>

<span class="k">class</span> <span class="nc">HttpServiceService</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;helloworld&#39;</span>

    <span class="nd">@http</span><span class="p">(</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="s">&#39;/get/&lt;int:value&gt;&#39;</span><span class="p">)</span>
    <span class="k">def</span> <span class="nf">get_method</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Response</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">({</span><span class="s">&#39;value&#39;</span><span class="p">:</span> <span class="n">value</span><span class="p">}),</span>
                        <span class="n">mimetype</span><span class="o">=</span><span class="s">&#39;application/json&#39;</span><span class="p">)</span>
</pre></div>
<p>The endpoint function can itself invoke other parts of the system via RPC
or other methods.</p>
<p>This functionality generally also extends into the websocket world, even
though that part is currently quite experimental.  It for instance is
possible to listen to events and forward them into websocket connections.</p>

<h2>Dependency Injection</h2>
<p>One of the really neat design concepts in Nameko is the use of dependency
injection to find resources.  A good example is the SQLAlchemy bridge
which attaches a SQLAlchemy database session to a service through
dependency injection.  The descriptor itself will hook into the lifecycle
management to automatically manage the database resources:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">nameko_sqlalchemy</span> <span class="kn">import</span> <span class="n">Session</span>

<span class="kn">import</span> <span class="nn">sqlalchemy</span> <span class="kn">as</span> <span class="nn">sa</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.ext.declarative</span> <span class="kn">import</span> <span class="n">declarative_base</span>

<span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">()</span>

<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
    <span class="n">__tablename__</span> <span class="o">=</span> <span class="s">&#39;users&#39;</span>
    <span class="nb">id</span> <span class="o">=</span> <span class="n">sa</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">sa</span><span class="o">.</span><span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    <span class="n">username</span> <span class="o">=</span> <span class="n">sa</span><span class="o">.</span><span class="n">Column</span><span class="p">(</span><span class="n">sa</span><span class="o">.</span><span class="n">String</span><span class="p">)</span>


<span class="k">class</span> <span class="nc">MyService</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;myservice&#39;</span>
    <span class="n">session</span> <span class="o">=</span> <span class="n">Session</span><span class="p">(</span><span class="n">Base</span><span class="p">)</span>

    <span class="nd">@rpc</span>
    <span class="k">def</span> <span class="nf">get_username</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">user_id</span><span class="p">):</span>
        <span class="n">user</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">User</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">user_id</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">user</span><span class="o">.</span><span class="n">username</span>
</pre></div>
<p>The implementation of the <tt class="docutils literal">Session</tt> dependency provider itself is
ridiculously simple.  The whole functionality could be implemented like
this:</p>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">weakref</span> <span class="kn">import</span> <span class="n">WeakKeyDictionary</span>

<span class="kn">from</span> <span class="nn">nameko.extensions</span> <span class="kn">import</span> <span class="n">DependencyProvider</span>
<span class="kn">from</span> <span class="nn">sqlalchemy</span> <span class="kn">import</span> <span class="n">create_engine</span>
<span class="kn">from</span> <span class="nn">sqlalchemy.orm</span> <span class="kn">import</span> <span class="n">sessionmaker</span>


<span class="k">class</span> <span class="nc">Session</span><span class="p">(</span><span class="n">DependencyProvider</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">declarative_base</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">declarative_base</span> <span class="o">=</span> <span class="n">declarative_base</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sessions</span> <span class="o">=</span> <span class="n">WeakKeyDictionary</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">get_dependency</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">worker_ctx</span><span class="p">):</span>
        <span class="n">db_uri</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">container</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s">&#39;DATABASE_URL&#39;</span><span class="p">]</span>
        <span class="n">engine</span> <span class="o">=</span> <span class="n">create_engine</span><span class="p">(</span><span class="n">db_uri</span><span class="p">)</span>
        <span class="n">session_cls</span> <span class="o">=</span> <span class="n">sessionmaker</span><span class="p">(</span><span class="n">bind</span><span class="o">=</span><span class="n">engine</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">sessions</span><span class="p">[</span><span class="n">worker_ctx</span><span class="p">]</span> <span class="o">=</span> <span class="n">session</span> <span class="o">=</span> <span class="n">session_cls</span><span class="p">()</span>
        <span class="k">return</span> <span class="n">session</span>

    <span class="k">def</span> <span class="nf">worker_teardown</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">worker_ctx</span><span class="p">):</span>
        <span class="n">sess</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sessions</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">worker_ctx</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">sess</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">sess</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
<p>The actual implementation is only a tiny bit more complicated, and that is
basically just a bit of extra code to support different database URLs for
different services and declarative bases.  Overall the concept is the same
however.  When the dependency is needed, a connection to the database is
established and when the worker shuts down, the session is closed.</p>

<h2>Concurrency and Parallelism</h2>
<p>What makes nameko interesting is that scales out really well through the
use of AMQP and eventlet.  First of all, when nameko starts a service
container it uses eventlet to patch up the Python interpreter to support
green concurrency.  This allows a service container to become quite
concurrent to do multiple things at once.  This is very useful when a
service waits on another service as threads in Python are a very
disappointing story.  As this however largely eliminates the possibility
of true parallelism it becomes necessary to start multiple instances of
services to scale up.  Thanks to the use of AMQP however, this becomes a
very transparent process.  For as long as services do not need to store
local state, it becomes very trivial to run as many of those service
containers as necessary.</p>

<h2>My Take On It</h2>
<p>Nameko as it stands has all the right principles for building a platform
out of small services and it's probably the best Open Source solution for
this problem in the Python world so far.</p>
<p>It's a bit disappointing that Python's async story is so diverging between
different Python versions and frameworks, but eventlet and gevent are by
far the cleanest and most practical implementations, so for most intents
and purposes the eventlet base in nameko is probably the best you can
currently get for async IO.  Fear not though, Nameko 2.0 now also runs on
Python3.</p>
<p>If you haven't tried this sort of service setup yet, you might want to
give Nameko a try.</p>
