美文网首页微服务
基于sanic的微服务框架 - 架构分析

基于sanic的微服务框架 - 架构分析

作者: 非梦nj | 来源:发表于2019-01-19 10:29 被阅读157次

    感谢@songcser分享的《基于sanic的微服务基础架构》https://github.com/songcser/sanic-ms
    最近正在学习微服务,发现这个repo不错,但不完整,跑不起来。所以学习了一下源码,实际使用Docker部署成功,本文记录实现过程。
    学习用的git: https://github.com/kevinqqnj/sanic-ms

    0. sanicms总体框架

    image.png

    1. 微服务是什么

    微服务架构是一种将单应用程序作为一套小型服务开发的方法,每种应用程序都在其自己的进程中运行,并与轻量级机制(通常是HTTP资源的API)进行通信。这些服务是围绕业务功能构建的,可以通过全自动部署机制进行独立部署。这些服务的集中化管理已经是最少的,它们可以用不同的编程语言编写,并使用不同的数据存储技术。

    image.png
    http://baijiahao.baidu.com/s?id=1600354904549354089&wfr=spider&for=pc

    2. 使用的功能模块

    Project structure

    ├── develop # 开发脚本
    │ ├── cluster.sh
    │ ├── reset.sh # 初始化项目
    │ ├── test.sh
    │ ├── utils.sh
    │ ├── wait-for-it.sh
    │ └── wait-service.sh
    ├── region_service # 微服务之1
    │ ├── sanicms
    │ ├── info.log
    │ ├── migrations.py
    │ ├── models.py
    │ ├── server.py
    │ ├── settings.py
    │ └── views.py
    ├── role_service # 微服务之2
    │ ├── ...
    ├── user_service # 微服务之3
    │ ├── ...
    ├── sanicms # 微服务主框架
    │ ├── _init.py
    │ ├── client.py
    │ ├── config.py
    │ ├── db.py
    │ ├── doc.py
    │ ├── exception.py
    │ ├── loggers.py
    │ ├── logging.yml
    │ ├── _main
    .py
    │ ├── migrations.py
    │ ├── openapi.py
    │ ├── server.py
    │ ├── service.py
    │ ├── tests.py
    │ └── utils.py
    ├── docker-compose-cluster.yml
    ├── docker-compose-service-cluster.yml
    ├── docker-compose.yml # Docker微服务服务的配置文件,包括db/zipkin/swagger/consul
    ├── Dockerfile # Docker微服务的基本环境包
    ├── pylintrc
    ├── README.md
    └── requirements.txt # Python依赖模块

    3. Docker部署

    1. 安装Docker in Ubuntu (WSL): https://www.jianshu.com/p/97d16b68045f

    2. git repo到本地
      git clone https://github.com/kevinqqnj/sanic-ms.git
      cd sanic-ms

    3. 调用脚本来配置docker-compose,初始化数据库

    kevinqq@CN-00009841:/c/Users/xxx/git/sanic-ms$ ./develop/reset.sh
    >>> stop existing services
    Stopping sanic-ms_user_server_1     ... done
    >>> removing existing services
    Going to remove sanic-ms_user_server_1, sanic-ms_role_server_1, sanic-ms_region_server_1, sanic-ms_consul-server-2_1, sanic-ms_consul-server-1_1, sanic-ms_swagger_1, sanic-ms_consul-agent-1_1, sanic-ms_consul-agent-2_1, sanic-ms_zipkin_1, sanic-ms_db_1, sanic-ms_consul_1
    Removing sanic-ms_user_server_1     ... done
    >>> starting db/consul/zipkin
    Creating sanic-ms_zipkin_1 ... done
    Creating sanic-ms_consul_1 ... done
    Creating sanic-ms_db_1     ... done
    trying to >>> connect postgres 1
    /var/run/postgresql:5432 - no response
    trying to >>> connect postgres 2
    /var/run/postgresql:5432 - accepting connections
    >>> starting services
    sanic-ms_consul_1 is up-to-date
    sanic-ms_zipkin_1 is up-to-date
    sanic-ms_db_1 is up-to-date
    Creating sanic-ms_swagger_1         ... done
    Creating sanic-ms_region_server_1   ... done
    Creating sanic-ms_role_server_1     ... done
    Creating sanic-ms_user_server_1     ... done
    >>> create tables
    Starting sanic-ms_db_1 ... done
    Starting sanic-ms_zipkin_1 ... done
    Starting sanic-ms_region_server_1 ... done
    Starting sanic-ms_role_server_1   ... done
    Success Migration
    

    各服务端口:

    kevinqq@CN-00009841:/c/Users/xxx/git/sanic-ms$ docker-compose ps
               Name                         Command               State                                             Ports
    ----------------------------------------------------------------------------------------------------------------------------------------------------------------
    sanic-ms_consul-agent-1_1    docker-entrypoint.sh agent ...   Up      8300/tcp, 8301/tcp, 8301/udp, 8302/tcp, 8302/udp, 8500/tcp, 8600/tcp, 8600/udp
    sanic-ms_consul-agent-2_1    docker-entrypoint.sh agent ...   Up      8300/tcp, 8301/tcp, 8301/udp, 8302/tcp, 8302/udp, 8500/tcp, 8600/tcp, 8600/udp
    sanic-ms_consul-server-1_1   docker-entrypoint.sh agent ...   Up      8300/tcp, 8301/tcp, 8301/udp, 8302/tcp, 8302/udp, 8500/tcp, 8600/tcp, 8600/udp
    sanic-ms_consul-server-2_1   docker-entrypoint.sh agent ...   Up      8300/tcp, 8301/tcp, 8301/udp, 8302/tcp, 8302/udp, 8500/tcp, 8600/tcp, 8600/udp
    sanic-ms_consul_1            docker-entrypoint.sh agent ...   Up      8300/tcp, 8301/tcp, 8301/udp, 8302/tcp, 8302/udp, 0.0.0.0:8400->8400/tcp,
                                                                          0.0.0.0:8500->8500/tcp, 0.0.0.0:8600->8600/tcp, 0.0.0.0:8600->8600/udp
    sanic-ms_db_1                docker-entrypoint.sh postgres    Up      0.0.0.0:55432->5432/tcp
    sanic-ms_region_server_1     python -m server                 Up      0.0.0.0:8050->8050/tcp
    sanic-ms_role_server_1       python -m server                 Up      0.0.0.0:8020->8020/tcp
    sanic-ms_swagger_1           sh /usr/share/nginx/docker ...   Up      0.0.0.0:8090->8080/tcp
    sanic-ms_user_server_1       python -m server                 Up      0.0.0.0:8030->8030/tcp
    sanic-ms_zipkin_1            /bin/sh -c test -n "$STORA ...   Up      0.0.0.0:9410->9410/tcp, 0.0.0.0:9411->9411/tcp
    
    1. 检查各个服务是否已正常运行

    - consul服务发现

    已经发现consul自己的集群,还有基于sanic的3个服务


    image.png

    consul集群,可以看到5个nodes:在docker-compose文件里定义了consul-server-bootstrap x 1, server x 2, client x 2


    image.png

    - sanic服务

    目前演示了3个服务:user-service, role-service, region-service
    添加一些测试数据:

    kevinqq@CN-00009841:/c/Users/xxx/git/sanic-ms$ curl -X POST "http://localhost:8020/roles" -H  "accept: application/json" -H  "content-type: application/json" -d "{  \"name\": \"admin\"}"
    {"code":0,"data":{"id":1}}
    
    kevinqq@CN-00009841:/c/Users/xxx/git/sanic-ms$ curl -X POST "http://localhost:8030/users" -H  "accept: application/json" -H  "content-type: application/json" -d "{\"name\": \"Kevinqqnj\",\"age\":11,\"role_id\":1}"
    {"code":0,"data":{"id":1}}
    

    访问各个端口API:
    user-service服务器:


    image.png

    role-service服务器:


    image.png

    演示跨服务器异步访问:

    # user_service/views.py
    @user_bp.get('/<id:int>', name="get_user")
    async def get_user(request, id):
        async with request.app.db.acquire(request) as cur:
            records = await cur.fetch(
                """ SELECT * FROM users WHERE id = $1 """, id)
            records = records[0]
            datas = [
                [records, 'role_id', get_role_by_id(request, records['role_id'])]
            ]
            await async_request(datas)
            return records
    
    async def get_role_by_id(request, id):
        cli = request.app.role_client.cli(request)
        async with cli.get('roles/{}'.format(id)) as res:
            return await res.json()
    
    image.png

    - zipkin分布式追踪系统

    查看刚才的访问记录:
    可以清晰地看到访问user_server/user/1,微服务里各节点的记录、消耗时间等

    image.png

    - Swagger API文档自动生成

    通过修改右上角server地址,可以查看其它sevice的API


    image.png

    几个要点:

    • 服务启动顺序非常重要!
      consul, zipkin必须在其它service之前启动,否则发现不了其它服务
      user_server启动须安排在role_server/region_server之后,不然Client服务创建会失败:
    @app.listener('before_server_start')
    async def before_srver_start(app, loop):
        app.region_client = Client('region-service', app=app)   # service name is APP-ID
        app.role_client = Client('role-service', app=app)
    
    • 原repo,sanicms模块是作为python包安装的,不方便经常更新sanicms里的内容。所以我的repo里,sanicms是作为一个内部模块了,跟其它模块在同一级目录。

    后续计划

    • 添加www服务
    • Sanic_session管理模块
    • Cache: 选用aiocache + aioredis
    • Sanic_JWT鉴权模块
    • 异步数据库操作进阶: 超快的asyncpg + peewee/gino?
    • 任务队列管理Celery
      sanic add_task feature is just wrapper on asyncio loop.create_task and nothing more. Asyncio tasks more like short processing and not for long background jobs.
    • Sanic_WebSocket
    • more...

    参考:https://github.com/mfornos/awesome-microservices


    点一下“喜欢”哦,大家的鼓励才是我写作的动力!

    相关文章

      网友评论

        本文标题:基于sanic的微服务框架 - 架构分析

        本文链接:https://www.haomeiwen.com/subject/vhiwqqtx.html