视频平台架构重构:从微服务到云原生

一、背景

一个典型的视频平台后端,原本采用 Spring Cloud Alibaba 微服务架构,包含 8 个 Java 服务、约 500 个 Java 文件。功能完整,但存在几个核心问题:

组件 当前实现 问题
消息队列 RocketMQ 换 MQ 必须改业务代码
服务调用 OpenFeign 只能 Java 调用 Java
服务发现 Nacos 弱设备无法运行
网关 Spring Cloud Gateway JVM 占用大,功能耦合

业务代码和基础设施强耦合,导致无法在弱设备部署、无法跨语言、无法切换实现。

此外还有代码质量问题:部分 Service 类超过 800 行、DTO 与 Entity 混用、异常处理不统一、测试覆盖不足。

已有亮点: 存储层已做抽象(StorageService → MinIO/Local 实现),说明抽象层思路已被验证可行。

二、重构思路:可插拔基础设施

设计目标

  1. 业务代码只依赖接口:不依赖具体实现

  2. 配置驱动:改配置就能切换实现

  3. 多实现:每个接口有轻量/企业级/测试多种实现

  4. 渐进迁移:一个服务一个服务切,可回滚

核心接口定义

ServiceDiscovery(服务发现):

go

复制代码
type ServiceDiscovery interface {
    Register(ctx context.Context, instance ServiceInstance) error
    Deregister(ctx context.Context) error
    Discover(ctx context.Context, serviceName string) ([]ServiceInstance, error)
    Watch(ctx context.Context, serviceName string) (<-chan []ServiceInstance, error)
}

实现:FileDiscovery(嵌入式单机)、EtcdDiscovery(K8s 标准)、NacosDiscovery(兼容现有)、MemoryDiscovery(单元测试)

MessageQueue(消息队列):

go

复制代码
type MessageQueue interface {
    Publish(ctx context.Context, topic string, msg Message) error
    Subscribe(ctx context.Context, topic string, group string) (<-chan Message, error)
    Ack(ctx context.Context, topic string, msg Message) error
}

实现:MemoryQueue(测试)、RedisStreamQueue(轻量)、NATSQueue(CNCF 标准)、RocketMQQueue(企业级兼容)

CacheStore(缓存):

go

复制代码
type CacheStore interface {
    Get(ctx context.Context, key string) ([]byte, error)
    Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
    Lock(ctx context.Context, key string, ttl time.Duration) (bool, error)
    Incr(ctx context.Context, key string, ttl time.Duration) (int64, error)
}

实现:MemoryCache(测试)、SQLiteCache(嵌入式持久化)、RedisCache(分布式)、BoltDBCache(嵌入式 KV)

ServiceCaller(服务间调用):

go

复制代码
type ServiceCaller interface {
    Call(ctx context.Context, target string, method string, req []byte) ([]byte, error)
    CallStream(ctx context.Context, target string, method string, req []byte) (<-chan []byte, error)
}

实现:MemoryCaller(测试)、HTTPClient(简单服务)、GRPCClient(跨语言标准)

配置驱动

yaml

复制代码
infrastructure:
  servicediscovery:
    type: etcd          # etcd / nacos / file / memory
    endpoints: ["http://localhost:2379"]
  messagequeue:
    type: redis-stream  # redis-stream / rocketmq / nats / memory
  cachestore:
    type: redis         # redis / sqlite / boltdb / memory
  servicecaller:
    type: grpc          # grpc / http / memory

切换环境只需改配置:

场景 配置组合
嵌入式设备 sqlite + memory + redis-stream
老旧服务器 sqlite + redis + file
云上生产环境 mysql + redis + etcd + rocketmq
单元测试 memory + memory + memory

三、无状态与高并发

无状态原则

服务不保存任何与请求绑定的状态,全部外置:

状态类型 存储位置
用户会话 Redis(JWT + 会话)
WebSocket 连接 Redis Pub/Sub(跨实例广播)
任务进度 Redis Stream
计数器 Redis
缓存 Redis
数据库 MySQL

WebSocket 跨实例广播

text

复制代码
客户端A ──WS──▶ realtime-1 ──┐
                              ├── Redis Pub/Sub ──▶ realtime-2 ──WS──▶ 客户端B
                              └──(弹幕/通知广播)

每个 realtime 实例订阅 Redis 主题,发消息只往 Redis Publish,所有实例收到后推给本地连接。实例增减不影响广播。

Redis Stream 作为消息队列

使用 Redis Stream 替代传统消息中间件,适合弱设备场景:

指标 Redis Stream RocketMQ
内存 复用 Redis 独立几百 MB
部署 已在跑 Redis 额外服务器
弱设备 可跑 不现实

核心用法:XADD(入队)、XREADGROUP(消费)、XACK(确认)、XCLAIM(认领超时任务)、XTRIM(清理已 ACK 消息)

四、技术选型

服务语言分配

服务 语言 原因
gateway Traefik(配置即用) K8s Gateway API 实现,不写代码
core Go 大量 CRUD + 缓存,Go 足够
realtime Go WebSocket 高并发,goroutine 天然适配
search Go Bleve 是 Go 库,天然集成
ads Go 轻量业务,Go 足够
media Java (GraalVM) 视频转码/AI 处理,Java 生态
store Java (GraalVM) 支付事务,Spring 生态

为什么混合语言

语言 优势 劣势
Go 单二进制、内存小、并发强 生态不如 Java 成熟
Java 生态全(支付/安全)、成熟 启动慢、内存大(GraalVM 缓解)

策略:在线轻量服务用 Go(跑盒子),复杂业务用 Java GraalVM(跑电脑)。

