1. 项目概述

本系统是一个 Web 爬虫监控平台,提供爬虫任务调度、数据采集记录管理、实时监控看板以及告警规则管理能力。系统由两部分组成:Next.js 前端控制台Bun 爬虫调度微服务,通过 Caddy 反向代理统一对外暴露服务。
在这里插入图片描述

1.1 核心能力

  • 多爬虫任务的创建、启停、触发与删除
  • 爬取记录的浏览、预览、源码查看与下载
  • 实时指标看板(请求量、成功率、响应时间、状态码分布、按小时/爬虫类型统计)
  • 可配置的告警规则引擎(成功率、错误数、响应时间阈值)
  • 爬虫调度器按指定频率自动执行爬取任务
  • 种子数据自动初始化,开箱即用

1.2 技术栈

层级 技术选型
前端框架 Next.js 16 (React 19, TypeScript)
UI 组件库 shadcn/ui (Radix UI)
样式方案 Tailwind CSS 4
图表库 Recharts
前端状态管理 React Hooks + Zustand
后端微服务运行时 Bun
ORM Prisma 6
数据库 SQLite (file-based)
反向代理 Caddy
构建工具 Bun (bundler)

2. 系统架构

2.1 整体架构图

┌──────────────────────────────────────────────────────────────┐
│                       Caddy (:81)                            │
│                    Reverse Proxy                              │
│         ┌─────────────────────┬─────────────────────┐        │
│         │                     │                     │        │
│   ┌─────▼──────┐      ┌──────▼──────┐              │        │
│   │  Next.js   │      │  Crawler    │              │        │
│   │  Frontend  │      │  Scheduler  │              │        │
│   │  (Port     │      │  Mini-      │              │        │
│   │   3000)    │      │  Service    │              │        │
│   │            │      │  (Port 3002)│              │        │
│   └─────┬──────┘      └──────┬──────┘              │        │
│         │                    │                     │        │
│         │         ┌──────────▼──────────┐          │        │
│         │         │    SQLite           │          │        │
│         └────────►   (custom.db)        ◄─────────┘        │
│                   └─────────────────────┘                   │
└──────────────────────────────────────────────────────────────┘

2.2 部署架构

系统采用 双进程 + 反向代理 模式部署:

  • Next.js Standalone Server (next-service-dist/server.js):服务前端页面与 API 路由,端口 3000
  • Crawler Scheduler Mini-Service (mini-services-dist/ 下的构建产物):爬虫调度引擎,端口 3002
  • Caddy:监听 81 端口,根据 XTransformPort 查询参数或默认路由转发请求
  • SQLite 数据库:两进程共享同一数据库文件

3. 模块设计

3.1 前端模块

前端基于 Next.js App Router,使用单页面 Tab 架构组织功能。

3.1.1 页面路由
路径 组件 说明
/ page.tsx 主入口,包含四个 Tab
3.1.2 Tab 模块
Tab 组件 功能描述
Dashboard KPICards + HourlyChart + SpiderChart + StatusPieChart + RecentErrors KPI 指标卡片(总请求数、成功率、活跃任务数、平均响应时间),按小时请求趋势、按爬虫类型统计、HTTP 状态码分布、最近错误列表
Tasks TasksTab 任务列表展示、创建/编辑/删除任务、启动/暂停、手动触发爬取
Records RecordsTab 分页记录列表、按任务筛选、记录详情 Sheet(元数据 + HTML 预览 iframe + 源码查看/复制/下载/新标签页打开)
Monitoring MonitoringTab 日志子 Tab(按任务/级别筛选) + 告警子 Tab(告警列表、告警规则 CRUD、启用/禁用)
3.1.3 自定义 Hook:useCrawlerAPI

封装所有前后端交互逻辑,提供统一的 API 调用接口和自动刷新机制:

  • 自动刷新:每 10 秒轮询 /api/metrics/api/tasks/api/alerts/api/alert-rules
  • 任务操作createTask / updateTask / deleteTask / triggerTask
  • 记录查询fetchRecords(taskId?, page, limit) — 含分页转换
  • 日志查询fetchLogs(taskId?, level?, limit)
  • 告警规则操作createAlertRule / updateAlertRule / deleteAlertRule
3.1.4 UI 组件库

基于 shadcn/ui 体系,核心使用的组件包括:

ButtonCardTabsTableDialogSheetSelectSwitchBadgeSkeletonTooltipSeparatorToast / Toaster

图表组件基于 Recharts:

  • HourlyChartBarChart(堆叠柱状图,成功/失败分层)
  • SpiderChartBarChart(横向柱状图,按爬虫名称统计)
  • StatusPieChartPieChart(环形图,HTTP 状态码分布)

3.2 后端模块(Crawler Scheduler)

爬虫调度微服务是一个独立的 Bun HTTP 服务,运行在端口 3002,主要承担三部分职责:HTTP API爬虫调度告警评估

