1. 对于一个系统的接口层应该如何设计

数据校验与安全认证

严格校验入参(类型、长度、格式、合法取值),防止 SQL 注入和非法业务逻辑。

强制使用 HTTPS,采用 JWT 或 OAuth2.0 进行身份鉴权,并对敏感信息进行脱敏处理。

异步处理与可观测性

针对耗时长的非核心接口(如发送邮件、统计),采用 消息队列(MQ) 削峰填谷,立即返回“处理中”。

完备的日志(TraceId)和监控指标(QPS、RT、错误率),确保出问题时能快速定位。

应对接口泄漏与大量恶意请求

限流

接口层应当在网关层实现限流,在网关层设置阈值,过滤掉超额流量。

多维度限流: 不要只针对全局,要针对 IP、用户ID、API 路径 进行多重限制。

常用算法: 令牌桶(Token Bucket): 允许一定程度的突发流量。

  • 漏桶(Leaky Bucket): 强制平滑流量,由于请求流出速率恒定,适合保护后续数据库。

黑白名单与封禁

动态黑名单: 配合监控系统,如果某个 IP 在短时间内触发了大量的 404 或限流错误,自动将其加入 Redis 黑名单封禁一段时间。

WAF(Web 应用防火墙): 在接入层(如 Nginx/Cloudflare)阻断常见的攻击向量。

接口隐藏与动态化

URL 签名: 请求必须携带由私钥生成的 Signature,即使 URL 泄漏,攻击者无法伪造签名也无法调用。

接口动态化: 针对抢购等高危接口,URL 后缀可以加上由后端下发的随机 Hash 值,且具有时效性。

幂等性设计(用户重复点击、网络抖动)

前端防抖

点击按钮后置灰(Loading 状态),防止用户物理层面的连续点击。但这只是辅助,不能作为唯一手段。

后端幂等令牌

获取 Token: 进入页面时,前端向后端申请一个唯一的 UUID(Token)。

携带提交: 提交表单时在 Header 中携带此 Token。

校验逻辑:后端使用 Redis 的 SETNX 命令:SET key value NX EX 3600

  • 如果设置成功,说明是第一次请求,正常执行业务。

  • 如果设置失败,说明是重复请求,直接返回“请勿重复提交”。

应对接口雪崩

如果后端业务逻辑执行慢,大量请求积压在接口层,会导致整个连接池耗尽。

  • 超时控制(Timeout): 设置合理的接口超时时间(如 3s),防止慢请求拖死线程池。

  • 熔断与降级(Circuit Breaker): 如果某个下游服务(如积分服务)持续报错,接口层应开启熔断,直接返回友好提示或默认值,不再调用下游。

  • 隔离策略(Bulkhead): 为核心业务接口分配独立的线程池,防止非核心接口的流量爆发影响核心业务。

2. 如何设计一个百万级QPS的接口

流量削峰与分层过滤

在百万级流量下,保护后端核心资源(如数据库)是第一优先级。

  • 多级限流: * 接入层: 在 Nginx 或云网关(API Gateway)利用漏桶或令牌桶算法,丢弃非正常频率的请求。

    • 应用层: 使用 Sentinel 或 Hystrix 对具体的接口、方法进行集群限流。

  • 黑白名单与风控: 尽早拦截无效流量(如机器人、爬虫)。

  • 请求合并: 将短时间内的大量同类读请求,在网关层合并为一个请求去访问底层服务,减少网络开销。

合理设计缓存(数据下沉)

百万 QPS 下,任何请求直接打到数据库都会瞬间造成系统崩溃。

  • 多级缓存:

    1. 本地缓存: 使用 Caffeine 或 Guava Cache 缓存极热点数据,避免 Redis 的网络 IO 瓶颈。

    2. 分布式缓存: Redis 集群需采用分片(Sharding)架构,并配合多副本读写分离。

  • 解决热点 Key 与缓存击穿:

    • 热点探测: 实时监控高频访问 Key,动态将其推送到本地内存。

    • 缓存预热: 流量洪峰到达前,提前加载数据。

  • 数据压缩: 尽量缩减缓存 Value 的大小(如使用 Protobuf 替代 JSON),节省带宽。

极速接入层与弹性架构

单机承载能力有限,必须通过水平扩展和优化底层协议来应对流量。

  • 无状态化: 保证应用节点不存储 Session 等状态,以便随时进行秒级水平扩容。

  • 高性能网关: 采用 OpenResty、Go 或基于 Netty 的 Java 网关,利用非阻塞 IO 处理海量连接。

  • 负载均衡策略: 使用四层负载均衡(LVS/DPDK)配合七层负载均衡(Nginx),分担解析压力。

  • 长连接维护: 适当调大连接池,减少 TCP 三次握手的开销。

异步化与解耦

对于非强一致性的操作,必须遵循“先响应,后处理”的原则。

  • 消息队列(MQ): * 将写操作(如发券、日志、积分增加)投递到 Kafka 或 RocketMQ,实现流量平滑。

    • 顺序与幂等: 确保消息消费的幂等性,防止重复执行。

  • 异步编程: Java 内部使用 CompletableFuture 或 Reactor 模型,避免主线程在 IO 等待上浪费时间。

存储引擎优化

即使有了缓存,存储层也需要做最后的兜底准备。

  • 读写分离与分库分表: 通过分片将压力分散到多个数据库节点。

  • 批量写入: 数据库写操作尽量采用 Batch Insert 减少磁盘 IO 次数。

  • 冷热隔离: 将近期活跃数据与历史数据分开存储,提升查询效率。

  • NoSQL 选型: 如果场景允许,优先使用 MongoDB、Cassandra 或 Elasticsearch 等擅长横向扩展的数据库。

稳定性保障

手段

描述

熔断降级

当某个服务响应过慢时,自动切断该调用链,返回友好提示或默认值。

全链路压测

模拟百万级真实流量,找出系统瓶颈点(如 CPU 瓶颈、网卡带宽或内存溢出)。

监控报警

建立 Prometheus + Grafana 的实时监控,涵盖 QPS、RT(响应时间)、P99 等关键指标。