DESIGN.md@backend_massive_concurrent/docs · git:20260617.47f66a5 · 2026-06-17 · sha256 59af7d59962a5e08

DESIGN.md@backend_massive_concurrent/docs git:20260617.47f66a5A

Immutable. This exact content never changes and is served at /api/v1/blob/59af7d59962a5e08.

# 架构设计文档

> backend_massive_concurrent — 高并发数据引擎

---

## 一、项目目标

| 目标              | 指标                          |
| ----------------- | ----------------------------- |
| 批量抓取吞吐      | ≥ 500 URL/s(网络不限速场景) |
| 聚合查询 P99 延迟 | ≤ 上游最慢接口延迟 + 10ms     |
| 文件事件响应延迟  | ≤ 300ms(含防抖)             |
| 内存占用          | 万级并发任务下 < 500 MB       |

---

## 二、模块划分

### 2.1 数据抓取 (`internal/scraper`)

**核心问题**:大量 URL 需要并发抓取,但必须避免打爆下游或本机资源。

**方案:Worker Pool + 令牌桶**

```
                   ┌─────────────────────────────┐
 输入 URL 列表 ──▶  │  Dispatcher(带缓冲 channel) │
                   └──────────┬──────────────────┘
                              │  分发任务
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
         Worker #1       Worker #2  ...  Worker #N
              │               │               │
        RateLimiter ──── 令牌桶(全局共享)────
              │
         http.Client(带超时 & 重试)
              │
         Result Channel
              │
              ▼
         ResultCollector(写入 DB / 内存缓存)
```

**关键设计决策**:

- Worker 数量从 `configs.scraper.worker_pool_size` 读取,运行时可通过 API 动态调整
- 每个 Worker 从 `jobs chan Job` 消费,实现背压(back-pressure)
- `RateLimiter` 使用 `golang.org/x/time/rate`,令牌桶算法,全局共享,防止超速
- HTTP Client 使用自定义 `Transport`,启用连接池(`MaxIdleConnsPerHost`)
- 重试使用指数退避 + jitter,避免惊群效应
- 任务状态机:`pending → running → done | failed`,通过 `sync.Map` 跟踪

**文件**:

```
internal/scraper/
├── dispatcher.go   # 任务分发,管理 worker pool 生命周期
├── worker.go       # 单个 worker,负责 HTTP 抓取
├── job.go          # Job 结构体,任务状态机
├── result.go       # Result 结构体,收集器
└── scraper.go      # 对外暴露的 Scraper 接口
```

---

### 2.2 文件系统监控 (`internal/watcher`)

**核心问题**:fsnotify 原始事件频率高(编辑器保存一次可触发 5+ 事件),需要防抖聚合;同时支持多目录、递归监控、文件类型过滤。

**方案:fsnotify + Debouncer + Event Bus**

```
 inotify / kqueue / FSEvents
         │
         ▼
   fsnotify.Watcher
         │  原始事件(高频)
         ▼
   Debouncer(按路径分组,time.AfterFunc 防抖)
         │  聚合后事件(低频)
         ▼
   Filter(glob 规则匹配)
         │  通过的事件
         ▼
   Event Bus(chan WatchEvent,带缓冲)
         │
    ┌────┴────┐
    ▼         ▼
  SSE 推送  内部订阅者(如触发重新索引)
```

**关键设计决策**:

- 递归监控通过 `filepath.Walk` 初始化时注册所有子目录,并在 `CREATE` 事件中动态添加新目录
- 防抖时间窗口可配置(默认 200ms),同一路径在窗口内的多次事件合并为一次
- 事件类型归一化为 `CREATE | MODIFY | DELETE | RENAME`
- 通过 `context.Context` 控制生命周期,`Stop()` 后 channel 关闭,订阅者自动退出

**文件**:

```
internal/watcher/
├── watcher.go      # 顶层 Watcher,管理多个目录
├── debouncer.go    # 事件防抖器
├── filter.go       # glob 过滤规则
└── event.go        # WatchEvent 类型定义
```

---

### 2.3 聚合查询 (`internal/aggregator`)

**核心问题**:单次业务查询需要同时请求多个上游接口(如:同时查图片生成状态 + 视频生成状态 + 知识库状态),串行太慢,需要并行 Fan-out + 超时控制。

**方案:errgroup + context 超时**

```
POST /aggregate
  body: { targets: [URL_A, URL_B, URL_C], timeout: "3s" }
        │
        ▼
  Aggregator.Query(ctx, targets)
        │
        ├── go fetch(ctx, URL_A) ──▶ result chan
        ├── go fetch(ctx, URL_B) ──▶ result chan
        └── go fetch(ctx, URL_C) ──▶ result chan
                                         │
                                   WithTimeout ctx
                                         │
                                    等待所有完成
                                    或 ctx 超时
                                         │
                                         ▼
                                   合并响应返回
```

