我们先来看下微服务网关的定义。
微服务网关是指为前端或客户端提供的统一服务入口,用于处理后端程序的通用逻辑,诸如:认证鉴权、动态路由、限流熔断、API监控等。
网关在微服务架构中所处的生态位,如下图所示:
认证鉴权:对用户请求进行识别判定,拦截非法请求,保障系统安全性。
动态路由:按照配置规则,动态地将用户请求路由到不同的微服务集群上。
限流熔断:旨在提升高并发场景下的系统可用性。
限流,控制单位时间内的请求流量,防止突发流量压垮后端服务,确保系统资源合理分配。
熔断,当下游非核心服务出现故障(如超时、异常)时,快速中断请求链路并返回预设响应,避免故障扩散引发雪崩效应。
API监控:通过集成多维度监控工具,实现对 API 请求的全链路追踪、性能指标收集与可视化分析,帮助开发者实时掌握网关流量状态与系统健康度。
接下来我们以Spring Cloud Gateway为例,看看这些功能是如何实现的,再回答“为什么微服务架构一定要有网关”这个问题,这样逻辑会清晰很多。
认证鉴权
Spring Cloud Gateway实现认证鉴权的核心是通过过滤器链(Filter Chain)拦截请求,结合安全框架(如 Spring Security)或自定义逻辑对用户身份和权限进行验证。
目前主流的认证鉴权方式是基于JWT来实现的,由
..三部分组成,具备无状态性、跨域支持和灵活扩展等优点。
代码实现如下:
@Component
public class JwtAuthFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
try {
String jwtToken = token.substring(7); // 去掉 "Bearer " 前缀
List<String> roles = JwtValidator.getRoles(jwtToken);
// 检查角色是否匹配(示例:仅允许 ROLE_ADMIN 访问)
if (!roles.contains("ROLE_ADMIN")) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
} catch (JwtException e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1; // 优先级
}
}
动态路由
Spring Cloud Gateway可通过与Nacos、Apollo等配置中心配合的方式实现动态
路由,由配置中心管理路由配置,Gateway监听配置变化并动态更新路由。
配置中心中的路由规则如下:
[ { "id": "user-service", "predicates": [{"name": "Path", "args": {"pattern": "/api/user/**"}}],
"filters": [{"name": "StripPrefix", "args": {"parts": 1}}],
"uri": "lb://user-service",
"order": 0
}
]
然后在代码中对路由配置变化进行监听:
@Component
public class NacosRouteDefinitionRepository implements RouteDefinitionRepository {
@Autowired
private NacosConfigManager nacosConfigManager;
@Override
public Flux<RouteDefinition> getRouteDefinitions() {
// 从 Nacos 加载路由配置:ml-citation{ref="6,8" data="citationList"}
return Flux.fromIterable(loadRoutesFromNacos());
}
@EventListener
public void onRefreshRoutesEvent(RefreshRoutesEvent event) {
// 触发路由更新:ml-citation{ref="6" data="citationList"}
}
}
限流熔断
对于限流熔断,目前的主流技术方案,是通过Spring Cloud Alibaba的Sentinel组件进行实现。
我们可以在Sentinel自带的控制台中进行精细化限流熔断参数配置,并可以实时生效。
如下图所示:
限流方面,我们可以简单粗暴地对Spring Cloud Gateway进行整体限流,也可以按需进行更加精细化的多维度限流。
比如:
(1)可以通过精确、前缀和正则表达式的方式进行API分组,对不同分组设置不同的限流策略。
(2)可以根据用户ID或外部系统编码进行限流,相比较于整体限流,这样可以更好地防止资源倾斜。
API监控
如上文所述,Sentinel是支持动态配置并实时生效的,但我们实时修改配置一定是需要一句的,这个依据就是对Spring Cloud Gateway中的API进行监控。
目前行业内的主流做法是,集成Prometheus监控平台进行数据收集和存储,并通过Grafana进行API指标(QPS、响应时间、错误率等)的可视化展示。
Spring Cloud Gateway还可以与Spring Cloud Sleuth + Zipkin进行集成,自动追踪请求在多个服务间的流转路径,记录耗时、状态码等关键信息,提升工程师的问题排查效率。
对于C端的高并发系统(QPS 10000+),我们可以调整采用率的方式来减轻存储压力,如:
spring.sleuth.sampler.probability = 0.1。
与此同时,我们还可以在代码中对关键业务接口专门配置注解,以使其进行强制采样。@Trace(sampler = Sampler.ALWAYS_SAMPLE)
网关的必要性
我们把网关所涉及到的功能梳理一遍后,接下来聊下“为什么微服务架构一定要有网关”。
如果没有网关层的话,那路由调用的工作只能由前端或客户端来完成,一定程度上增加了它们的工作复杂度。
如果没有网关层的话,那认证鉴权、限流熔断、API监控等工作只能由每个微服务都实现一遍,增加了很多重复的代码和工作量。
这两种副作用显然都不是我们想要看到的。
接下来我们再从系统架构的角度聊下微服务网关存在的意义。
系统架构设计通常有两个思路,那就是分治化和中心化。
分治化,其思路是将复杂问题进行拆解简化并逐个击破,而中心化则是将散点问题集中在一起进行解决,以起到提效的目的。
如果说我们将系统从单体架构拆分为微服务架构是分治化的思路,那网关层的中心化引入,则是在一定程度上弥补微服务拆分后所带来的研发效率问题。