GraalVM 注意事项

  • Lombok 反射需要 reflect-config.json

  • FFmpeg/Whisper 用子进程调用,避免 JNI 反射配置

五、安全架构:零信任与网关职责分离

问题:旧做法把网关当万能工具

原网关承担了过多职责:路由转发、JWT 认证、三层授权、用户身份透传、CORS、异常处理。授权逻辑耦合在网关里,每次改权限都要改网关代码。

原则:网关不做业务层授权

text

复制代码
用户请求
    ↓
Traefik(网关)
  ├── JWT 验签(token 有效吗?)
  ├── 限流(请求太多吗?)
  ├── 路由(转发到哪个服务?)
  └── 透传原始 JWT(不注入 X-User-Id)
        ↓
各服务自己从 JWT 解析身份,自行判断权限

网关职责边界

网关应该做的事: JWT 验证、路由转发、限流、自动证书、CORS

网关不该做的事: 细粒度授权("video:manage 权限能不能删这个视频"------这是业务规则)、用户身份透传(下游服务自己从 JWT 解析更安全)

各服务自己认证

网关验证 JWT 有效性后,将原始 JWT 透传给下游。每个服务自己从 JWT 中解析用户身份,自行判断权限。

六、组件选型

组件 决定 替代掉 原因
服务发现 etcd Nacos K8s 底层就是 etcd,Raft 强一致
消息队列 NATS RocketMQ CNCF 孵化,Go 单二进制 ~20MB
缓存 Redis - 保留,老电脑内存管够
主数据库 MySQL - 保留,支付强一致
本地缓存 SQLite MongoDB 零依赖,文件型
服务调用 gRPC Feign CNCF 毕业,HTTP/2 + Protobuf,跨语言
网关 Traefik Spring Cloud Gateway K8s Gateway API 官方实现,~30MB
对象存储 MinIO 自建文件 S3 兼容,可迁移云 OSS
搜索 Bleve Elasticsearch Go 嵌入式,内存从 500MB 降到 50MB
任务调度 NATS JetStream XXL-Job 复用 MQ 消费组
监控 Prometheus + Grafana - CNCF 毕业
日志 Loki ELK CNCF 毕业,轻量
链路追踪 OpenTelemetry - CNCF 毕业

七、中间件汇总

组件 部署位置 内存
etcd 老电脑 ~50MB
Redis 老电脑 ~100MB
MySQL 老电脑 ~200MB
NATS 老电脑 ~20MB
MinIO 主力机 ~100MB
SQLite 每台设备 0(文件)
Bleve search 服务内 ~50MB
Traefik 盒子入口 ~30MB
Prometheus 老电脑/主力机 ~100MB
Loki 老电脑/主力机 ~50MB

全部基础设施内存合计:老电脑 ~520MB,盒子 ~230MB(含业务),1GB 盒子无压力。

八、对比总结

维度 旧架构 新架构
服务发现 Nacos(几百 MB) etcd(几十 MB)
消息队列 RocketMQ(几百 MB) NATS(几十 MB)
搜索 ES(500MB+) Bleve(几十 MB)
服务调用 Feign(Java only) gRPC(跨语言)
网关 Spring Cloud Gateway Traefik(K8s Gateway API)
语言 Java 全栈 Go + Java GraalVM
内存合计 2GB+ 老电脑 ~520MB,盒子 ~230MB
弱设备 不可行 可行
云迁移 绑定阿里云 标准云原生,可上 K8s

九、重构优先级

优先级 工作量 风险
P0 抽象 MessageQueue
P0 抽象 ServiceCaller
P0 抽象 ServiceDiscovery
P1 统一错误码/异常处理
P1 DTO/Entity 分层
P2 长类拆分
P2 硬编码配置化

策略:先抽接口(改动集中在注入点),确认编译通过且功能不变后再逐个替换实现。每个服务独立迁移,先支持配置切换(保持原实现),再逐步替换。

十、核心原则

  1. CNCF 标准优先:etcd、gRPC、NATS、Prometheus、Loki、OpenTelemetry

  2. K8s 生态对齐:Traefik(Gateway API)

  3. 数据集中:MySQL + Redis + etcd 放老电脑,好管

  4. 业务无状态:盒子随便扩缩,挂了换一个

  5. 抽象接口:所有组件可切换,不锁死

  6. 二进制化:Go 原生 + Java GraalVM

  7. 双模式部署:嵌入式(盒子)和企业级(云)都能跑

  8. 可观测性标配:没有监控的分布式系统等于盲人摸象

相关推荐
myy-learn12 小时前
27-进程通信
linux·服务器·网络
tryCbest13 小时前
Kubernetes(K8s)容器化部署
云原生·容器·kubernetes
疯狂打码的少年18 小时前
【数据库技术】关系模型基本概念(关系/属性/元组/键)
java·服务器·数据库·笔记
Henry-SAP18 小时前
AI突破重塑未来科技格局
人工智能·云原生·sap·erp
Mr数据杨20 小时前
【Codex】用部门管理模块维护组织架构与管理层级
架构·django·codex·项目开发
国医中兴20 小时前
电子病历的时序数据分析:ClickHouse在临床指标监控中的落地
微服务·云原生·容器·kubernetes·k8s
亚历克斯神21 小时前
低代码与 AI 的融合趋势——从可视化搭建到自然语言生成应用
java·spring·微服务
Capricorn198821 小时前
个人知识库接入大模型频现“幻觉引用”?排查 RAG 溯源失效问题,解析知芽构建可信第三大脑的底层架构
大数据·论文阅读·人工智能·笔记·架构·论文笔记
商业看点解说21 小时前
2026 桌面 Agent 选型指南:QoderWork、AiPy 与工程 Agent 的架构博弈
其他·架构