微服务架构 (Microservices)
微服务架构(Microservices Architecture)是一种将单体应用拆分为一组小型、独立服务的设计方法。每个服务运行在独立进程中,围绕业务能力构建,通过轻量级协议(通常是 HTTP/API)通信。1
单体架构 vs 微服务
单体架构 (Monolithic)
┌─────────────────────────────┐
│ 单体应用 │
├─────────────────────────────┤
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ 用户 │ │ 订单 │ │ 库存 │ │
│ │ 模块 │ │ 模块 │ │ 模块 │ │
│ └──┬──┘ └──┬──┘ └──┬──┘ │
│ └────────┼────────┘ │
│ ▼ │
│ ┌──────┐ │
│ │数据库│ │
│ └──────┘ │
└─────────────────────────────┘
特点:
- 部署简单(单一部署单元)
- 性能开销小(无网络调用)
- 测试相对容易
- 但扩展困难、维护成本高
微服务架构
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 用户服务 │ │ 订单服务 │ │ 库存服务 │
│ :8001 │ │ :8002 │ │ :8003 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└────────────┼────────────┘
▼
┌────────────┐
│ API Gateway │
└────────────┘
特点:
- 每个服务独立部署
- 按需扩展特定服务
- 技术栈多样化
- 故障隔离
- 但复杂度高,运维挑战大
核心设计原则
1. 单一职责原则 (SRP)
每个微服务只负责一个业务领域:
用户服务 → 用户注册、登录、权限
订单服务 → 订单创建、查询、取消
支付服务 → 支付处理、退款
库存服务 → 库存查询、扣减
2. 独立数据存储
每个服务拥有自己的数据库:
用户服务 → 用户数据库 (MySQL)
订单服务 → 订单数据库 (PostgreSQL)
库存服务 → 库存数据库 (MongoDB)
好处:
- 服务间解耦
- 可选择最适合的数据库
- 独立扩展
3. API 优先设计
服务间通过明确定义的 API 通信:
# OpenAPI 规范示例
openapi: 3.0.0
info:
title: Order Service API
version: 1.0.0
paths:
/orders:
post:
summary: 创建订单
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
responses:
'201':
description: 订单创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/OrderResponse'服务间通信
同步通信 (Synchronous)
REST/gHTTP:
# 获取用户信息
curl -X GET http://user-service:8001/users/123gRPC:
// user.proto
service UserService {
rpc GetUser(GetUserRequest) returns (User);
rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
}
message GetUserRequest {
string user_id = 1;
}
message User {
string id = 1;
string name = 2;
string email = 3;
}异步通信 (Asynchronous)
消息队列:
订单服务 ──publish──► 消息队列 ──subscribe──► 库存服务
│
└──subscribe──► 通知服务
常用消息队列:
- RabbitMQ:可靠性高,功能丰富
- Apache Kafka:高吞吐量,日志处理
- ActiveMQ:Java 生态系统
# RabbitMQ 配置示例
# docker-compose.yml
services:
rabbitmq:
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"事件驱动 (Event-Driven)
服务通过事件进行通信:
// 订单创建事件
{
"event_type": "order_created",
"order_id": "ORD-2024-001",
"user_id": "USR-123",
"items": [
{"product_id": "PROD-456", "quantity": 2}
],
"timestamp": "2024-01-15T10:30:00Z"
}API 网关 (API Gateway)
API 网关作为系统的单一入口:
┌──────────────┐
客户端 ─────────►│ API Gateway │
└──────┬───────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│用户服务 │ │订单服务 │ │商品服务 │
└──────────┘ └──────────┘ └──────────┘
功能:
- 请求路由
- 身份认证/鉴权
- 限流熔断
- 日志监控
- 协议转换
常用 API 网关
| 网关 | 特点 |
|---|---|
| Nginx | 高性能,反向代理 |
| Kong | 可扩展,插件丰富 |
| Spring Cloud Gateway | Java 生态,Spring 集成 |
| Envoy | 服务网格数据平面 |
服务发现 (Service Discovery)
客户端发现
服务直接向注册中心查询:
# Python 服务发现客户端
import consul
c = consul.Consul()
def get_user_service():
services = c.agent.services()
user_service = services.get('user-service')
if user_service:
return f"http://{user_service['Address']}:{user_service['Port']}"
return None服务端发现
通过负载均衡器发现服务:
服务 ──查询──► 负载均衡器 ──转发──► 目标服务
熔断器模式 (Circuit Breaker)
防止级联故障:
import time
from functools import wraps
class CircuitBreaker:
def __init__(self, failure_threshold=5, timeout=60):
self.failure_threshold = failure_threshold
self.timeout = timeout
self.failures = 0
self.last_failure_time = None
self.state = 'CLOSED' # CLOSED, OPEN, HALF_OPEN
def call(self, func, *args, **kwargs):
if self.state == 'OPEN':
if time.time() - self.last_failure_time > self.timeout:
self.state = 'HALF_OPEN'
else:
raise CircuitOpenError("Circuit is OPEN")
try:
result = func(*args, **kwargs)
if self.state == 'HALF_OPEN':
self.state = 'CLOSED'
self.failures = 0
return result
except Exception as e:
self.failures += 1
self.last_failure_time = time.time()
if self.failures >= self.failure_threshold:
self.state = 'OPEN'
raise分布式事务
微服务架构中,跨服务的事务处理是难点。
两阶段提交 (2PC)
第一阶段(Prepare):
协调者 ──prepare──► 所有参与者
◄──OK/FAIL──
第二阶段(Commit/Rollback):
协调者 ──commit──► 所有参与者(全部OK)
◄──ACK──
Saga 模式
将大事务拆分为多个小事务,通过补偿机制保证最终一致性:
创建订单 Saga:
1. 创建订单(pending) ──► 成功
2. 预留库存(reserved) ◄──► 失败则释放
3. 扣款(paid) ◄──► 失败则释放库存
4. 完成订单(completed)
补偿动作:
def cancel_order(order_id):
# 1. 取消订单
order_service.cancel(order_id)
# 2. 释放库存
inventory_service.release(order_id)
# 3. 退款
payment_service.refund(order_id)容器化与编排
Docker 部署
# user-service/Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8001
CMD ["python", "app.py"]Docker Compose 本地开发
# docker-compose.yml
version: '3.8'
services:
user-service:
build: ./user-service
ports:
- "8001:8001"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/users
depends_on:
- db
order-service:
build: ./order-service
ports:
- "8002:8002"
environment:
- USER_SERVICE_URL=http://user-service:8001
- DATABASE_URL=postgresql://user:pass@db:5432/orders
api-gateway:
build: ./api-gateway
ports:
- "80:8080"
depends_on:
- user-service
- order-service
db:
image: postgres:15
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:Kubernetes 部署
# user-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: myregistry/user-service:v1.0
ports:
- containerPort: 8001
resources:
limits:
memory: "256Mi"
cpu: "500m"
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 80
targetPort: 8001
type: ClusterIP监控与日志
分布式追踪
使用 Jaeger 或 Zipkin:
请求: GET /orders/123
│
▼
API Gateway (10ms)
│
▼
Order Service (50ms)
├── User Service (20ms)
└── Inventory Service (15ms)
日志聚合
使用 ELK Stack (Elasticsearch, Logstash, Kibana):
各服务 ──► Filebeat ──► Logstash ──► Elasticsearch ──► Kibana
└────────────┐
▼
Loki/Grafana
关键指标
| 指标类型 | 示例 |
|---|---|
| RED 指标 | Rate(请求率)、Errors(错误率)、Duration(延迟) |
| 基础设施 | CPU、内存、网络 |
| 业务指标 | 订单量、转化率 |
优缺点总结
优点
- 独立部署:可单独部署每个服务
- 技术多样性:不同服务可用不同技术栈
- 故障隔离:一个服务故障不导致全线崩溃
- 团队自治:团队可独立负责特定服务
- 按需扩展:只扩展需要的服务
缺点
- 复杂度高:分布式系统的固有复杂性
- 运维挑战:需要成熟的 CI/CD 和监控
- 数据一致性:跨服务事务处理困难
- 网络延迟:服务调用有额外开销
- 测试复杂:集成测试比单体复杂
适用场景
适合微服务:
- 大型复杂应用
- 需要高扩展性
- 多团队协作开发
- 快速迭代需求
可能不需要微服务:
- 小型简单应用
- 团队规模小
- 创业初期快速验证
- 运维能力有限
参考
Footnotes
-
本段参考微服务架构 - OI Wiki ↩