🎯 本文适合人群 :SpringCloud 初学者、微服务开发者
⏱️ 阅读时长 :25 分钟
📌 你将收获:掌握 Gateway 网关配置、Sentinel 熔断降级、流量控制
📖 目录
- [一、Gateway 网关快速入门](#一、Gateway 网关快速入门)
- [二、Gateway 路由与过滤器](#二、Gateway 路由与过滤器)
- [三、Sentinel 熔断降级](#三、Sentinel 熔断降级)
- [四、Sentinel 流量控制](#四、Sentinel 流量控制)
- [五、Gateway + Sentinel 整合](#五、Gateway + Sentinel 整合)
- 六、常见面试题
一、Gateway 网关快速入门
1.1 为什么需要网关?
没有网关的问题:
❌ 客户端需要知道所有服务地址
❌ 跨域(CORS)问题
❌ 每个服务都要写鉴权代码
❌ 限流、日志分散
使用网关:
客户端 → Gateway(统一入口)→ 各个微服务
✅ 统一入口
✅ 统一鉴权、限流
✅ 动态路由
✅ 协议转换
1.2 Gateway 核心概念
| 概念 | 说明 | 示例 |
|---|---|---|
| Route(路由) | 请求路径 → 目标服务 | /user/** → user-service |
| Predicate(断言) | 匹配条件 | Path=/user/** |
| Filter(过滤器) | 请求前后执行逻辑 | 鉴权、日志、限流 |
1.3 快速搭建 Gateway
步骤 1:依赖配置
xml
<!-- pom.xml -->
<dependencies>
<!-- Gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Nacos 服务发现 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- LoadBalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
</dependencies>
注意 :Gateway 不要引入 spring-boot-starter-web,会冲突!
步骤 2:配置文件
yaml
# application.yml
server:
port: 9000
spring:
application:
name: gateway-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
# 用户服务路由
- id: user-route
uri: lb://user-service # lb = LoadBalancer
predicates:
- Path=/user/**
filters:
- StripPrefix=1 # 去掉 /user 前缀
# 订单服务路由
- id: order-route
uri: lb://order-service
predicates:
- Path=/order/**
filters:
- StripPrefix=1
步骤 3:启动类
java
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
步骤 4:测试
bash
# 通过网关访问用户服务
curl http://localhost:9000/user/1001
# 实际转发到:http://user-service/1001
二、Gateway 路由与过滤器
2.1 Predicate(断言)常用类型
| 断言 | 说明 | 示例 |
|---|---|---|
| Path | 路径匹配 | Path=/user/** |
| Method | 请求方法 | Method=GET,POST |
| Header | 请求头匹配 | Header=X-Token, .* |
| Query | 查询参数 | Query=version, v2 |
| Host | 主机匹配 | Host=**.example.com |
组合使用:
yaml
predicates:
- Path=/api/**
- Method=GET,POST
- Header=X-Token, .*
2.2 Filter(过滤器)常用类型
| 过滤器 | 作用 | 示例 |
|---|---|---|
| StripPrefix | 去掉路径前缀 | StripPrefix=1 |
| AddRequestHeader | 添加请求头 | AddRequestHeader=X-Gateway, Gateway |
| AddResponseHeader | 添加响应头 | AddResponseHeader=X-Time, 100ms |
| RewritePath | 重写路径 | RewritePath=/red/(.*), /$\{segment} |
2.3 自定义全局过滤器(鉴权)
java
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ① 获取请求
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
// ② 白名单:登录接口不需要鉴权
if (path.equals("/user/login")) {
return chain.filter(exchange);
}
// ③ 获取 Token
String token = request.getHeaders().getFirst("Authorization");
// ④ 验证 Token
if (token == null || !token.startsWith("Bearer ")) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
// ⑤ Token 合法,放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100; // 优先级高
}
}
三、Sentinel 熔断降级
3.1 什么是熔断降级?
问题场景:雪崩效应
库存服务挂了:
用户请求 → 订单服务 → 库存服务(超时)
↓
请求堆积 → 订单服务崩溃 → 系统瘫痪 ❌
解决方案:熔断器
使用 Sentinel:
订单服务 → 检测到库存服务异常 → 熔断器打开
→ 快速失败 → 返回降级响应 ✅
3.2 Sentinel 快速入门
步骤 1:添加依赖
xml
<!-- Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
步骤 2:配置文件
yaml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel 控制台
port: 8719
步骤 3:定义资源
java
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/{id}")
@SentinelResource(
value = "getUserById", // 资源名
blockHandler = "handleBlock", // 限流/熔断降级方法
fallback = "handleFallback" // 异常降级方法
)
public User getUserById(@PathVariable Long id) {
if (id < 0) {
throw new IllegalArgumentException("ID 不合法");
}
return new User(id, "用户" + id, 25, "user@example.com");
}
// 限流/熔断降级方法
public User handleBlock(Long id, BlockException ex) {
return new User(id, "系统繁忙", 0, "");
}
// 异常降级方法
public User handleFallback(Long id, Throwable ex) {
return new User(id, "服务异常", 0, "");
}
}
3.3 熔断规则配置
java
@Configuration
public class SentinelConfig {
@PostConstruct
public void initRules() {
List<DegradeRule> rules = new ArrayList<>();
// 异常比例熔断
DegradeRule rule = new DegradeRule("getUserById");
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO);
rule.setCount(0.5); // 异常比例 50%
rule.setTimeWindow(10); // 熔断时长 10 秒
rule.setMinRequestAmount(5); // 最小请求数
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
3.4 熔断器状态机
┌──────────┐
│ 关闭 │ → 正常请求
└────┬─────┘
│ 异常率 > 50%
↓
┌──────────┐
│ 开启 │ → 拒绝所有请求
└────┬─────┘
│ 等待 10 秒
↓
┌──────────┐
│ 半开 │ → 尝试一次请求
└────┬─────┘
├─→ 成功 → 关闭
└─→ 失败 → 开启
四、Sentinel 流量控制
4.1 限流规则
| 策略 | 说明 | 示例 |
|---|---|---|
| QPS | 每秒请求数 | QPS ≤ 100 |
| 并发线程数 | 同时处理的请求数 | 并发 ≤ 10 |
流控效果:
| 效果 | 说明 |
|---|---|
| 快速失败 | 超过阈值直接拒绝(默认) |
| Warm Up | 预热,逐渐增加流量 |
| 排队等待 | 匀速排队,削峰填谷 |
4.2 限流规则配置
java
@PostConstruct
public void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
// QPS 限流
FlowRule rule = new FlowRule("getUserById");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10); // QPS = 10
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
4.3 Sentinel 控制台
下载启动:
bash
# 下载
wget https://github.com/alibaba/Sentinel/releases/download/1.8.6/sentinel-dashboard-1.8.6.jar
# 启动
java -jar sentinel-dashboard-1.8.6.jar
# 访问:http://localhost:8080
# 账号/密码:sentinel / sentinel
控制台功能:
- ✅ 实时监控(QPS、响应时间)
- ✅ 流控规则配置
- ✅ 熔断规则配置
- ✅ 热点参数限流
4.4 规则持久化到 Nacos
添加依赖:
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
配置文件:
yaml
spring:
cloud:
sentinel:
datasource:
flow: # 流控规则
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
rule-type: flow
Nacos 创建配置:
json
[
{
"resource": "getUserById",
"limitApp": "default",
"grade": 1,
"count": 10,
"strategy": 0,
"controlBehavior": 0
}
]
五、Gateway + Sentinel 整合
5.1 Gateway 集成 Sentinel
步骤 1:添加依赖
xml
<!-- Sentinel Gateway -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
步骤 2:配置限流规则
java
@Configuration
public class GatewaySentinelConfig {
@PostConstruct
public void initRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
// 针对路由限流
GatewayFlowRule rule = new GatewayFlowRule("user-route")
.setCount(10) // QPS = 10
.setIntervalSec(1);
rules.add(rule);
GatewayRuleManager.loadRules(rules);
// 配置限流降级处理
initBlockHandler();
}
private void initBlockHandler() {
GatewayCallbackManager.setBlockHandler((exchange, ex) -> {
Map<String, Object> result = new HashMap<>();
result.put("code", 429);
result.put("msg", "请求过于频繁,请稍后再试");
return ServerResponse
.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result));
});
}
}
5.2 测试网关限流
bash
# 快速请求 20 次
for i in {1..20}; do
curl http://localhost:9000/user/1001
done
# 前 10 次:正常返回
# 后 10 次:限流返回 429
5.3 OpenFeign 集成 Sentinel
配置文件:
yaml
feign:
sentinel:
enabled: true # 开启 Feign Sentinel 支持
定义降级类:
java
@FeignClient(
name = "user-service",
fallback = UserClientFallback.class // 降级类
)
public interface UserClient {
@GetMapping("/user/{id}")
User getUserById(@PathVariable Long id);
}
@Component
public class UserClientFallback implements UserClient {
@Override
public User getUserById(Long id) {
// 降级逻辑
return new User(id, "降级用户", 0, "");
}
}
六、常见面试题
面试题 1:Gateway 的工作原理是什么?
参考答案:
- 接收请求
- 匹配路由(Predicate)
- 执行前置过滤器(鉴权、限流)
- 转发请求到目标服务(LoadBalancer 负载均衡)
- 接收响应
- 执行后置过滤器(添加响应头、日志)
- 返回响应
面试题 2:Gateway 和 Zuul 的区别?
参考答案:
| 对比项 | Gateway | Zuul |
|---|---|---|
| 技术栈 | WebFlux(响应式) | Servlet(阻塞式) |
| 性能 | 高 | 一般 |
| 维护 | ✅ 持续维护 | ❌ 停止维护 |
推荐 :新项目使用 Gateway!
面试题 3:什么是熔断?什么是降级?
参考答案:
熔断(Circuit Breaker):
- 当服务故障率达到阈值,自动切断调用
- 防止雪崩效应
降级(Fallback):
- 服务不可用时,返回备用响应
- 保证核心功能可用
关系:熔断是手段,降级是结果
面试题 4:Sentinel 的限流算法有哪些?
参考答案:
- 快速失败:超过阈值直接拒绝(默认)
- Warm Up:预热,逐渐增加流量
- 排队等待:匀速排队,削峰填谷
面试题 5:Sentinel 和 Hystrix 的区别?
参考答案:
| 对比项 | Sentinel | Hystrix |
|---|---|---|
| 功能 | 限流 + 熔断 + 系统保护 | 仅熔断 |
| 控制台 | ✅ 功能丰富 | ❌ 无 |
| 维护 | ✅ 持续维护 | ❌ 停止维护 |
推荐 :新项目使用 Sentinel!
面试题 6:如何实现灰度发布?
参考答案:
方案 1:基于权重(Nacos)
新版本:权重 10
旧版本:权重 90
→ 10% 流量到新版本
方案 2:基于请求头(Gateway)
yaml
predicates:
- Header=X-Version, v2 # 带 v2 头的请求路由到新版本
面试题 7:Gateway 如何实现跨域?
参考答案:
yaml
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods: "*"
allowedHeaders: "*"
面试题 8:Sentinel 如何持久化规则?
参考答案:
方式 1:推送到 Nacos
yaml
spring:
cloud:
sentinel:
datasource:
flow:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
方式 2:推送到 Apollo
方式 3:推送到文件
总结
本文介绍了 Gateway 和 Sentinel 的核心使用:
✅ Gateway :统一网关入口,路由、鉴权、限流
✅ Sentinel :流量控制、熔断降级、系统保护
✅ 整合:Gateway + Sentinel 实现网关限流
学习建议:
- 先搭建 Gateway,理解路由和过滤器
- 再学习 Sentinel,理解限流和熔断
- 最后整合实践,结合实际场景
🎉 SpringCloud 系列博客完结!从微服务基础到 Gateway + Sentinel,带你全面掌握 SpringCloud 核心技术!
📚 系列回顾:
- 微服务基础与 SpringCloud 核心作用
- 五大核心组件全解析
- Nacos 服务注册与发现实战
- OpenFeign 服务调用与负载均衡
- Gateway 网关与 Sentinel 熔断入门
💡 继续学习:
- SpringCloud Stream(消息驱动)
- Seata(分布式事务)
- Sleuth + Zipkin(链路追踪)