3.2.1 启动流程
start()
  ├── seedDatabase()        ← 首次运行填充种子数据
  ├── Bun.serve()            ← 启动 HTTP 服务 (port 3002)
  ├── setInterval(30s)       ← 启动调度循环
  ├── runSchedulerCycle()    ← 立即执行首个调度周期
  └── await new Promise()    ← 保持进程存活
3.2.2 HTTP API 路由表
方法 路径 处理函数 说明
GET / handleHealthCheck 健康检查,返回运行状态和已运行时长
GET /api/tasks handleListTasks 获取所有任务(含记录/日志计数)
POST /api/tasks handleCreateTask 创建新任务
PATCH /api/tasks/:id handleUpdateTask 更新任务
DELETE /api/tasks/:id handleDeleteTask 删除任务(级联删除记录和日志)
POST /api/tasks/:id/trigger handleTriggerTask 手动触发一次爬取
GET /api/records handleListRecords 分页查询爬取记录
GET /api/records/:id handleGetRecord 获取单条记录详情(含 rawHtml)
GET /api/records/:id/download handleDownloadRecord 下载爬取结果的 HTML 文件
GET /api/logs handleListLogs 查询日志(支持 taskId/level 过滤)
GET /api/metrics handleGetMetrics 获取聚合指标数据
GET /api/alerts handleListAlerts 查询告警列表
GET /api/alert-rules handleListAlertRules 获取告警规则列表
POST /api/alert-rules handleCreateAlertRule 创建告警规则
PATCH /api/alert-rules/:id handleUpdateAlertRule 更新告警规则
DELETE /api/alert-rules/:id handleDeleteAlertRule 删除告警规则
3.2.3 爬虫调度引擎
// 调度循环 (每隔 30 秒执行一次)
async function runSchedulerCycle() {
  // 1. 查询所有 active 状态的任务
  const activeTasks = await db.crawlTask.findMany({ where: { status: "active" } });
  
  // 2. 逐个执行爬取
  for (const task of activeTasks) {
    await executeCrawl(task);
  }
  
  // 3. 执行告警评估
  await evaluateAlertRules();
}

executeCrawl 执行流程:

  1. 调用 simulateCrawl(task) 获取模拟爬取结果
  2. 写入 CrawlRecord 记录
  3. 写入 CrawlLog 日志
  4. 更新任务的 lastRunAtlastStatus
3.2.4 爬取模拟器

simulateCrawl 基于概率分布模拟真实爬取行为:

场景 概率 状态码 响应时间 日志级别
成功 85% 200 0.1s ~ 3s(90%)或 5s ~ 15s(10%) info
禁止访问 8% 403 正常分布 warning
超时 5% 0(超时标记) 正常分布 error
其他错误 2% 400 ~ 599 正常分布 error

成功爬取时,根据爬虫类型(spiderName)生成对应风格的 HTML 模板内容,包含:

  • default_spider — 通用网页
  • tech_news_spider — 科技新闻文章
  • ecommerce_spider — 电商产品页(含价格、评分、规格)
  • social_spider — 社交媒体帖子(含头像、互动数据)
  • blog_spider — 技术博客(含目录、代码块、作者信息)
  • docs_spider — API 文档(含侧边栏、端点表格)
3.2.5 告警评估引擎

evaluateAlertRules 在每个调度周期末尾执行:

  1. 查询所有启用的告警规则
  2. 统计最近 30 分钟的爬取记录,计算成功率、错误数、平均响应时间
  3. 逐条匹配规则条件(lt / gt / eq)
  4. 触发告警时检查 5 分钟内是否有相同规则的 firing 告警,避免重复
3.2.6 进程管理

manager.ts 负责守护 crawler-scheduler 主进程:

  • 通过 spawn 启动子进程
  • 将子进程的输出转发到标准输出并写入日志文件 /tmp/crawler-scheduler.log
  • 子进程退出时等待 3 秒后退出自身,由 start.sh wrapper 重新拉起

4. 数据模型设计

4.1 ER 关系图

CrawlTask (1) ──┬── (N) CrawlRecord
                │
                └── (N) CrawlLog

AlertRule (1) ──── (N) Alert

4.2 CrawlTask(爬虫任务)

字段 类型 约束 说明
id String (CUID) PK 主键
name String NOT NULL 任务名称
url String NOT NULL 目标 URL
cronExpr String 默认 “*/30 * * * *” Cron 表达式
status String 默认 “active” active / paused / error
spiderName String 默认 “default_spider” 爬虫类型标识
concurrency Int 默认 1 并发数
timeout Int 默认 15 超时时间(秒)
lastRunAt DateTime? - 最近一次执行时间
nextRunAt DateTime? - 下一次计划执行时间
lastStatus String? - 最近一次执行结果
createdAt DateTime 默认 now() 创建时间
updatedAt DateTime 自动更新 更新时间

在这里插入图片描述

4.3 CrawlRecord(爬取记录)

