基于sanic的微服務(wù)框架 - 架構(gòu)分析

感謝@songcser分享的《基于sanic的微服務(wù)基礎(chǔ)架構(gòu)》https://github.com/songcser/sanic-ms
最近正在學(xué)習(xí)微服務(wù),發(fā)現(xiàn)這個repo不錯,但不完整,跑不起來。所以學(xué)習(xí)了一下源碼,實際使用Docker部署成功,本文記錄實現(xiàn)過程。
學(xué)習(xí)用的git: https://github.com/kevinqqnj/sanic-ms

0. sanicms總體框架

image.png

1. 微服務(wù)是什么

微服務(wù)架構(gòu)是一種將單應(yīng)用程序作為一套小型服務(wù)開發(fā)的方法,每種應(yīng)用程序都在其自己的進(jìn)程中運行,并與輕量級機(jī)制(通常是HTTP資源的API)進(jìn)行通信。這些服務(wù)是圍繞業(yè)務(wù)功能構(gòu)建的,可以通過全自動部署機(jī)制進(jìn)行獨立部署。這些服務(wù)的集中化管理已經(jīng)是最少的,它們可以用不同的編程語言編寫,并使用不同的數(shù)據(jù)存儲技術(shù)。

image.png

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

2. 使用的功能模塊

Project structure

├── develop # 開發(fā)腳本
│ ├── cluster.sh
│ ├── reset.sh # 初始化項目
│ ├── test.sh
│ ├── utils.sh
│ ├── wait-for-it.sh
│ └── wait-service.sh
├── region_service # 微服務(wù)之1
│ ├── sanicms
│ ├── info.log
│ ├── migrations.py
│ ├── models.py
│ ├── server.py
│ ├── settings.py
│ └── views.py
├── role_service # 微服務(wù)之2
│ ├── ...
├── user_service # 微服務(wù)之3
│ ├── ...
├── sanicms # 微服務(wù)主框架
│ ├── _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微服務(wù)服務(wù)的配置文件,包括db/zipkin/swagger/consul
├── Dockerfile # Docker微服務(wù)的基本環(huán)境包
├── pylintrc
├── README.md
└── requirements.txt # Python依賴模塊

3. Docker部署

  1. 安裝Docker in Ubuntu (WSL): http://www.itdecent.cn/p/97d16b68045f

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

  3. 調(diào)用腳本來配置docker-compose,初始化數(shù)據(jù)庫

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

各服務(wù)端口:

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. 檢查各個服務(wù)是否已正常運行

- consul服務(wù)發(fā)現(xiàn)

已經(jīng)發(fā)現(xiàn)consul自己的集群,還有基于sanic的3個服務(wù)


image.png

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


image.png

- sanic服務(wù)

目前演示了3個服務(wù):user-service, role-service, region-service
添加一些測試數(shù)據(jù):

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服務(wù)器:


image.png

role-service服務(wù)器:


image.png

演示跨服務(wù)器異步訪問:

# 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分布式追蹤系統(tǒng)

查看剛才的訪問記錄:
可以清晰地看到訪問user_server/user/1,微服務(wù)里各節(jié)點的記錄、消耗時間等

image.png

- Swagger API文檔自動生成

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


image.png

幾個要點:

  • 服務(wù)啟動順序非常重要!
    consul, zipkin必須在其它service之前啟動,否則發(fā)現(xiàn)不了其它服務(wù)
    user_server啟動須安排在role_server/region_server之后,不然Client服務(wù)創(chuàng)建會失?。?/li>
@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包安裝的,不方便經(jīng)常更新sanicms里的內(nèi)容。所以我的repo里,sanicms是作為一個內(nèi)部模塊了,跟其它模塊在同一級目錄。

后續(xù)計劃

  • 添加www服務(wù)
  • Sanic_session管理模塊
  • Cache: 選用aiocache + aioredis
  • Sanic_JWT鑒權(quán)模塊
  • 異步數(shù)據(jù)庫操作進(jìn)階: 超快的asyncpg + peewee/gino?
  • 任務(wù)隊列管理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


點一下“喜歡”哦,大家的鼓勵才是我寫作的動力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容