本文使用 gateway 内置的过滤工厂 -RequestRateLimiter 实现限流的。
本文Demo 是对《重新定义》 代码示例进行改造。
说明一下,我准备好的客户端接口,和父pom如下
@RequestMapping("/hello")
@RestController
public class HelloController {
@GetMapping("/rateLimit")
public String hello() {
return "Hello, spring cloud Gateway";
}
}
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
说明一下,所有工程<parent> 中,groupId,artifactId,version替换成父pom即可。
创建一个maven工程,作为我们gateway。pom需要添加的依赖如下
<dependencies>
<!-- Spring Cloud Gateway的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
创建一个 RemoteAddrKeyResolver 类,为了编写 key-resolver 对应的 remoteAddrKeyResolver
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class RemoteAddrKeyResolver implements KeyResolver {
public static final String BEAN_NAME = "remoteAddrKeyResolver";
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress());
}
}
把key对应的解析器加载到spring 容器中。
@SpringBootApplication@EnableEurekaClient
public class GatewayApplication {
@Bean(name = RemoteAddrKeyResolver.BEAN_NAME)
public RemoteAddrKeyResolver remoteAddrKeyResolver() {
return new RemoteAddrKeyResolver();
}
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
yml 配置
server.port: 8081
eureka:
client:
serviceUrl:
defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8888}/eureka/
instance:
prefer-ip-address: true
spring:
application:
name: ch18-6-1-gateway
redis:
host: localhost
port: 6379
cloud:
gateway:
routes:
- id: ch18-6-provider
uri: http://localhost:8000/hello/rateLimit
order: 0
predicates:
- Path=/client/**
filters:
#filter名称必须是RequestRateLimiter
- name: RequestRateLimiter
args:
#使用SpEL按名称引用bean
key-resolver: "#{@remoteAddrKeyResolver}"
#允许用户每秒处理多少个请求
redis-rate-limiter.replenishRate: 1
#令牌桶的容量,允许在一秒钟内完成的最大请求数
redis-rate-limiter.burstCapacity: 5
discovery:
locator:
enabled: true
lower-case-service-id: true
logging:
level:
#org.springframework.cloud.gateway: debug
cn.springcloud.book.filter: debug
代码解释:
我们说下面的代码意思是把 gateway 配合注册中心进行转发
discovery:
locator:
enabled: true
lower-case-service-id: true
下面代码是路由转发,跟 zuul 的path 和serviceId 的作用一样
cloud:
gateway:
routes:
- id: ch18-6-provider
uri: http://localhost:8000/hello/rateLimit
order: 0
predicates:
- Path=/client/**
更多关于 路由规则和 gateway的学习 请观看我好友的博客 :https://www.lhdyx.cn/article/84
测试
在启动 我们gateway 工程之前,要保证我们前置准备 都已经做好,然后启动 网关。
下面 访问:http://localhost:8081/client/hello/rateLimit ,然后用你那单身 20 多年的手速点击浏览器刷新按钮,看你一秒内能不能超过 5次,我可以,看图。
工程结构图,有需要加微信