Files
vibe_coding/.cursor/rules/references/017-architecture-deep.md
2026-03-05 21:27:11 +08:00

284 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 017-architecture.mdc (Deep Reference)
> 该文件为原始详细规范归档,供 Tier 3 按需读取。
---
# 🏗️ Million-Level Concurrency Architecture Standards
## 架构总览
```
┌──────────────┐
│ CDN/WAF │
└──────┬───────┘
┌────────────┴────────────┐
│ Nginx Cluster │
│ (负载均衡 + SSL + 静态) │
└────────────┬────────────┘
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Hyperf-1 │ │ Hyperf-2 │ │ Hyperf-N │
│ Swoole │ │ Swoole │ │ Swoole │
│ HTTP:9501│ │ HTTP:9501│ │ HTTP:9501│
│ WS:9502 │ │ WS:9502 │ │ WS:9502 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└───────┬───────┴───────┬───────┘
│ │
┌──────┴──────┐ ┌─────┴──────┐
│ Redis │ │ MySQL │
│ Cluster/ │ │ Master │
│ Sentinel │ │ ├─Slave 1 │
│ │ │ └─Slave 2 │
└─────────────┘ └────────────┘
```
## 无状态服务设计
所有 Hyperf 实例必须无状态,确保水平扩展:
| 状态类型 | 存储位置 | 禁止 |
|---------|---------|------|
| 用户 Session | Redis | 存储在内存/文件 |
| JWT Token | Redis (可验证+可吊销) | 仅本地验证 |
| 文件上传 | 对象存储 (S3/OSS) | 本地 storage/ |
| WebSocket 连接 | Redis 维护映射表 | 进程内变量 |
| 配置 | 配置中心 / env | 硬编码 |
## 缓存策略
### 多级缓存
```
L1: 进程内缓存 (APCu / Swoole Table) — 毫秒级, 容量小
L2: Redis 缓存 — 亚毫秒级, 容量中
L3: MySQL 查询 — 毫秒级, 容量大
```
### 缓存防护
| 问题 | 场景 | 解决方案 |
|------|------|---------|
| **穿透** | 查询不存在的数据 | 布隆过滤器 / 缓存空值 (TTL 30s) |
| **雪崩** | 大量缓存同时过期 | TTL 加随机抖动 / 预热 |
| **击穿** | 热点 Key 过期时大量请求 | 互斥锁 (singleflight) |
```php
// Cache-Aside with mutex lock
public function getOrderWithLock(int $id): ?ProductionOrder
{
$cacheKey = "order:{$id}";
$lockKey = "lock:order:{$id}";
$cached = $this->redis->get($cacheKey);
if ($cached !== false) {
return unserialize($cached);
}
// Mutex: only one coroutine queries DB
$lock = $this->redis->set($lockKey, '1', ['NX', 'EX' => 5]);
if ($lock) {
try {
$order = ProductionOrder::find($id);
$ttl = 300 + random_int(0, 60); // jitter
$this->redis->setex($cacheKey, $ttl, serialize($order));
return $order;
} finally {
$this->redis->del($lockKey);
}
}
// Wait and retry
Coroutine::sleep(0.05);
return $this->getOrderWithLock($id);
}
```
## 限流策略
### 令牌桶 (API 级别)
```php
use Hyperf\RateLimit\Annotation\RateLimit;
#[RateLimit(create: 1, capacity: 100, limitCallback: [RateLimitHandler::class, 'handle'])]
public function list(): array
{
// 每秒生成 1 个令牌,桶容量 100
}
```
### 滑动窗口 (用户级别)
```php
// Redis ZSET sliding window
public function isRateLimited(string $key, int $maxRequests, int $windowSeconds): bool
{
$now = microtime(true);
$windowStart = $now - $windowSeconds;
$pipe = $this->redis->pipeline();
$pipe->zremrangebyscore($key, '-inf', (string) $windowStart);
$pipe->zadd($key, [(string) $now => $now]);
$pipe->zcard($key);
$pipe->expire($key, $windowSeconds);
$results = $pipe->exec();
return $results[2] > $maxRequests;
}
```
## 消息队列削峰
```
高并发写入:
Client → API → Redis Queue (缓冲) → Consumer → MySQL
适用场景:
- 订单创建 (削峰)
- 通知发送 (异步)
- 日志记录 (解耦)
- 数据统计 (批处理)
```
## 服务降级与熔断
```php
// 降级策略
class OrderService
{
public function getStatistics(int $orderId): array
{
try {
return $this->doGetStatistics($orderId);
} catch (\Throwable $e) {
// Fallback: return cached/default data
return $this->getCachedStatistics($orderId) ?? self::DEFAULT_STATS;
}
}
}
// 熔断器模式
// Circuit Breaker: CLOSED → OPEN → HALF-OPEN → CLOSED
// Use hyperf/circuit-breaker component
```
## 数据库扩展策略
### 垂直拆分 (按业务域)
```
production_db → 订单、子订单、发货
permission_db → 用户、角色、权限
notification_db → 通知、消息
```
### 水平分片 (百万级后)
```
分片键: order_id
分片策略: order_id % shard_count
路由层: Hyperf 中间层 或 ProxySQL
注意: 跨分片查询需要聚合层
```
## 部署扩展清单
| 阶段 | QPS | 架构 |
|------|-----|------|
| 起步 | < 1K | 单机 Docker Compose |
| 成长 | 1K ~ 10K | Nginx + 2~4 Hyperf + MySQL主从 + Redis Sentinel |
| 规模 | 10K ~ 100K | K8s + HPA + MySQL Cluster + Redis Cluster |
| 百万 | 100K+ | 微服务拆分 + 消息队列 + 分库分表 + CDN |
## 模块通信规范
> 与 `019-modular.mdc` 互补,本节侧重**跨服务/跨进程**通信019 侧重**代码内模块边界**。
### 通信方式选择矩阵
| 场景 | 推荐方式 | 禁止方式 |
|------|---------|---------|
| 同进程同步调用 | 依赖注入 + 接口 | 全局静态方法 |
| 跨进程异步 | AsyncQueue / RabbitMQ | 轮询 DB |
| 实时推送 | WebSocket + Redis Pub/Sub | HTTP 长轮询 |
| 定时任务 | Hyperf Crontab | sleep 循环 |
| 跨服务数据 | REST API / 共享 Redis | 直连对方 DB |
### 前端模块通信规范
```
组件间通信优先级(由低到高耦合):
1. Props & Emits父子 — 首选
2. provide/inject跨层级 — 适合主题/配置
3. Pinia Store状态共享 — 跨模块全局状态
4. EventBus (mitt) — 非父子一次性事件(慎用)
5. URL / Query Params — 页面级状态持久化
```
```typescript
// ✅ 推荐:通过 Pinia 跨模块共享状态
// stores/notification.ts
export const useNotificationStore = defineStore('notification', () => {
const unreadCount = ref(0)
const messages = ref<Notification[]>([])
function addNotification(msg: Notification): void {
messages.value.unshift(msg)
unreadCount.value++
}
return { unreadCount, messages, addNotification }
})
// 订单模块使用通知(无直接耦合)
// views/order/composables/useOrderActions.ts
const notificationStore = useNotificationStore()
async function createOrder(data: OrderCreateForm): Promise<void> {
const order = await OrderApi.create(data)
// 通过 Store 通知,不直接调用通知组件
notificationStore.addNotification({
type: 'success',
title: '订单创建成功',
content: `订单号 ${order.orderNo} 已提交`,
})
}
```
### WebSocket 模块通信
```typescript
// src/composables/useWebSocket.ts — 全局单例 WebSocket 管理
// 所有模块订阅自己关心的消息类型,不感知连接细节
export const wsClient = useWebSocket()
// 订单模块:只监听订单相关消息
const { on, off } = useWebSocket()
on('order.status_changed', (payload) => {
orderStore.updateOrderStatus(payload.orderId, payload.status)
})
// 通知模块:只监听通知消息
on('notification.new', (payload) => {
notificationStore.addNotification(payload)
})
```
## 性能基线
| 指标 | 目标值 | 监控方式 |
|------|--------|---------|
| API P99 延迟 | < 200ms | Prometheus + Grafana |
| 数据库查询 | < 50ms | 慢查询日志 |
| Redis 命令 | < 5ms | Redis INFO |
| 缓存命中率 | > 85% | 自定义指标 |
| 错误率 | < 0.1% | Sentry / 日志 |
| 可用性 | 99.9% | 健康检查 + 告警 |