引言
在大型电商平台中,API 网关作为系统的入口,承担着统一管理、安全防护、流量控制等重要职责。京东作为国内领先的电商平台,其商品 API 网关的设计直接关系到系统的稳定性、安全性和用户体验。本文将详细介绍京东商品 API 网关在认证、限流与监控方面的设计策略,并提供相关代码实现。
一、API 网关整体架构
京东商品 API 网关采用分层架构设计,主要包括接入层、核心层和后端服务层。
- 接入层:负责接收客户端请求,进行请求的初步过滤和转发。
- 核心层:是网关的核心部分,包含认证、限流、监控等功能模块。
- 后端服务层:由各个商品相关的微服务组成,如商品查询服务、商品库存服务等。
二、统一认证策略
2.1 认证方式选择
京东商品 API 网关采用 OAuth 2.0 认证方式,结合 JWT(JSON Web Token)实现无状态认证。OAuth 2.0 提供了授权码模式、密码模式等多种授权方式,满足不同场景下的认证需求。JWT 则用于在客户端和服务端之间传递认证信息,具有无状态、可扩展等优点。
2.2 认证流程
- 客户端向认证服务器申请令牌(Token)。
- 认证服务器验证客户端身份和授权信息,生成 JWT 令牌并返回给客户端。
- 客户端在后续请求中携带 JWT 令牌,API 网关对令牌进行验证,包括令牌的有效性、签名正确性和过期时间等。
- 验证通过后,API 网关将请求转发给后端服务;验证失败则返回相应的错误信息。
2.3 代码实现
// JWT工具类
public class JwtUtils {
private static final String SECRET = "jd商品API网关密钥";
private static final long EXPIRATION_TIME = 3600000; // 1小时
// 生成JWT令牌
public static String generateToken(String username) {
Date expirationDate = new Date(System.currentTimeMillis() + EXPIRATION_TIME);
return Jwts.builder()
.setSubject(username)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
}
// 验证JWT令牌
public static boolean validateToken(String token) {
try {
Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
// 从JWT令牌中获取用户名
public static String getUsernameFromToken(String token) {
Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
return claims.getSubject();
}
}
// 认证过滤器
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 获取Authorization头部信息
String authorizationHeader = httpRequest.getHeader("Authorization");
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResponse.getWriter().write("Unauthorized: No token provided");
return;
}
// 提取并验证令牌
String token = authorizationHeader.substring(7);
if (!JwtUtils.validateToken(token)) {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResponse.getWriter().write("Unauthorized: Invalid token");
return;
}
// 将用户名存入请求属性中,供后续使用
String username = JwtUtils.getUsernameFromToken(token);
httpRequest.setAttribute("username", username);
chain.doFilter(request, response);
}
}
三、限流策略
3.1 限流算法选择
京东商品 API 网关采用令牌桶算法实现限流。令牌桶算法是一种常用的限流算法,其原理是:系统以一定的速率向令牌桶中放入令牌,当有请求到达时,需要从令牌桶中获取一个令牌,如果令牌桶中有足够的令牌,则请求被允许处理;否则,请求被拒绝。
3.2 限流粒度设计
为了满足不同场景下的限流需求,京东商品 API 网关支持多种限流粒度,包括:
- 全局限流:对整个 API 网关的请求进行限流,限制单位时间内的总请求数。
- 服务级限流:对每个后端服务的请求进行限流,限制单位时间内该服务的请求数。
- 接口级限流:对每个具体的 API 接口的请求进行限流,限制单位时间内该接口的请求数。
- 用户级限流:对每个用户的请求进行限流,限制单位时间内该用户的请求数。
3.3 代码实现
// 限流工具类
public class RateLimiterUtils {
private static final ConcurrentHashMap<String, RateLimiter> RATE_LIMITERS = new ConcurrentHashMap<>();
// 获取或创建令牌桶
public static RateLimiter getRateLimiter(String key, double permitsPerSecond) {
return RATE_LIMITERS.computeIfAbsent(key, k -> RateLimiter.create(permitsPerSecond));
}
// 尝试获取令牌
public static boolean tryAcquire(String key, double permitsPerSecond) {
RateLimiter rateLimiter = getRateLimiter(key, permitsPerSecond);
return rateLimiter.tryAcquire();
}
}
// 限流过滤器
public class RateLimitingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
// 获取请求的相关信息,用于构建限流键
String serviceName = httpRequest.getParameter("serviceName");
String interfaceName = httpRequest.getParameter("interfaceName");
String username = (String) httpRequest.getAttribute("username");
// 构建不同粒度的限流键
String globalKey = "global";
String serviceKey = "service:" + serviceName;
String interfaceKey = "interface:" + interfaceName;
String userKey = "user:" + username;
// 设置不同粒度的限流速率(可根据实际情况调整)
double globalRate = 1000.0; // 全局每秒1000个请求
double serviceRate = 500.0; // 服务级每秒500个请求
double interfaceRate = 100.0; // 接口级每秒100个请求
double userRate = 10.0; // 用户级每秒10个请求
// 依次进行不同粒度的限流判断
if (!RateLimiterUtils.tryAcquire(globalKey, globalRate)) {
httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
httpResponse.getWriter().write("Too many requests: Global rate limit exceeded");
return;
}
if (!RateLimiterUtils.tryAcquire(serviceKey, serviceRate)) {
httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
httpResponse.getWriter().write("Too many requests: Service rate limit exceeded");
return;
}
if (!RateLimiterUtils.tryAcquire(interfaceKey, interfaceRate)) {
httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
httpResponse.getWriter().write("Too many requests: Interface rate limit exceeded");
return;
}
if (!RateLimiterUtils.tryAcquire(userKey, userRate)) {
httpResponse.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
httpResponse.getWriter().write("Too many requests: User rate limit exceeded");
return;
}
chain.doFilter(request, response);
}
}
四、监控策略
4.1 监控指标设计
京东商品 API 网关的监控指标主要包括以下几个方面:
- 请求指标:请求总数、成功请求数、失败请求数、请求响应时间等。
- 系统指标:CPU 使用率、内存使用率、磁盘使用率、网络带宽等。
- 业务指标:商品查询量、商品下单量、商品库存变化量等。
4.2 监控数据收集与展示
- 数据收集:通过在 API 网关中植入监控代码,收集请求指标和系统指标数据。同时,与后端业务系统集成,获取业务指标数据。
- 数据存储:将收集到的监控数据存储到时序数据库中,如 InfluxDB、Prometheus 等,以便进行后续的查询和分析。
- 数据展示:通过监控仪表盘展示监控数据,支持实时监控和历史数据查询。监控仪表盘可以根据不同的角色和需求进行定制,如运维人员关注系统指标,业务人员关注业务指标。
4.3 代码实现
// 监控工具类
public class MonitoringUtils {
private static final MeterRegistry meterRegistry = new SimpleMeterRegistry();
// 记录请求总数
public static void recordRequestCount() {
meterRegistry.counter("api.requests.total").increment();
}
// 记录成功请求数
public static void recordSuccessRequestCount() {
meterRegistry.counter("api.requests.success").increment();
}
// 记录失败请求数
public static void recordFailureRequestCount() {
meterRegistry.counter("api.requests.failure").increment();
}
// 记录请求响应时间
public static Timer.Sample recordRequestDuration() {
return Timer.start(meterRegistry);
}
// 获取MeterRegistry实例
public static MeterRegistry getMeterRegistry() {
return meterRegistry;
}
}
// 监控过滤器
public class MonitoringFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Timer.Sample sample = MonitoringUtils.recordRequestDuration();
MonitoringUtils.recordRequestCount();
try {
chain.doFilter(request, response);
MonitoringUtils.recordSuccessRequestCount();
} catch (Exception e) {
MonitoringUtils.recordFailureRequestCount();
throw e;
} finally {
sample.stop(MonitoringUtils.getMeterRegistry().timer("api.requests.duration"));
}
}
}
五、总结与展望
京东商品 API 网关通过统一的认证、限流与监控策略,有效保障了系统的安全性、稳定性和可用性。在认证方面,采用 OAuth 2.0 和 JWT 实现无状态认证,提高了认证的灵活性和安全性;在限流方面,采用令牌桶算法支持多种粒度的限流,有效防止了系统过载;在监控方面,设计了全面的监控指标,实现了对系统的实时监控和分析。
未来,京东商品 API 网关将进一步优化和完善,例如引入人工智能技术实现智能限流和异常检测,提高系统的自适应能力;加强与云原生技术的融合,实现更灵活的部署和扩展。同时,将持续关注行业技术发展趋势,不断提升 API 网关的性能和功能,为用户提供更好的服务。