**关键设计决策**:

- 使用 `golang.org/x/sync/errgroup` 管理并发 goroutine,自动传播 cancel
- `fail_fast: true` 时任意上游报错即通过 `cancel()` 中止其他请求(errgroup.WithContext)
- `fail_fast: false` 时收集所有结果,部分失败在响应中标记 `"status": "error"`
- 响应结果附带每个上游的耗时,便于排查慢接口
- 内置缓存(`pkg/cache`),相同 target 在 TTL 内命中缓存,不重复请求上游

**文件**:

```
internal/aggregator/
├── aggregator.go   # 对外接口,Query() 方法
├── fetcher.go      # 单个上游 HTTP 请求封装
└── result.go       # AggregateResult 结构体
```

---

### 2.4 公共包 (`pkg/`)

| 包              | 职责                                                       |
| --------------- | ---------------------------------------------------------- |
| `pkg/pool`      | 通用 goroutine worker pool,可复用于 scraper 和 aggregator |
| `pkg/ratelimit` | 令牌桶限流,封装 `golang.org/x/time/rate`                  |
| `pkg/cache`     | 轻量内存缓存,`sync.Map` + TTL 清理 goroutine              |

---

## 三、HTTP 层 (`internal/server`)

使用标准库 `net/http` + `chi` 路由(轻量,兼容标准 Handler 接口)。

**中间件链**:

```
请求 ──▶ Recovery ──▶ RequestID ──▶ Logger ──▶ RateLimit ──▶ Handler
```

**SSE 推送**(文件变更事件):

```go
// GET /watch/events
// 客户端保持长连接,服务端通过 WatchEvent channel 持续推送
w.Header().Set("Content-Type", "text/event-stream")
for event := range eventBus {
    fmt.Fprintf(w, "data: %s\n\n", event.JSON())
    flusher.Flush()
}
```

---

## 四、配置与启动流程

```
main()
  │
  ├── 加载 configs/config.yaml(viper)
  ├── 初始化 logger(zap,结构化日志)
  ├── 启动 Watcher(注册目录,开始监听)
  ├── 启动 Scraper worker pool
  ├── 初始化 Aggregator(注入 cache & fetcher)
  ├── 注册 HTTP 路由
  └── http.ListenAndServe(graceful shutdown via signal)
```

**优雅关闭**:捕获 `SIGINT` / `SIGTERM`,先停止接收新请求,等待 in-flight 请求完成(最长 30s),再关闭 Watcher 和 worker pool。

---

## 五、技术选型

| 组件     | 选型                         | 理由                                               |
| -------- | ---------------------------- | -------------------------------------------------- |
| 路由     | `go-chi/chi`                 | 轻量,零依赖,兼容标准接口                         |
| 文件监控 | `fsnotify/fsnotify`          | 跨平台(Linux inotify / macOS FSEvents / Windows) |
| 并发控制 | `golang.org/x/sync/errgroup` | 官方,简洁,支持 context 传播                      |
| 限流     | `golang.org/x/time/rate`     | 官方令牌桶,线程安全                               |
| 配置     | `spf13/viper`                | 支持 yaml / env / 热重载                           |
| 日志     | `uber-go/zap`                | 高性能结构化日志,零分配                           |
| 测试     | `testify` + `httptest`       | 标准化断言,HTTP mock                              |

---

## 六、开发计划

### Phase 1 — 基础骨架(1周)

- [ ] 项目结构初始化,`go.mod`
- [ ] `pkg/pool`:通用 worker pool
- [ ] `pkg/ratelimit`:令牌桶封装
- [ ] `internal/server`:基础 HTTP 框架 + 健康检查

### Phase 2 — 核心功能(2周)

- [ ] `internal/scraper`:Worker pool + 抓取 + 状态跟踪
- [ ] `internal/watcher`:fsnotify + 防抖 + 过滤 + SSE 推送
- [ ] `internal/aggregator`:Fan-out / Fan-in + 缓存

### Phase 3 — 生产加固(1周)

- [ ] 集成测试覆盖三个模块
- [ ] Prometheus metrics 暴露(`/metrics`)
- [ ] `configs/config.yaml` 完善 + 文档
- [ ] Docker 镜像 + `docker-compose.yml`
- [ ] Graceful shutdown 验证

---

## 七、性能基准目标(Benchmark)

```bash
go test -bench=. -benchmem ./...
```

| 测试                            | 目标                                |
| ------------------------------- | ----------------------------------- |
| `BenchmarkWorkerPool`           | 10万任务入队/出队 < 100ms           |
| `BenchmarkRateLimiter`          | 并发 1000 goroutine 取令牌无锁争用  |
| `BenchmarkAggregator_10Targets` | 10个上游 50ms 返回,聚合耗时 < 60ms |
| `BenchmarkDebouncer`            | 1万事件经防抖后输出数 ≤ 目录数 × 2  |