网关限流
Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。[1]
Spring Cloud Gateway
从 1.6.0 版本开始,Sentinel 提供了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:
- route 维度:即在 Spring 配置文件中配置的路由条目,资源名为对应的 routeId
- 自定义 API 维度:用户可以利用 Sentinel 提供的 API 来自定义一些 API 分组
使用时需引入以下模块(以 Maven 为例):
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
官网写的是下面的配置,可能是版本问题,我看的教程是需要配置上面的模块
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
<version>x.y.z</version>
</dependency>
完整依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zjw</groupId>
<artifactId>sc-06-sentinel-gateway-router-9000</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sc-06-sentinel-gateway-router-9000</name>
<description>sc-06-sentinel-gateway-router-9000</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2022.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
</properties>
<dependencies>
<!--sentinel与spring cloud gateway整合依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 9000
spring:
application:
name: sentinel-gateway # 微服务名称
cloud:
nacos:
discovery:
server-addr: nacos-local:8848 # nacos注册中心地址
username: nacos # 用户名密码
password: nacos
gateway:
routes:
- id: get_route
uri: lb://depart-consumer
predicates:
- Path=/depart/get/**
- id: list
uri: lb://depart-consumer
predicates:
- Path=/depart/list
sentinel: # sentinel配置
eager: true # 饥饿加载,默认false
filter:
enabled: false # 若在网关流控控制台上看到了 URL 资源
transport:
port: 8719 # sentinel内部启动的http服务
dashboard: localhost:8888 # sentinel服务
启动类不需要额外配置。
sentinel控制台配置网关限流规则。
当请求过快,会出现以下界面。
控制台会报错,说方法不存在
点击查看代码
2023-12-07T02:15:29.713+08:00 ERROR 20520 --- [ctor-http-nio-3] reactor.netty.http.server.HttpServer : [c632f6fc-1, L:/[0:0:0:0:0:0:0:1]:9000 - R:/[0:0:0:0:0:0:0:1]:13569]
java.lang.NoSuchMethodError: 'org.springframework.web.reactive.function.server.ServerResponse$BodyBuilder org.springframework.web.reactive.function.server.ServerResponse.status(org.springframework.http.HttpStatus)'
at com.alibaba.csp.sentinel.adapter.gateway.sc.callback.DefaultBlockRequestHandler.htmlErrorResponse(DefaultBlockRequestHandler.java:51) ~[sentinel-spring-cloud-gateway-adapter-1.8.6.jar:na]
at com.alibaba.csp.sentinel.adapter.gateway.sc.callback.DefaultBlockRequestHandler.handleRequest(DefaultBlockRequestHandler.java:42) ~[sentinel-spring-cloud-gateway-adapter-1.8.6.jar:na]
自定义异常
重定向
package com.zjw;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
public class SentinelGateWay9001Application {
public static void main(String[] args) {
SpringApplication.run(SentinelGateWay9001Application.class, args);
// 初始化阻塞处理器
initBlockHandler();
}
/**
* 初始化阻塞处理器
*/
private static void initBlockHandler() {
//重定向
GatewayCallbackManager.setBlockHandler(new RedirectBlockRequestHandler("https://baidu.com"));
}
}
也可以在配置文件中添加重定向
sentinel: # sentinel配置
eager: true # 饥饿加载,默认false
filter:
enabled: false # 若在网关流控控制台上看到了 URL 资源
transport:
port: 8719 # sentinel内部启动的http服务
dashboard: localhost:8888 # sentinel服务
scg:
mode: redirect
redirect: https://baidu.com
自定义结果
package com.zjw;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
@SpringBootApplication
public class SentinelGateWay9001Application {
public static void main(String[] args) {
SpringApplication.run(SentinelGateWay9001Application.class, args);
// 初始化阻塞处理器
initBlockHandler();
}
/**
* 初始化阻塞处理器
*/
private static void initBlockHandler() {
// 自定义异常结果
GatewayCallbackManager.setBlockHandler((serverWebExchange, throwable) -> {
Map<String, Object> map = new HashMap<>();
map.put("uri", serverWebExchange.getRequest().getURI());
map.put("msg","访问量过大,稍后请重试");
map.put("code", HttpStatus.TOO_MANY_REQUESTS.value());
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(map), Map.class);
});
}
}
也可以在配置中配置,但是显得很呆
sentinel: # sentinel配置
scg:
fallback:
mode: response
content-type: 'application/json'
response-status: 429
response-body: '{"code":"429","msg":"访问量过大,稍后请重试"}'