一、后端架构的演进
后端架构经历了从单体应用到微服务的演进:
- 单体架构:所有功能在一个应用中,开发简单但扩展困难
- SOA 架构:服务化思想初步形成,但仍然重量级
- 微服务架构:服务独立部署、独立扩展,但复杂度增加
- 云原生架构:容器化、服务网格、Serverless 成为主流
理解这些架构模式,能帮助你在不同阶段做出正确的技术决策。
二、服务拆分模式
2.1 按业务能力拆分
# 用户服务 - user-service/
class UserService:
def get_user(self, user_id: int) -> User:
"""获取用户信息"""
pass
def update_profile(self, user_id: int, profile: Profile) -> User:
"""更新用户资料"""
pass
def check_permission(self, user_id: int, resource: str) -> bool:
"""权限检查"""
pass
# 订单服务 - order-service/
class OrderService:
def create_order(self, user_id: int, items: List[OrderItem]) -> Order:
"""创建订单"""
pass
def get_orders(self, user_id: int, status: str = None) -> List[Order]:
"""获取订单列表"""
pass
def cancel_order(self, order_id: int) -> bool:
"""取消订单"""
pass
# 支付服务 - payment-service/
class PaymentService:
def process_payment(self, order_id: int, method: str) -> PaymentResult:
"""处理支付"""
pass
def refund(self, payment_id: int, amount: float) -> bool:
"""退款"""
pass
2.2 按领域拆分
src/
├── domain/ # 领域层
│ ├── user/ # 用户领域
│ │ ├── entities/ # 实体
│ │ ├── value_objects/ # 值对象
│ │ ├── aggregates/ # 聚合根
│ │ ├── repositories/ # 仓储接口
│ │ └── services/ # 领域服务
│ ├── order/ # 订单领域
│ │ ├── entities/
│ │ ├── value_objects/
│ │ ├── aggregates/
│ │ ├── repositories/
│ │ └── services/
│ └── payment/ # 支付领域
│ ├── entities/
│ ├── value_objects/
│ ├── aggregates/
│ ├── repositories/
│ └── services/
├── application/ # 应用层
│ ├── user/
│ │ ├── dto/ # 数据传输对象
│ │ ├── services/ # 应用服务
│ │ └── facades/ # 服务门面
│ ├── order/
│ └── payment/
├── infrastructure/ # 基础设施层
│ ├── persistence/ # 持久化
│ ├── messaging/ # 消息队列
│ └── external/ # 外部服务
└── interfaces/ # 接口层
├── rest/
├── grpc/
└── webhooks/
三、数据访问模式
3.1 仓储模式
from abc import ABC, abstractmethod
from typing import List, Optional
class UserRepository(ABC):
@abstractmethod
def find_by_id(self, user_id: int) -> Optional[User]:
pass
@abstractmethod
def find_by_email(self, email: str) -> Optional[User]:
pass
@abstractmethod
def find_all(self, page: int, size: int) -> List[User]:
pass
@abstractmethod
def save(self, user: User) -> User:
pass
@abstractmethod
def delete(self, user_id: int) -> bool:
pass
# PostgreSQL 实现
class PostgresUserRepository(UserRepository):
def __init__(self, connection: Connection):
self.connection = connection
def find_by_id(self, user_id: int) -> Optional[User]:
with self.connection.cursor() as cursor:
cursor.execute(
"SELECT * FROM users WHERE id = %s",
(user_id,)
)
row = cursor.fetchone()
return User.from_row(row) if row else None
def save(self, user: User) -> User:
if user.id:
# 更新
with self.connection.cursor() as cursor:
cursor.execute("""
UPDATE users SET
name = %s, email = %s, updated_at = NOW()
WHERE id = %s
""", (user.name, user.email, user.id))
else:
# 插入
with self.connection.cursor() as cursor:
cursor.execute("""
INSERT INTO users (name, email, created_at, updated_at)
VALUES (%s, %s, NOW(), NOW())
RETURNING id
""", (user.name, user.email))
user.id = cursor.fetchone()[0]
return user
3.2 工作单元模式
class UnitOfWork:
def __init__(self, connection: Connection):
self.connection = connection
self._new_objects = []
self._dirty_objects = []
self._removed_objects = []
def register_new(self, obj):
self._new_objects.append(obj)
def register_dirty(self, obj):
self._dirty_objects.append(obj)
def register_removed(self, obj):
self._removed_objects.append(obj)
def commit(self):
try:
# 插入新对象
for obj in self._new_objects:
if hasattr(obj, '_insert'):
obj._insert(self.connection)
# 更新脏对象
for obj in self._dirty_objects:
if hasattr(obj, '_update'):
obj._update(self.connection)
# 删除对象
for obj in self._removed_objects:
if hasattr(obj, '_delete'):
obj._delete(self.connection)
self.connection.commit()
# 清空缓存
self._new_objects.clear()
self._dirty_objects.clear()
self._removed_objects.clear()
except Exception as e:
self.connection.rollback()
raise e
def rollback(self):
self.connection.rollback()
self._new_objects.clear()
self._dirty_objects.clear()
self._removed_objects.clear()
3.3 CQRS 模式
# 命令端 - 写操作
class CreateOrderCommand:
def __init__(self, user_id: int, items: List[OrderItem]):
self.user_id = user_id
self.items = items
class CreateOrderHandler:
def __init__(self, order_repository, event_bus):
self.order_repository = order_repository
self.event_bus = event_bus
def handle(self, command: CreateOrderCommand):
# 验证
user = self._validate_user(command.user_id)
items = self._validate_items(command.items)
# 创建订单
order = Order.create(user, items)
self.order_repository.save(order)
# 发布事件
self.event_bus.publish(OrderCreatedEvent(order.id))
return order.id
# 查询端 - 读操作
class OrderQueryService:
def __init__(self, read_database: Connection):
self.read_db = read_database
def get_order_summary(self, order_id: int) -> OrderSummaryDTO:
with self.read_db.cursor() as cursor:
cursor.execute("""
SELECT o.id, o.status, o.total_amount,
u.name as user_name, u.email,
json_agg(json_build_object(
'product_name', p.name,
'quantity', oi.quantity,
'price', oi.price
)) as items
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE o.id = %s
GROUP BY o.id, o.status, o.total_amount, u.name, u.email
""", (order_id,))
return OrderSummaryDTO.from_row(cursor.fetchone())
def get_user_orders(self, user_id: int, page: int = 1) -> List[OrderListItem]:
offset = (page - 1) * 20
with self.read_db.cursor() as cursor:
cursor.execute("""
SELECT id, status, total_amount, created_at
FROM orders
WHERE user_id = %s
ORDER BY created_at DESC
LIMIT 20 OFFSET %s
""", (user_id, offset))
return [OrderListItem.from_row(row) for row in cursor.fetchall()]
四、消息通信模式
4.1 事件驱动架构
from abc import ABC, abstractmethod
from typing import Any, Dict
class DomainEvent(ABC):
@property
@abstractmethod
def event_type(self) -> str:
pass
@property
@abstractmethod
def aggregate_id(self) -> str:
pass
def to_dict(self) -> Dict[str, Any]:
return {
'event_type': self.event_type,
'aggregate_id': self.aggregate_id,
'timestamp': datetime.utcnow().isoformat(),
'payload': self._get_payload()
}
@abstractmethod
def _get_payload(self) -> Dict[str, Any]:
pass
class OrderCreatedEvent(DomainEvent):
def __init__(self, order_id: int, user_id: int, total_amount: float):
self._order_id = order_id
self._user_id = user_id
self._total_amount = total_amount
@property
def event_type(self) -> str:
return 'order.created'
@property
def aggregate_id(self) -> str:
return str(self._order_id)
def _get_payload(self) -> Dict[str, Any]:
return {
'order_id': self._order_id,
'user_id': self._user_id,
'total_amount': self._total_amount
}
# 事件总线
class EventBus:
def __init__(self):
self._handlers: Dict[str, List[Callable]] = {}
def subscribe(self, event_type: str, handler: Callable):
if event_type not in self._handlers:
self._handlers[event_type] = []
self._handlers[event_type].append(handler)
def publish(self, event: DomainEvent):
event_type = event.event_type
if event_type in self._handlers:
for handler in self._handlers[event_type]:
try:
handler(event)
except Exception as e:
# 记录错误但不影响其他处理器
logger.error(f"Handler failed: {e}")
def publish_async(self, event: DomainEvent):
# 异步发布 - 使用消息队列
message = json.dumps(event.to_dict())
redis.publish('events', message)
4.2 Saga 模式
class OrderSaga:
def __init__(self, order_service, payment_service, inventory_service, notification_service):
self.steps = [
self._create_order,
self._reserve_inventory,
self._process_payment,
self._confirm_order,
self._send_notification
]
self.compensating_steps = [
self._cancel_order,
self._release_inventory,
self._refund_payment
]
async def execute(self, order_data: dict) -> SagaResult:
context = SagaContext()
try:
for step in self.steps:
result = await step(order_data, context)
context.add_step_result(step.__name__, result)
return SagaResult.success(context)
except Exception as e:
# 执行补偿操作
await self._execute_compensation(context)
return SagaResult.failed(str(e))
async def _create_order(self, order_data: dict, context: SagaContext) -> dict:
order = await self.order_service.create(order_data)
context.set('order_id', order.id)
return {'order_id': order.id, 'status': 'created'}
async def _reserve_inventory(self, order_data: dict, context: SagaContext) -> dict:
order_id = context.get('order_id')
result = await self.inventory_service.reserve(order_id)
context.set('inventory_reserved', True)
return {'inventory_id': result.id, 'status': 'reserved'}
async def _process_payment(self, order_data: dict, context: SagaContext) -> dict:
order_id = context.get('order_id')
result = await self.payment_service.charge(order_id)
context.set('payment_id', result.payment_id)
return {'payment_id': result.payment_id, 'status': 'paid'}
async def _cancel_order(self, context: SagaContext):
order_id = context.get('order_id')
await self.order_service.cancel(order_id)
async def _release_inventory(self, context: SagaContext):
if context.get('inventory_reserved'):
inventory_id = context.get('inventory_id')
await self.inventory_service.release(inventory_id)
async def _refund_payment(self, context: SagaContext):
if context.get('payment_id'):
payment_id = context.get('payment_id')
await self.payment_service.refund(payment_id)
4.3 消息队列模式
import asyncio
from typing import Callable, Any
class MessageQueue:
def __init__(self, broker: str):
self.broker = broker
self._consumers: Dict[str, List[Callable]] = {}
self._running = False
async def publish(self, topic: str, message: Any, priority: int = 0):
"""发布消息"""
if self.broker == 'rabbitmq':
await self._publish_rabbitmq(topic, message, priority)
elif self.broker == 'kafka':
await self._publish_kafka(topic, message)
elif self.broker == 'redis':
await self._publish_redis(topic, message)
async def subscribe(self, topic: str, handler: Callable, group_id: str = None):
"""订阅消息"""
if topic not in self._consumers:
self._consumers[topic] = []
self._consumers[topic].append(handler)
if not self._running:
self._running = True
await self._start_consuming()
async def _start_consuming(self):
"""开始消费消息"""
for topic, handlers in self._consumers.items():
asyncio.create_task(self._consume_loop(topic, handlers))
async def _consume_loop(self, topic: str, handlers: List[Callable]):
"""消费循环"""
while self._running:
try:
message = await self._get_message(topic)
for handler in handlers:
try:
await handler(message)
except Exception as e:
logger.error(f"Handler error: {e}")
# 可以发送到死信队列
await self._send_to_dlq(topic, message, e)
except Exception as e:
logger.error(f"Consume error: {e}")
await asyncio.sleep(1) # 避免空转
# 使用示例
async def handle_order_created(message: dict):
order_id = message['order_id']
# 发送通知
await notification_service.send_order_confirmation(order_id)
# 更新库存
await inventory_service.update(order_id)
mq = MessageQueue('rabbitmq')
await mq.subscribe('order.created', handle_order_created)
await mq.publish('order.created', {
'order_id': 12345,
'user_id': 678,
'total': 99.99
})
五、缓存模式
5.1 多级缓存
class MultiLevelCache:
def __init__(self):
# L1: 本地内存缓存
self._l1 = {}
# L2: Redis 分布式缓存
self._l2 = None # Redis client
# L3: 数据库
async def get(self, key: str) -> Any:
# 先查 L1
if key in self._l1:
return self._l1[key]
# 再查 L2
if self._l2:
value = await self._l2.get(key)
if value:
# 回填 L1
self._l1[key] = value
return value
# 查 L3(数据库)
value = await self._fetch_from_db(key)
if value:
# 回填 L1 和 L2
self._l1[key] = value
if self._l2:
await self._l2.set(key, value, ttl=3600)
return value
async def set(self, key: str, value: Any, ttl: int = None):
# 设置 L1
self._l1[key] = value
# 设置 L2
if self._l2:
await self._l2.set(key, value, ttl=ttl or 3600)
async def delete(self, key: str):
# 删除 L1
self._l1.pop(key, None)
# 删除 L2
if self._l2:
await self._l2.delete(key)
5.2 缓存穿透防护
class CacheWithBloomFilter:
def __init__(self, cache: MultiLevelCache, bloom_filter):
self.cache = cache
self.bloom_filter = bloom_filter
async def get(self, key: str) -> Any:
# 先检查布隆过滤器
if not self.bloom_filter.might_contain(key):
return None # 一定不存在
# 查缓存
return await self.cache.get(key)
async def set(self, key: str, value: Any, ttl: int = None):
# 设置布隆过滤器
self.bloom_filter.add(key)
# 设置缓存
await self.cache.set(key, value, ttl)
# 缓存空值防止缓存击穿
class CacheWithNullValue:
def __init__(self):
self._cache = {}
self._null_cache = {} # 存储空值
async def get(self, key: str) -> Any:
# 查普通缓存
if key in self._cache:
return self._cache[key]
# 查空值缓存
if key in self._null_cache:
# 检查是否过期
if time.time() - self._null_cache[key]['time'] < 60:
return None # 返回空,不查询数据库
del self._null_cache[key]
# 查数据库
value = await self._fetch_from_db(key)
if value:
self._cache[key] = value
else:
# 写入空值缓存
self._null_cache[key] = {'time': time.time()}
return value
5.3 缓存一致性
class CacheAsidePattern:
def __init__(self, cache: MultiLevelCache, repository):
self.cache = cache
self.repository = repository
async def get(self, key: str) -> Any:
# 读缓存
value = await self.cache.get(key)
if value is not None:
return value
# 读数据库
value = await self.repository.find_by_id(key)
if value:
# 写缓存
await self.cache.set(key, value)
return value
async def set(self, key: str, value: Any):
# 写数据库
await self.repository.save(value)
# 删除缓存(不是更新)
await self.cache.delete(key)
async def delete(self, key: str):
# 删除数据库
await self.repository.delete(key)
# 删除缓存
await self.cache.delete(key)
async def update(self, key: str, updates: dict):
# 更新数据库
await self.repository.update(key, updates)
# 删除缓存
await self.cache.delete(key)
六、容错模式
6.1 断路器
import asyncio
from enum import Enum
from datetime import datetime, timedelta
class CircuitState(Enum):
CLOSED = 'closed' # 正常
OPEN = 'open' # 断开
HALF_OPEN = 'half_open' # 半开
class CircuitBreaker:
def __init__(self, name: str, failure_threshold: int = 5,
recovery_timeout: int = 60, half_open_success_threshold: int = 2):
self.name = name
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.half_open_success_threshold = half_open_success_threshold
self._state = CircuitState.CLOSED
self._failure_count = 0
self._success_count = 0
self._last_failure_time = None
self._half_open_attempts = 0
@property
def state(self) -> CircuitState:
if self._state == CircuitState.OPEN:
if datetime.now() - self._last_failure_time > timedelta(seconds=self.recovery_timeout):
self._state = CircuitState.HALF_OPEN
self._half_open_attempts = 0
return self._state
async def call(self, func, *args, **kwargs):
if self.state == CircuitState.OPEN:
raise CircuitOpenError(f"Circuit {self.name} is open")
try:
result = await func(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise
def _on_success(self):
if self._state == CircuitState.HALF_OPEN:
self._half_open_attempts += 1
if self._half_open_attempts >= self.half_open_success_threshold:
self._state = CircuitState.CLOSED
self._failure_count = 0
else:
self._failure_count = 0
def _on_failure(self):
self._failure_count += 1
self._last_failure_time = datetime.now()
if self._failure_count >= self.failure_threshold:
self._state = CircuitState.OPEN
# 使用
circuit_breaker = CircuitBreaker('payment-service')
async def process_payment(order_id: int):
return await circuit_breaker.call(payment_service.charge, order_id)
6.2 重试模式
import asyncio
from typing import Callable, TypeVar, Optional
T = TypeVar('T')
class RetryPolicy:
def __init__(self, max_attempts: int = 3,
initial_delay: float = 1.0,
max_delay: float = 60.0,
exponential_base: float = 2.0,
retryable_exceptions: tuple = (Exception,)):
self.max_attempts = max_attempts
self.initial_delay = initial_delay
self.max_delay = max_delay
self.exponential_base = exponential_base
self.retryable_exceptions = retryable_exceptions
async def execute(self, func: Callable[..., T], *args, **kwargs) -> T:
last_exception = None
for attempt in range(self.max_attempts):
try:
return await func(*args, **kwargs)
except self.retryable_exceptions as e:
last_exception = e
if attempt < self.max_attempts - 1:
delay = self._calculate_delay(attempt)
await asyncio.sleep(delay)
raise last_exception
def _calculate_delay(self, attempt: int) -> float:
delay = self.initial_delay * (self.exponential_base ** attempt)
return min(delay, self.max_delay)
# 使用
retry_policy = RetryPolicy(
max_attempts=3,
initial_delay=0.5,
exponential_base=2.0,
retryable_exceptions=(ConnectionError, TimeoutError, TransientError)
)
async def fetch_user(user_id: int):
return await retry_policy.execute(user_service.get_by_id, user_id)
6.3 限流模式
import asyncio
from collections import deque
from datetime import datetime, timedelta
class TokenBucket:
def __init__(self, rate: float, capacity: int):
self.rate = rate # tokens per second
self.capacity = capacity
self.tokens = capacity
self.last_update = datetime.now()
self._lock = asyncio.Lock()
async def acquire(self, tokens: int = 1) -> bool:
async with self._lock:
now = datetime.now()
# 添加 tokens
elapsed = (now - self.last_update).total_seconds()
self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)
self.last_update = now
if self.tokens >= tokens:
self.tokens -= tokens
return True
return False
class SlidingWindowRateLimiter:
def __init__(self, max_requests: int, window_seconds: int):
self.max_requests = max_requests
self.window_seconds = window_seconds
self._windows: Dict[str, deque] = {}
self._lock = asyncio.Lock()
async def is_allowed(self, key: str) -> bool:
async with self._lock:
now = datetime.now()
window_start = now - timedelta(seconds=self.window_seconds)
if key not in self._windows:
self._windows[key] = deque()
window = self._windows[key]
# 移除过期的请求
while window and window[0] < window_start:
window.popleft()
# 检查是否超限
if len(window) >= self.max_requests:
return False
# 记录新请求
window.append(now)
return True
# 使用
rate_limiter = SlidingWindowRateLimiter(max_requests=100, window_seconds=60)
async def handle_request(request_id: str):
if not await rate_limiter.is_allowed(request_id):
raise RateLimitExceeded()
return await process_request(request_id)
七、总结
后端架构设计的关键模式:
- 服务拆分:按业务能力或领域拆分,保持服务边界清晰
- 数据访问:使用仓储模式、UOW、CQRS 分离读写操作
- 消息通信:事件驱动、Saga 模式处理分布式事务
- 缓存策略:多级缓存、缓存穿透防护、缓存一致性
- 容错设计:断路器、重试、限流保护系统稳定
掌握这些模式,能帮助你构建高可用、可扩展的后端系统。
如果这篇文章对你有帮助,欢迎点赞收藏。