• Stars
    star
    191
  • Rank 202,877 (Top 4 %)
  • Language
    Python
  • Created over 8 years ago
  • Updated about 8 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Code for example in this post: http://brunorocha.org/python/microservices-with-python-rabbitmq-and-nameko.html

TL;DR: start coding here

"Micro-services is the new black" - Splitting the project in to independently scalable services is the currently the best option to ensure the evolution of the code. In Python there is a Framework called "Nameko" which makes it very easy and powerful.

Micro services

The term "Microservice Architecture" has sprung up over the last few years to describe a particular way of designing software applications as suites of independently deployable services. - M. Fowler

I recommend reading the Fowler's posts to understand the theory behind it.

Ok I so what does it mean?

In brief a Micro Service Architecture exists when your system is divided in small (single context bound) responsibilities blocks, those blocks doesn't know each other, they only have a common point of communication, generally a message queue, and does know the communication protocol and interfaces.

Give me a real-life example

The code is available on github: http://github.com/rochacbruno/nameko-example take a look at service and api folders for more info.

Consider you have an REST API, that API has an endpoint receiving some data and you need to perform some kind of computation with that data, instead of blocking the caller you can do it asynchronously, return an status "OK - Your request will be processed" to the caller and do it in a background task.

Also you want to send an email notification when the computation is finished without blocking the main computing process, so it is better to delegate the "email sending" to another service.

Scenario

enter image description here

Show me the code!

Lets create the system to understand it in practice.

Environment

We need an environment with:

  • A running RabbitMQ
  • Python VirtualEnv for services
  • Python VirtualEnv for API

Rabbit

The easiest way to have a RabbitMQ in development environment is running its official docker container, considering you have Docker installed run:

docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management

Go to the browser and access http://localhost:15672 using credentials guest:guest if you can login to RabbitMQ dashboard it means you have it running locally for development.

enter image description here

The Service environment

Now lets create the Micro Services to consume our tasks. We'll have a service for computing and another for mail, follow the steps.

In a shell create the root project directory

$ mkdir myproject
$ cd myproject

Create and activate a virtualenv (you can also use virtualenv-wrapper)

$ virtualenv service_env
$ source service_env/bin/activate

Install nameko framework and yagmail

(service_env)$ pip install nameko
(service_env)$ pip install yagmail

The service code

Now having that virtualenv prepared (consider you can run service in a server and API in another) lets code the nameko RPC Services.

We are going to put both services in a single python module, but you can also split in separate modules and also run them in separate servers if needed.

In a file called service.py

import yagmail
from nameko.rpc import rpc, RpcProxy


class Mail(object):
    name = "mail"

    @rpc
    def send(self, to, subject, contents):
        yag = yagmail.SMTP('[email protected]', 'mypassword')
        # read the above credentials from a safe place.
        # Tip: take a look at Dynaconf setting module
        yag.send(to=to.encode('utf-8'),
                 subject=subject.encode('utf-8'),
                 contents=[contents.encode('utf-8')])


class Compute(object):
    name = "compute"
    mail = RpcProxy('mail')

    @rpc
    def compute(self, operation, value, other, email):
        operations = {'sum': lambda x, y: int(x) + int(y),
                      'mul': lambda x, y: int(x) * int(y),
                      'div': lambda x, y: int(x) / int(y),
                      'sub': lambda x, y: int(x) - int(y)}
        try:
            result = operations[operation](value, other)
        except Exception as e:
            self.mail.send.async(email, "An error occurred", str(e))
            raise
        else:
            self.mail.send.async(
                email,
                "Your operation is complete!",
                "The result is: %s" % result
            )
            return result

Now with the above services definition we need to run it as a Nameko RPC service.

NOTE: We are going to run it in a console and leave it running, but in production it is recommended to put the service to run using supervisord or an alternative.

Run the service and let it running in a shell

(service_env)$ nameko run service --broker amqp://guest:guest@localhost
starting services: mail, compute
Connected to amqp://guest:**@127.0.0.1:5672//
Connected to amqp://guest:**@127.0.0.1:5672//

Testing it

Go to another shell (with the same virtenv) and test it using nameko shell

(service_env)$ nameko shell --broker amqp://guest:guest@localhost
Nameko Python 2.7.9 (default, Apr  2 2015, 15:33:21)
[GCC 4.9.2] shell on linux2
Broker: amqp://guest:guest@localhost
>>>

You are now in the RPC client testing shell exposing the n.rpc object, play with it

>>> n.rpc.mail.send("[email protected]", "testing", "Just testing")

The above should sent an email and we can also call compute service to test it, note that it also spawns an async mail sending with result.

>>> n.rpc.compute.compute('sum', 30, 10, "[email protected]")
40
>>> n.rpc.compute.compute('sub', 30, 10, "[email protected]")
20
>>> n.rpc.compute.compute('mul', 30, 10, "[email protected]")
300
>>> n.rpc.compute.compute('div', 30, 10, "[email protected]")
3

Calling the micro-service through the API

In a different shell (or even a different server) prepare the API environment

Create and activate a virtualenv (you can also use virtualenv-wrapper)

$ virtualenv api_env
$ source api_env/bin/activate

Install Nameko, Flask and Flasgger

(api_env)$ pip install nameko
(api_env)$ pip install flask
(api_env)$ pip install flasgger

NOTE: In api you dont need the yagmail because it is service responsability

Lets say you have the following code in a file api.py

from flask import Flask, request
from flasgger import Swagger
from nameko.standalone.rpc import ClusterRpcProxy

app = Flask(__name__)
Swagger(app)
CONFIG = {'AMQP_URI': "amqp://guest:guest@localhost"}


