1.前言
本章将介绍OCP开源项目:Spring Cloud Gateway模块中动态路由的实现。
2. Spring Cloud Gateway
Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API,并为他们提供横切关注点,例如:安全性,监控/指标和弹性。
2.1 Spring Cloud Gateway特征
- 基于Spring Framework 5,Project Reactor和Spring Boot 2.0构建
- 能够匹配任何请求属性上的路由。
- 谓词和过滤器特定于路线。
- Hystrix断路器集成。
- Spring Cloud DiscoveryClient集成
- 易于编写谓词和过滤器
- 请求率限制
- 路径重写
2.2 项目实战
接下来,开始我们的 Spring Cloud Gateway 限流之旅吧!
2.2.1 Spring Cloud Gateway 限流
2.2.2 OCP子项目new-api-gateway
pom.xml
org.springframework.boot spring-boot-starter-data-redis-reactiveorg.springframework.boot spring-boot-starter-webfluxorg.springframework.cloud spring-cloud-starter-gatewayorg.springframework.boot spring-boot-starter-actuatororg.springframework.cloud spring-cloud-starter-netflix-hystrix
2.2.3 配置HostName的规则限流
目前只对user-center用户中心进行限流
spring: cloud: gateway: discovery: locator: lowerCaseServiceId: true enabled: true routes: # ===================================== - id: api-eureka uri: lb://eureka-server order: 8000 predicates: - Path=/api-eureka/** filters: - StripPrefix=1 - name: Hystrix args: name : default fallbackUri: 'forward:/defaultfallback' - id: api-user uri: lb://user-center order: 8001 predicates: - Path=/api-user/** filters: - GwSwaggerHeaderFilter - StripPrefix=1 - name: Hystrix args: name : default fallbackUri: 'forward:/defaultfallback' - name: RequestRateLimiter #对应 RequestRateLimiterGatewayFilterFactory args: redis-rate-limiter.replenishRate: 1 # 令牌桶的容积 放入令牌桶的容积每次一个 redis-rate-limiter.burstCapacity: 3 # 流速 每秒 key-resolver: "#{@ipAddressKeyResolver}" # SPEL表达式去的对应的bean
2.2.4 新增配置类RequestRateLimiterConfig
配置类新建在com.open.capacity.client.config路径下
package com.open.capacity.client.config;import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import reactor.core.publisher.Mono;/** * 定义spring cloud gateway中的 key-resolver: "#{@ipAddressKeyResolver}" #SPEL表达式去的对应的bean * ipAddressKeyResolver 要取bean的名字 * */@Configurationpublic class RequestRateLimiterConfig { /** * 根据 HostName 进行限流 * @return */ @Bean("ipAddressKeyResolver") public KeyResolver ipAddressKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); } /** * 根据api接口来限流 * @return */ @Bean(name="apiKeyResolver") public KeyResolver apiKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getPath().value()); } /** * 用户限流 * 使用这种方式限流,请求路径中必须携带userId参数。 * 提供第三种方式 * @return */ @Bean("userKeyResolver") KeyResolver userKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId")); }}
2.2.5 压力测试
接下来配置东西弄完之后 我们开始进行压力测试,压力测试之前,由于new-api-gateway有全局拦截器 AccessFilter 的存在,如果不想进行登录就进行测试的。先把
"/api-auth/**" 的判断中的注释掉。接下来我们开用postman进行测试
@Overridepublic Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { // TODO Auto-generated method stub String accessToken = extractToken(exchange.getRequest()); if(pathMatcher.match("/**/v2/api-docs/**