技术控

    今日:67| 主题:49157
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] Microservices in Flask

[复制链接]
披着蚊帐当婚纱 发表于 2016-10-10 18:32:56
151 0

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
I recently gave a talk about microservices in Flask on Wrocpy . This blog post is a translation of that talk into English.
  Table of Contents:
      Monolithic application

   Microservices talk usually starts with a monolithic application. In my case, it is the same. I work on a project where I have a big monolithic application. If I wanted to take some part of it and make some microservice from for instance django app it would be impossible. There are too many internal imports from every part of application:
   [code]from app.users.models import UserSiteProfile
from app.utils.cache import cache_key_user
from app.sites.models import SiteProfile
from app.sites.utils import site_terms
from app.utils.users import get_homepage_url
from app.utils.views import ThemedFormView, ThemedTemplateView
from app.authentication import signals
from app.authentication.forms import AuthForm, EmailForm
from app.authentication.idp import (
    is_valid_idp, MultipleIDPError, saml_available,
    site_idp, user_idp_lookup)
from app.authentication.loginchecks import (
    check_account_expiration, get_site_login_errors,
    pre_login_checks
)
from app.saml.utils import site_specific_config_loader
from app.saml.views import _get_subject_id[/code]   Snippet from above presents exemplary imports of random python module in my project.
    So where are these microservices? In my team, we decided to have new parts of the application made as a microservices. So right now from the architectural point of view I have a big monolithic application and small microservices that are around this big thing, like in this picture:
   
Microservices in Flask-1 (recently,English,usually,import,wanted)
    Picture from link .
        We choose the flask as a tool that will be used in our microservices. It doesn't set any boundaries and it's flexible but don't have batteries included . Let's start with the first flask extension that helps us building microservices:
        Django has a set of powerful commands available. To enable such a feature in flask you needFlask-Script. It allows you to create commands such as runserver or shell . In listing below I created a runserver command:
    [code]from flask.ext.script import Manager, Shell, Server
from my_app.application import app

manager = Manager(app)
manager.add_command(
    'runserver',
    Server(host='0.0.0.0', port=7000, use_debugger=True)
)[/code]           To communicate between microservices I use REST. To ease yourself when creating resources and endpoints you can useFlask-RESTful. It is superuseful when you need to create REST API. It is easy- you specify endpoint with resource and rest is done by Flask-RESTful. It also has request parsing and it is very easy to create other representations like xml. The snippet below shows it:
    [code]from flask_restful import Resource

class MyResource(Resource):
    def get():
        return {'OK'}
@api.representation('application/xml')
def output_xml(data, code, headers=None):
    response = make_response(dicttoxml.dicttoxml(data), code)
    inject_headers(response, headers)
    return response[/code]          Marshallow & flask-marshallow

     To serialize or deserialize objects you can use flask-marshallow . In code below, I created a simple Schema with id, name and url. Then when the user enters /api/custom/1 I can easily serialize objects from a database and return JSON.
    [code]ma = Marshmallow(app)

class CustomSchema(ma.Schema):
    id = ma.Int(dump_only=True)
    name = ma.Str(required=True)
    url = ma.Url(relative=True)


    @app.route('/api/custom/')
    def users():
        all_obj = Object.all()
        result = object_schema.dump(all_obj)
        return jsonify(result.data)[/code]           Most of the modern frameworks have support for ORM- the same is with Flask. There is an extension called Flask-SQLAchemy that adds support for SQLAlchemy . Take this snippet for instance:
    [code]from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)

class MyModel(db.Model):
    GROUP = 'group'
    USER = 'user'
    TYPES = [
        (GROUP, GROUP),
        (USER, USER),
    ]

    __tablename__ = 'my_model'
    id = db.Column(db.Integer, primary_key=True)
    model_type = db.Column(ChoiceType(TYPES))
    model_value_id = db.Column(db.Integer, db.ForeignKey('model_value.id'))
    value = db.Column(db.String(1024))

    def __init__(self, model_type, model_value_id, value):
        self.share_type = share_type
        self.rule_value_id = rule_value_id
        self.value = value[/code]     I created MyModel class that will be translated to the table in a database. I also add columns to that table like model_type , model_value_id or value .
    Flask SQLAlchemy is layer sitting on top of SQLAlchemy so you can use all advantages of ORM like having queries written in python.
           When your database keeps getting larger there is a need for database migrations to make sure that everyone has the same database structure. To accomplish that we useFlask-Migrate. It is using Alembic under the hood so you have to make sure that adjust your migration files after generation. Example migration file can look as follows:
    [code]def upgrade():
    op.create_table(
        'my_model',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column(
            'model_type',
            sqlalchemy_utils.types.choice.ChoiceType(TYPES),
            nullable=True
        ),
        sa.PrimaryKeyConstraint('id'),
        sa.Column('value', sa.String(length=1024), nullable=True),
    )
    op.create_table(
        'my_model_values',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('model_value_id', sa.Integer(), nullable=True),
        sa.Column('value', sa.String(length=1024), nullable=True),
        sa.ForeignKeyConstraint(['model_value_id'], ['my_model.id']),
        sa.PrimaryKeyConstraint('id')
    )[/code]     In snipped above I created two tables: my_model and my_model_values with respective columns. Also my_model_values has ForeignKey relation to my_model by their ids.
       During the development of microservices, we write unit tests as well as integration ones. Testing how well microservices behave with each other can be tricky: we mock whole external services. Because of that, we need to keep them up to date with real microservices. Nature of this system causes some difficulties while an error occurs: I got an error from external microservice in most cases with a form of HTTP status code and a small message in JSON or XML. Then I need to debug not only my microservice but also external one.
     After testing is done we deploy microservice using few tools:
    We use puppet for managing and provisioning our microservices. Especially we use an R10k module for puppet: gtihub link .
        To make sure that every microservice has the same structure we also use cookiecutter . Thanks to that puppet knows that config file is always in this location or there will be logs stored there. Example microservice structure will look as follows:
    [code]└── flask_microservice
    ├── AUTHORS.rst
    ├── debian
    ├── docs
    │   ├── make.bat
    │   ├── Makefile
    │   └── source
    │       ├── authors.rst
    │       ├── conf.py
    │       ├── contributing.rst
    │       ├── history.rst
    │       ├── index.rst
    │       ├── readme.rst
    │       ├── technical_details.rst
    │       └── usage.rst
    |── HISTORY.rst
    ├── MANIFEST.in
    ├── README.rst
        ├── requirements.txt
        ├── setup.cfg
        ├── setup.py
        ├── src
        │   ├── flask_microservice
        │   │   ├── application.py
        │   │   ├── default_config.ini
        │   │   ├── __init__.py
        │   │   └── manage.py
        │   └── tests
        │       ├── conftest.py
        │       └── test_flask_microservice.py
        └── tox.ini[/code]       To distribute packages we usedh-virtualenv. This basically is taking python virtual enviroments and packing it to deb packages. So to have new code released we just run jenkins job to create new deb.
    That's all for today! The slides from this presentation can be found here: presentation . Do you also use flask to build microservices? Please give your comments about that.
   Special thanks to Kasia for being editor for this post. Thank you.
    Cover image by NASA JPL - Nasa JPL under CC0 Public Domain .
友荐云推荐




上一篇:Swift3实现多代理
下一篇:A Beginners Guide to JXA, JavaScript Application Scripting
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表