@app.route('/compute', methods=['POST'])
def compute():
    """
    Micro Service Based Compute and Mail API
    This API is made with Flask, Flasgger and Nameko
    ---
    parameters:
      - name: body
        in: body
        required: true
        schema:
          id: data
          properties:
            operation:
              type: string
              enum:
                - sum
                - mul
                - sub
                - div
            email:
              type: string
            value:
              type: integer
            other:
              type: integer
    responses:
      200:
        description: Please wait the calculation, you'll receive an email with results
    """
    operation = request.json.get('operation')
    value = request.json.get('value')
    other = request.json.get('other')
    email = request.json.get('email')
    msg = "Please wait the calculation, you'll receive an email with results"
    subject = "API Notification"
    with ClusterRpcProxy(CONFIG) as rpc:
        # asynchronously spawning and email notification
        rpc.mail.send.async(email, subject, msg)
        # asynchronously spawning the compute task
        result = rpc.compute.compute.async(operation, value, other, email)
        return msg, 200

app.run(debug=True)

Put the above API to run in a different shell or server

(api_env) $ python api.py
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

and then access the url http://localhost:5000/apidocs/index.html you will see the Flasgger UI and you can interact with the api and start producing tasks on queue to the service to consume.

[image]

NOTE: You can see the shell where service is running for logging, prints and error messages. You can also access the RabbitMQ dashboard to see if there is some message in process there.

There is a lot of more advanced things you can do with Nameko framework you can find more information on https://nameko.readthedocs.org/en/stable/

Let's Micro Serve!

More Repositories

1

py2rs

A quick reference guide for the Pythonista in the process of becoming a Rustacean
CSS
2,022
star
2

python-week-2022

Template Para a Python Week 2002 - 25 a 29 de Abril na LINUXTips
Python
1,848
star
3

rust-python-example

Example of using Rust to Extend Python
Python
776
star
4

python-project-template

DO NOT FORK, CLICK ON "Use this template" - A github template to start a Python Project - this uses github actions to generate your project based on the template.
Makefile
753
star
5

fastapi-project-template

DO NOT FORK, CLICK "Use this template" - The base to start an openapi project featuring: SQLModel, Typer, FastAPI, JWT Token Auth, Interactive Shell, Management Commands.
Python
290
star
6

flask-powered

List of companies using Flask framework - who is using Flask?
134
star
7

python-base

https://www.linuxtips.io/products/python-base
Python
129
star
8

flask-project-template

DO NOT FORK, CLICK "Use this template" - A github template to start a Flask Project - this uses github actions to generate your project based on the template.
Python
121
star
9

rust_memes

The best memes and stickers about #rust #rustlang - listed here for easy use on talks and share
Rust
106
star
10

learndynaconf

Learn Dynaconf - the best config library for Python :)
Python
61
star
11

talkshow

A Call 4 Papers System - A simple base app as example of Flask Architecture
Python
59
star
12

wtf

What The Flask - News App da parte 1 do artigo What the Flask
Python
50
star
13

vegan_recipes

100% vegan recipes
48
star
14

dotfiles

My Environment Configurations
Lua
42
star
15

fastapi-workshop

Material do workshop - Criando API com FastAPI da LINUXtips
Python
36
star
16

python-hello-world

Hello World
28
star
17

rochacbruno

My Profile
20
star
18

i_am_learning_rust

My Rust exercices with notes (mostly based on Rust Essentials and TRPL books + exercism)
Rust
20
star
19

dundie-api

Projeto do Treinamento Python Web API LINUXtips
Shell
18
star
20

dundie-rewards

point rewards system for dunder mifflin company
Python
17
star
21

makectl

WIP - Generate and Manage targets in your makefiles.
Rust
16
star
22

python-web-api

https://cursodepython.com.br
15
star
23

DURC

Declarative Understandable Reproducible Cases - Powered by Ansible
Python
11
star
24

aprenda-rust

https://bit.ly/aprendarust
Rust
10
star
25

thunar-actions

My actions used in Thunar (XFCE file manager)
Shell
9
star
26

dynaconf_ng

You know... when a repo is created having `_ng` suffix it means the main project will evolve or is going to die...
Python
6
star
27

Postgre

A Database System Inspired by Postgres
6
star
28

rust-dynaconf

GO TO https://github.com/rubik/hydroconf
Rust
5
star
29

discord_classroom

Discord bot to work as a Learning Management System - LMS
Rust
5
star
30

python-base-1

Codigos do Treinamento Python Expert Modulo Base
Python
4
star
31

bruno-api-done

Python
4
star
32

exercism

My exercism solutions, don't COPY it!!! :) try yourself at -> https://exercism.io/
Rust
3
star
33

fastapi-workshop-template

⬅️ Click on Use This Template - Template para o workshop de FastAPI da Codecon 2021
Python
3
star
34

rust-intro

Rust Intro Repository for Data Umbrella Workshop - This repository is almost empty, only some instructions on the readme.
3
star
35

web-api-example

Python
2
star
36

micro-rust-plugin

Micro Editor rust plugin
Lua
2
star
37

trivia

Python TUI for Open Trivia Database
Python
2
star
38

smarter

Some objects could be smarter
Python
2
star
39

make-me-a-blog

One click blog
2
star
40

ansible-test

ansible.test.case is a testing framework and test runner within ansible tasks, it talks to API using openapispec, to Selenium using pageObjects and CLI using pexpect.
HTML
2
star
41

flask_admin_example

FlaskConf 2018 talk code
Python
1
star
42

dataclass-validator

Python
1
star
43

wagd

Workspace for Ansible Galaxy Development
1
star
44

conffee-maker

`$cm` or Confee Maker is a command terminal interface TUI to generate configuration files for different applications based on templates.
Rust
1
star