当前位置: 首页 > news >正文

Tornado + Motor 微服务架构(Docker + 测试 + Kubernetes)

Tornado + Motor 微服务架构(Docker + 测试 + Kubernetes)

一、项目结构

project-root/
├── docker-compose.yml
├── k8s/                    # Kubernetes 配置文件
│   ├── api-deployment.yaml
│   ├── api-service.yaml
│   ├── user-deployment.yaml
│   ├── user-service.yaml
│   ├── mongo-deployment.yaml
│   ├── mongo-service.yaml
│   └── ingress.yaml
├── common/
│   ├── config.py
│   ├── db.py
│   ├── utils.py
├── api_service/
│   ├── Dockerfile
│   ├── main.py
│   ├── handlers/
│   │   └── user_handler.py
│   ├── services/
│   │   └── user_service.py
│   └── tests/
│       └── test_user.py
├── user_service/
│   ├── Dockerfile
│   ├── main.py
│   ├── handlers/
│   │   └── user_handler.py
│   ├── services/
│   │   └── user_service.py
│   └── tests/
│       └── test_user.py
└── requirements.txt

二、核心依赖(requirements.txt)

tornado==6.4
motor==3.3.2
pytest==8.2.0
pytest-asyncio==0.24.0
requests==2.32.3

三、公共模块(common/)

config.py

import osMONGO_URI = os.getenv('MONGO_URI', 'mongodb://mongo:27017')
DB_NAME = os.getenv('DB_NAME', 'microdb')
SERVICE_NAME = os.getenv('SERVICE_NAME', 'default-service')
PORT = int(os.getenv('PORT', 8000))

db.py

from motor.motor_tornado import MotorClient
from common.config import MONGO_URI, DB_NAMEclient = MotorClient(MONGO_URI)
db = client[DB_NAME]

utils.py

import json
import tornado.webclass BaseHandler(tornado.web.RequestHandler):def set_default_headers(self):self.set_header('Content-Type', 'application/json')def write_json(self, data, status=200):self.set_status(status)self.write(json.dumps(data))

四、API 服务(api_service/)

Dockerfile

FROM python:3.11-slim
WORKDIR /app
COPY ../../requirements.txt ./
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]

main.py

import tornado.ioloop
import tornado.web
from tornado.process import fork_processes
from handlers.user_handler import UserHandler
from common.config import PORTdef make_app():return tornado.web.Application([(r"/user", UserHandler),])if __name__ == '__main__':fork_processes(None)  # 多进程 workerapp = make_app()app.listen(PORT)tornado.ioloop.IOLoop.current().start()

handlers/user_handler.py

from common.utils import BaseHandler
from services.user_service import UserServiceclass UserHandler(BaseHandler):async def get(self):users = await UserService().get_all_users()self.write_json({"users": users})async def post(self):data = self.request.body.decode()result = await UserService().create_user(data)self.write_json(result)

services/user_service.py

from common.db import db
import jsonclass UserService:async def get_all_users(self):cursor = db.users.find()return [doc async for doc in cursor]async def create_user(self, data):user = json.loads(data)result = await db.users.insert_one(user)return {"_id": str(result.inserted_id)}

tests/test_user.py

import pytest
import asyncio
from services.user_service import UserService@pytest.mark.asyncio
async def test_create_user():service = UserService()res = await service.create_user('{"name":"test_user"}')assert "_id" in res

五、User 服务(user_service/)

结构相同,只是接口路径不同,例如 /profile


六、Docker Compose

docker-compose.yml

version: '3.8'
services:mongo:image: mongo:6.0container_name: mongoports:- "27017:27017"api_service:build: ./api_servicecontainer_name: api_serviceenvironment:- MONGO_URI=mongodb://mongo:27017- DB_NAME=microdb- PORT=8000ports:- "8000:8000"depends_on:- mongouser_service:build: ./user_servicecontainer_name: user_serviceenvironment:- MONGO_URI=mongodb://mongo:27017- DB_NAME=microdb- PORT=8001ports:- "8001:8001"depends_on:- mongo

七、Kubernetes 配置示例(k8s/)

api-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:name: api-deployment
spec:replicas: 2selector:matchLabels:app: api-servicetemplate:metadata:labels:app: api-servicespec:containers:- name: api-serviceimage: api_service:latestports:- containerPort: 8000

api-service.yaml

apiVersion: v1
kind: Service
metadata:name: api-service
spec:type: ClusterIPselector:app: api-serviceports:- port: 8000targetPort: 8000

ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: micro-ingress
spec:rules:- host: micro.localhttp:paths:- path: /userpathType: Prefixbackend:service:name: api-serviceport:number: 8000

八、运行与测试

  1. 启动开发环境:

    docker-compose up --build
    
  2. 本地运行测试:

    pytest -v
    
  3. 部署到 Kubernetes:

    kubectl apply -f k8s/
    

九、说明

  • Tornado 使用多进程 worker(fork_processes(None))自动创建与 CPU 核数相同的进程。
  • MongoDB 异步连接由 Motor 驱动支持。
  • 测试通过 pytest-asyncio 实现异步单元测试。
  • Kubernetes YAML 已含 Ingress,可直接对外暴露 API 服务。

这一结构可直接扩展为完整的微服务体系,每个服务都独立运行、可水平扩展。

http://www.dtcms.com/a/515298.html

相关文章:

  • YLOLv4
  • 实验室入门——ubuntu20.04安装ros和ros2全流程
  • uTools 最新版优化macOS 26 高 GPU 占用问题
  • wordpress如何建站拓普建站推广
  • 建筑智库免费网站商城网站开发报
  • 从埋点到用户行为分析:ClkLog 如何帮助企业读懂用户
  • 【Q-dir】QDir_x64窗口配合Mouselnc实现上一步
  • 手机网站备案密码找回的方法枣庄专业做网站
  • Oracle Database 19c 服务端(19.3)下载与安装
  • 如何使用 vxe-table 实现全键盘操作,按键切换复选框单选框的选中状态
  • AI IDE 编辑器产品销售策略:从功能宣讲到赋能用户盈利的范式转变[特殊字符]
  • K8S知识点--Node和NameSpace
  • 【开发AI】Windows安装和使用Milvus的保姆级教程
  • 【完整源码+数据集+部署教程】【零售和消费品&存货】食品分类检测系统源码&数据集全套:改进yolo11-RepNCSPELAN_CAA
  • 【Qt】文件操作/事件--mainwindow做编辑器
  • 高频低客单价产品怎么做私域?餐饮/生鲜/零售用社群运营提效37%的私域代运营方案
  • 石家庄大型网站建设做it题的网站
  • 网站建设 要维护么重庆做汉堡的餐饮公司网站
  • leetcode单链表反转
  • 【英语】listicles 是什么意思?
  • JSA变成类似vba环境给第三方软件集成IDE功能,脚本功能
  • 做外单网站亚马逊wordpress菜单分开
  • [ Java 反射机制 ]
  • 元宇宙与医疗健康的深度融合:重构诊疗、培训与健康管理新生态
  • 《算法闯关指南:优选算法--二分查找》--21.山峰数组的的峰顶索引,22.寻找峰值
  • h5游戏免费下载:弗莱迪的物理实验
  • C++ 学习 —— 03 - 类
  • 元宇宙与金融的深度融合:重构服务生态与价值边界
  • 用js做的网站页面设计理念万能模板
  • 做音乐网站的目的在线画画网站