字段 类型 约束 说明
id String (CUID) PK 主键
taskId String FK → CrawlTask, ON DELETE CASCADE 关联任务
url String NOT NULL 被抓取 URL
title String? - 页面标题
contentHash String? INDEX 内容哈希值
statusCode Int? - HTTP 状态码
duration Float? - 耗时(秒)
rawHtml String? - 原始 HTML 内容
isNew Boolean 默认 true 是否为新内容
crawledAt DateTime 默认 now() 爬取时间

索引:taskIdcontentHash

在这里插入图片描述

4.4 CrawlLog(爬取日志)

字段 类型 约束 说明
id String (CUID) PK 主键
taskId String FK → CrawlTask, ON DELETE CASCADE 关联任务
level String 默认 “info” info / warning / error
message String NOT NULL 日志消息
errorType String? - 错误类型
url String? - 目标 URL
duration Float? - 耗时(秒)
statusCode Int? - HTTP 状态码
createdAt DateTime 默认 now() 创建时间

索引:taskIdlevel
在这里插入图片描述

4.5 AlertRule(告警规则)

字段 类型 约束 说明
id String (CUID) PK 主键
name String NOT NULL 规则名称
metric String NOT NULL 指标:success_rate / error_count / response_time
condition String NOT NULL 条件:lt / gt / eq
threshold Float NOT NULL 阈值
duration Int 默认 300 评估窗口(秒)
severity String 默认 “warning” critical / warning / info
enabled Boolean 默认 true 是否启用
createdAt DateTime 默认 now() 创建时间
updatedAt DateTime 自动更新 更新时间

4.6 Alert(告警记录)

字段 类型 约束 说明
id String (CUID) PK 主键
ruleId String FK → AlertRule 关联规则
message String NOT NULL 告警消息
severity String 默认 “warning” 严重程度
status String 默认 “firing” firing / resolved
value Float? - 触发值
triggeredAt DateTime 默认 now() 触发时间
resolvedAt DateTime? - 解决时间

索引:ruleIdstatus


5. 反向代理设计

系统使用 Caddy 作为反向代理,监听 81 端口,支持两种路由模式:

5.1 默认路由

未携带 XTransformPort 查询参数时,请求转发到 Next.js(端口 3000),并携带原始请求头(Host、X-Forwarded-For、X-Forwarded-Proto、X-Real-IP)。

5.2 动态端口路由

携带 XTransformPort 参数时(如 ?XTransformPort=3002),请求转发到对应端口的 localhost 服务。此机制用于开发调试时灵活切换后端目标。


6. 种子数据

系统首次启动时自动执行 seedDatabase(),填充以下种子数据:

6.1 示例任务(5 个)

任务名称 URL Cron 爬虫类型 默认状态
Tech News Crawler https://news.example.com */15 * * * * tech_news_spider active
E-Commerce Products https://shop.example.com/products */30 * * * * ecommerce_spider active
Social Media Feed https://social.example.com/feed */5 * * * * social_spider active
Blog Articles https://blog.example.com 0 * * * * blog_spider paused
API Documentation https://docs.example.com 0 */2 * * * docs_spider active

6.2 告警规则(3 条)

规则名称 指标 条件 阈值 严重程度
Success Rate Alert success_rate lt 80 critical
Error Spike Alert error_count gt 10 warning
Slow Response Alert response_time gt 5 warning

6.3 历史数据

  • 50 条爬取记录(CrawlRecord),时间随机分布在过去 24 小时内
  • 30 条爬取日志(CrawlLog),时间随机分布在过去 24 小时内

7. 构建与部署流程

7.1 构建流程(build.sh)

1. bun install                        → 安装 Node 依赖
2. bun run build                      → Next.js standalone 构建
3. mini-services-install.sh           → 微服务依赖安装
4. mini-services-build.sh             → 微服务 bun build 打包
5. 收集产物到临时目录
   ├── next-service-dist/             → Next.js standalone 输出
   ├── mini-services-dist/            → 微服务构建产物
   ├── db/custom.db                   → SQLite 数据库
   ├── Caddyfile                      → Caddy 配置
   ├── start.sh                       → 生产启动脚本
   └── mini-services-start.sh         → 微服务启动脚本
6. tar -czf 打包为 .tar.gz

7.2 启动流程(start.sh)

1. 设置环境变量(PORT, HOSTNAME, DATABASE_URL)
2. 启动 Next.js 服务    → bun server.js (port 3000)
3. 启动 mini-services    → sh mini-services-start.sh
4. 启动 Caddy 反向代理   → caddy run (port 81, 前台运行)

7.3 微服务启动流程(mini-services-start.sh)

扫描 mini-services-dist/ 目录下的 mini-service-*.js 文件,逐个通过 bun 启动为后台进程。

7.4 进程守护机制

crawler-scheduler 采用三层守护:

start.sh (wrapper)
  └── while true; bun manager.ts
        └── spawn('bun', ['index.ts'])
  • 内层 index.ts 崩溃 → manager.ts 检测到 exit,3 秒后退出
  • manager.ts 退出 → start.sh 检测到退出码,2 秒后重新拉起
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