📘 新闻数据时间流系统设计说明书(v1.2)
一、系统概述
1.1 项目名称
News TimeStream Platform(新闻数据时间流平台)
1.2 项目定位
本系统是一个多数据源驱动的实时/准实时信息流处理与分析平台,提供:
- 多源新闻数据采集与入库
- 定时调度驱动的数据更新
- 数据分析与事件聚合
- 用户个性化信息流展示
1.3 核心目标
- 目标一:数据统一 — 将多个异构数据源统一为标准化新闻事件模型
- 目标二:时间流建模 — 以"时间"为核心维度构建信息流
- 目标三:用户产品化 — 提供可交互的前端信息流入口
二、整体系统架构
2.1 逻辑架构
┌────────────────────┐
│ Frontend │
│ (Web / Future App) │
└─────────┬──────────┘
↓
┌────────────────────┐
│ BFF Service │ ⭐ 编排层(规划中)
│ (Java Spring Boot)│
└────────┬───────────┘
↓
┌─────────────┴──────────────┐
↓ ↓
┌────────────────────┐ ┌────────────────────┐
│ Agora │ │ news-analytics │
│ (调度 + 入库 + │ │ (数据分析/聚合API) │
│ Web API + 认证) │ │ │
└────────┬───────────┘ └────────────────────┘
│ 主动拉取
↓
┌────────────────────┐
│ LatestNews │
│ (多源数据聚合服务) │
└────────────────────┘
架构要点:
- Agora 主动定时拉取 LatestNews,不是 LatestNews 推送
- BFF 不直接调用 LatestNews 和 Agora 后台调度接口
- Agora 内置用户认证能力(Keylo),不是独立服务
2.2 架构分层
| 层级 | 模块 | 职责 |
|---|---|---|
| 表现层 | Frontend | 信息流展示 |
| 编排层 | BFF | 数据聚合 + 用户上下文 |
| 分析层 | news-analytics | 数据处理与统计 API |
| 调度+存储层 | Agora | 定时拉取 + 数据入库 + Web API + 认证 |
| 数据源层 | LatestNews | 多源新闻数据聚合 |
三、核心系统说明
3.1 LatestNews(数据源系统)
语言:Node.js / TypeScript(已运行)
数据生产职责
- 多源新闻数据抓取(RSS / API / 爬虫)
- 原始数据结构化存储
- 对外暴露查询 API
核心 API
GET /api/s/ids → 返回所有数据源 ID 列表 ["zhihu","weibo",...]
GET /api/s?id={sourceId} → 返回单个数据源的新闻列表
输出数据结构
{
"id": "zhihu",
"name": "知乎",
"updatedTime": 1745000000,
"items": [{ "title": "...", "url": "..." }]
}
LatestNews 服务边界
- 只负责数据生产,不涉及业务展示逻辑
- 不持久化到业务数据库
3.2 Agora(调度 + 数据入库 + 认证平台)
语言:Rust(已运行)
GitHub 仓库:bruceblink/agora
实际职责
| 子模块 | 说明 |
|---|---|
| 定时调度 | cron 驱动的任务执行引擎 |
| 数据拉取 | 主动调用 LatestNews HTTP API |
| 数据入库 | 将新闻数据写入 PostgreSQL(news_info / news_item / news_keywords / news_event) |
| 数据触发 | 调用 news-analytics HTTP API 触发分析任务 |
| Web API | 对外提供 REST 接口 |
| 认证(Keylo) | 内置 OAuth2 / JWT / RBAC 认证能力 |
当前已注册的定时命令
| 命令 | cron | 说明 |
|---|---|---|
health_check | 每10分钟 | 保活 Render 上的 news-analytics 服务 |
fetch_all_news | 每小时整点 | 拉取 LatestNews 所有数据源写入 news_info |
extract_transform_news_info_to_item | 每10分钟(6-23点) | 触发 analytics 提取 news_item |
extract_keywords_to_news_keywords | 每30分钟(6-23点) | 触发 analytics 提取关键词 |
extract_news_event | 每30分钟(6-23点) | 触发 analytics 提取新闻事件 |
merge_cross_day_news_events | 每天凌晨1点 | 触发 analytics 合并跨天事件 |
fetch_all_news 执行流程
1. GET https://news.likanug.top/api/s/ids
→ 获取所有 sourceId 数组(约 60+ 个)
2. 并发 GET https://news.likanug.top/api/s?id={sourceId}
→ 解析为 NewsInfo { id, name, items }
3. upsert_news_info → PostgreSQL news_info 表
Agora 调度边界
- 不做爬虫,只调用 LatestNews HTTP API
- 通过 cron 调度驱动整个数据管线
3.3 news-analytics(分析系统)
语言:Python(已运行,部署于 Render)
数据分析职责
- 从数据库读取原始新闻(news_info)
- 数据清洗、热点分析、关键词提取、事件聚合
- 对外提供统一分析数据 API
被动触发模式
news-analytics 被 Agora 的定时任务 HTTP 调用触发,不主动轮询。
边界约束
- 不做 UI 适配逻辑
- 不做用户个性化逻辑
- 不直接与前端通信
3.4 Keylo(认证能力,内嵌于 Agora)
⚠️ 注意:Keylo 不是独立部署的服务,其认证能力内嵌在 Agora 中,共用同一个 PostgreSQL 数据库。
功能
- OAuth2 授权码流程(GitHub 等第三方登录)
- JWT Token 签发与校验
- RBAC 角色权限管理(admin / editor / user)
- 套餐权限管控(free / pro / enterprise)
对 BFF 的意义
BFF 通过调用 Agora 暴露的 /auth/* 端点完成鉴权,而不是调用独立的 Keylo 服务。
3.5 BFF(Backend For Frontend)⭐ 规划中
语言:Java Spring Boot
编排服务职责
- 面向前端的数据编排与裁剪
- 调用 news-analytics 获取处理后的数据
- 调用 Agora 认证端点完成用户鉴权
- 缓存优化(Redis)
- 多端适配(Web / App)
正确的内部调用链
Frontend
↓
BFF
├── Agora /auth/verify (JWT 校验,作为 middleware)
├── news-analytics /api/... (获取分析数据)
└── 聚合 + 裁剪 + 返回给 Frontend
注意:BFF 不直接调用 LatestNews(那是 Agora 的职责域)
核心接口
GET /api/feed → 个性化信息流
GET /api/user/profile → 用户信息
GET /api/user/subscriptions → 用户订阅
GET /api/stats/hot → 热点(透传 analytics)
GET /api/stats/trend → 趋势(透传 analytics)
Feed 响应示例
{
"items": [
{ "title": "...", "source": "zhihu", "publish_time": "...", "hot_score": 98 }
],
"page": 1,
"has_more": true
}
四、数据流设计
4.1 数据采集流(后台,已运行)
LatestNews(多源聚合)
↑ Agora cron 主动拉取(每小时)
│ GET /api/s/ids → 获取所有 sourceId
│ GET /api/s?id={id} × N(并发)
↓
Agora PostgreSQL(news_info 表)
↓ Agora cron 触发(HTTP POST)
news-analytics(提取 / 关键词 / 事件聚合)
↓ 写回
Agora PostgreSQL(news_item / news_keywords / news_event 表)
4.2 用户查询流(规划中)
Frontend
→ BFF(携带 JWT Token)
→ Agora /auth/verify(鉴权 middleware)
→ news-analytics /api/...(读取分析结果)
← BFF 聚合裁剪
← Frontend 展示
4.3 用户认证流
Frontend → Agora /auth/login(GitHub OAuth2)
→ 回调 → 签发 JWT
→ Frontend 持有 JWT
→ 后续请求携带 JWT → BFF → Agora 校验
五、接口设计规范
5.1 BFF Feed 接口
GET /api/feed?page=1&size=20
{
"items": [
{ "title": "...", "source": "zhihu", "publish_time": "...", "hot_score": 98 }
],
"page": 1,
"has_more": true
}
5.2 用户接口
GET /api/user/profileGET /api/user/subscriptions
5.3 分析接口(透传 analytics)
GET /api/stats/hotGET /api/stats/trend
六、关键设计原则
6.1 职责分离
| 模块 | 唯一职责 | 不允许 |
|---|---|---|
| LatestNews | 多源数据聚合,提供 API | 业务逻辑、写入业务库 |
| Agora | 定时拉取 + 入库 + 触发分析 + 认证 | 直接服务前端 UI |
| news-analytics | 数据分析处理,对外提供分析 API | UI 适配、用户个性化 |
| BFF | 编排聚合 + 前端适配 | 持久化业务数据、直接调用 LatestNews |
| Frontend | 展示 | 直接调用后端分析服务 |
6.2 数据流向单一
LatestNews → Agora → news-analytics,单向流动,不反向依赖。
6.3 BFF 不存数据
- ❌ 不持久化业务数据
- ✅ 只做聚合 + Redis 缓存
6.4 认证统一入口
所有认证由 Agora 内置的 Keylo 能力处理,BFF 作为校验调用方。
6.5 analytics 不做 UI 适配
严格保持数据层纯净性,UI 适配逻辑全部在 BFF 完成。
七、技术选型
后端
| 层 | 技术 | 状态 |
|---|---|---|
| BFF | Java Spring Boot | 规划中 |
| Agora(调度+入库+认证) | Rust | 运行中 |
| news-analytics | Python | 运行中(Render) |
| LatestNews | Node.js / TypeScript | 运行中 |
存储
| 存储 | 用途 |
|---|---|
| PostgreSQL | Agora 主库(新闻数据 + 用户 + RBAC) |
| Redis | BFF 缓存层(规划中) |
通信
- HTTP REST(主,现阶段全部服务间通信)
- 后续可扩展 gRPC(内部高频通信)
八、演进路线
Phase 1(当前优先)
Agora 与 LatestNews 已运行,本阶段聚焦 BFF 接入
- BFF 上线,接入现有 Agora 认证
- Feed 接口打通(对接 news-analytics)
- 基础前端页面
Phase 2
- 用户订阅系统
- 个性化 Feed 算法
Phase 3
- Redis 缓存层(BFF 层)
- 热点分析增强
Phase 4
- 实时推送(WebSocket)
Phase 5(高级)
- Kafka 事件流
- 推荐系统
九、系统边界总结
| 系统 | 只负责 | 不允许 |
|---|---|---|
| LatestNews | 数据生产(提供 API) | 业务逻辑、存储到业务库 |
| Agora | 定时拉取 + 入库 + 触发分析 + 认证 | 直接服务前端 UI |
| news-analytics | 数据加工与分析 API | UI 适配、用户个性化 |
| BFF | 编排聚合 + 前端适配 | 持久化业务数据、直接调用 LatestNews |
| Frontend | 展示 | 直接调用后端分析服务 |
十、一句话总结
本系统通过 Agora(Rust) 定时主动拉取 LatestNews(Node.js) 多源数据并入库,触发 news-analytics(Python) 完成数据加工,再通过 BFF(Java Spring Boot) 对前端统一编排,用户认证统一由 Agora 内置的 Keylo 能力提供。