1. 淘宝闪购SPS系统架构解析
淘宝闪购作为电商秒杀活动的核心系统,其SPS(Seckill Platform Service)模块承担着高并发流量下的商品抢购业务。这个日均PV过亿的系统采用Java技术栈构建,基于Spring Cloud微服务架构,主要包含商品中心、订单中心、支付中心和风控中心四大模块。
在微服务架构下,前端页面需要同时调用多个服务的接口,这就产生了典型的跨域问题。特别是在移动端H5页面调用后端接口时,由于域名不同(如m.taobao.com调用api.taobao.com),浏览器会触发同源策略限制。
同源策略是浏览器的重要安全机制,它要求协议、域名、端口三者完全相同才允许通信。在实际业务中,这显然不现实。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Java跨域问题的核心挑战
2.1 淘宝闪购的业务特点
闪购业务具有典型的"三高"特征:
- 高并发:峰值QPS可达50万+
- 高频交互:页面平均每3秒轮询库存
- 高实时性:从点击到下单需在200ms内完成
这些特性使得跨域解决方案必须满足:
- 极低的性能开销(<5ms延迟)
- 高可用性(99.99% SLA)
- 安全性(防CSRF/XSS攻击)
2.2 常见跨域场景分析
在SPS系统中,我们主要遇到三类跨域场景:
| 场景类型 | 示例 | 出现频率 | 解决方案复杂度 |
|---|---|---|---|
| 前后端分离 | H5调用Java API | 极高 | 中 |
| 微服务间调用 | 订单服务调支付服务 | 低 | 低 |
| 第三方接入 | 银行支付回调 | 中 | 高 |
3. 五种实战解决方案及性能对比
3.1 @CrossOrigin注解方案
这是Spring框架提供的最简单方案:
java复制@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "https://m.taobao.com",
maxAge = 3600,
allowedHeaders = "*")
public class ProductController {
@GetMapping("/stock")
public StockInfo getStock(@RequestParam Long itemId) {
//...
}
}
实测数据:
- 平均延迟:2.3ms
- 吞吐量:12,000 QPS
- 内存占用:可忽略
适合场景:内部管理系统、低频接口。在淘宝闪购中仅用于运营后台。
3.2 全局CORS配置方案
通过WebMvcConfigurer实现全局配置:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://m.taobao.com")
.allowedMethods("GET", "POST")
.allowCredentials(true)
.maxAge(3600);
}
}
性能优化技巧:
- 使用精确的path匹配(避免/**)
- 限制HTTP方法(不要用*)
- 设置合理的maxAge缓存
3.3 Nginx反向代理方案
这是淘宝闪购主力的生产方案:
nginx复制server {
listen 443;
server_name api.taobao.com;
location /sps/ {
add_header 'Access-Control-Allow-Origin' 'https://m.taobao.com';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type,X-Token';
if ($request_method = 'OPTIONS') {
return 204;
}
proxy_pass http://backend-service;
}
}
优势对比:
- 性能:比Java层处理快3倍
- 灵活:可动态调整策略
- 解耦:不侵入业务代码
3.4 Spring Cloud Gateway方案
对于微服务架构的现代方案:
yaml复制# application.yml
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://m.taobao.com"
allowedMethods: "*"
allowedHeaders: "*"
allowCredentials: true
maxAge: 3600
灰度发布策略:
- 先对10%流量启用
- 监控RT和错误率
- 逐步全量
3.5 JSONP方案(历史兼容)
虽然已过时但某些场景仍需:
java复制@RestController
public class ProductController {
@GetMapping("/api/stock")
public String getStock(@RequestParam Long itemId,
@RequestParam String callback) {
StockInfo stock = stockService.getStock(itemId);
return callback + "(" + JSON.toJSONString(stock) + ")";
}
}
注意事项:
- 只支持GET请求
- 需防范XSS攻击
- 性能较差(比CORS慢5倍)
4. 淘宝闪购的最佳实践
4.1 多级缓存策略
我们采用三级缓存架构解决跨域带来的性能问题:
- 浏览器本地缓存(maxAge控制)
- Nginx层缓存(缓存预检请求)
- Redis集群缓存(热点数据)
4.2 安全防护措施
针对跨域特有的安全问题:
- CSRF Token校验
- Origin白名单动态加载
- CORS配置自动化测试
java复制// 动态Origin校验示例
@RestControllerAdvice
public class SecurityAdvice implements HandlerInterceptor {
private Set<String> allowOrigins = loadWhiteList();
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
String origin = request.getHeader("Origin");
if (!allowOrigins.contains(origin)) {
response.setStatus(403);
return false;
}
return true;
}
}
4.3 性能优化指标
经过优化后的关键指标对比:
| 方案 | 平均延迟 | 最大QPS | CPU占用 | 适用场景 |
|---|---|---|---|---|
| @CrossOrigin | 2.3ms | 12k | 低 | 后台管理 |
| Nginx | 0.8ms | 85k | 极低 | 生产环境 |
| Gateway | 1.2ms | 65k | 中 | 微服务 |
| JSONP | 12ms | 3k | 高 | 兼容旧版 |
5. 踩坑实录与解决方案
5.1 Cookie跨域问题
现象:登录态丢失
原因:SameSite属性限制
解决:
java复制@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieSameSiteSupporter() {
return factory -> factory.addContextCustomizers(context -> {
context.setSessionCookieName("JSESSIONID");
context.setSessionCookiePath("/");
context.setSessionCookieDomain(".taobao.com");
context.setSessionCookieSameSiteCookies("None");
});
}
5.2 预检请求风暴
现象:OPTIONS请求占50%流量
优化方案:
- 延长maxAge到86400秒
- Nginx缓存预检响应
- 合并简单请求
5.3 移动端兼容性问题
特殊案例:某款Android机型无法识别*
解决方案:
- 显式列出所有Headers
- 禁用通配符*
- 增加UA检测逻辑
6. 未来架构演进
虽然当前方案稳定运行,但我们正在测试两种新方案:
-
WebSocket全双工通信:避免重复预检
- 适用于实时库存推送
- 连接成本较高
-
HTTP/2 Server Push:主动推送资源
- 减少连接建立开销
- 需要客户端支持
在双11大促前,我们计划将Nginx方案升级到OpenResty,通过Lua脚本实现动态跨域规则加载,预计可再提升30%性能。
