其实网关是很强大,能做的事情很多,包含很多过滤器包括限流,具体的网关可以参考我的另外一篇博文Spring Cloud GateWay-过滤器
今天我们来说下网关如何限流,主要两种方案:
Spring Cloud GateWay整合hystrx
environment: test
management:
security:
enabled: false
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
default-property-inclusion: NON_NULL
time-zone: GMT+8
servlet:
multipart:
file-size-threshold: 100MB
max-file-size: 4GB
max-request-size: 4GB
thymeleaf:
cache: false
mode: LEGACYHTML5
cloud:
# 服务发现
nacos:
discovery:
server-addr: nacos-headless.ota.svc.cluster.local:8848 #服务端url
namespace: ota-prd
gateway:
discovery:
locator:
enabled: true
enabled: true
routes:
# 公共服务 基础数据 base服务
- id: vota-api-core
uri: lb://vota-api-core
predicates:
- Path=/mgapi/vota-api-core/**
filters:
- name: Hystrix
args:
name: vota-api-core
fallbackUri: forward:/fallback
- name: StripPrefix
args:
parts: 2
- name: SessionAccess
args:
ignorePath:
- /mgapi
- /static
- /client-api
- /busi
- /zuul
vota-api-core:
ribbon:
ConnectTimeout: 500
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: true
ReadTimeout: 3600000
hystrix:
command:
vota-api-core:
execution:
isolation:
thread:
timeoutInMilliseconds: 2401000
其实上面如何需要整合hystrix的信号量模式 ,在 application.yml 或 application.properties 文件中配置 Hystrix 的命令属性比较完整的
hystrix:
command:
default:
execution:
isolation:
# 设置隔离策略为信号量隔离(semaphore isolation)
strategy: SEMAPHORE
semaphore:
# 设置信号量隔离的最大并发请求数
maxConcurrentRequests: 10
# 设置超时时间
timeout:
isolation:
thread:
timeoutInMilliseconds: 1000
circuitBreaker:
# 是否启用断路器
enabled: true
# 请求阈值,当在统计窗口内请求次数达到此值后,断路器才开始生效
requestVolumeThreshold: 20
# 统计窗口时间长度,单位为毫秒
sleepWindowInMilliseconds: 5000
# 错误率阈值,当在统计窗口内的错误率超过此值,断路器将打开
errorThresholdPercentage: 50
# 是否启用请求缓存
requestCache:
enabled: true
metrics:
# 设置滑动窗口大小,用于统计请求和错误率
rollingStats:
# 滑动窗口的大小,单位为秒
timeInMilliseconds: 10000
# 滑动窗口的分割数量
numberOfBuckets: 10
maxConcurrentRequests: 设置信号量隔离的最大并发请求数,超过这个数量的请求将被立即拒绝。
timeoutInMilliseconds: 设置命令执行的超时时间,单位为毫秒,超时后将触发断路器或回退逻辑。
requestVolumeThreshold: 断路器生效前的最小请求量,只有当在统计窗口内的请求次数达到此值,断路器的统计和规则才会生效。
sleepWindowInMilliseconds: 断路器打开后的休眠窗口时间,单位为毫秒,在这段时间内,断路器将保持打开状态,不接受新的请求。
errorThresholdPercentage: 错误率阈值,当在统计窗口内的错误率超过此值,断路器将打开。
enabled: 控制断路器和请求缓存的开关注意事项:
1、上面的代码块通过熔断器这种超时实现,其实上面这样的配置是不会生效的,通过配置文件其实想要通过hystrx的线程隔离模式,但是呢,这样的配置不会生效的,这个地方很多人都会陷入误区,首先呢,hystrx在springcloud中要不被feign整合,要不被gateway整合,前者默认是线程池,后置默认是信号量,具体两者的区别,信号量是单线程不会涉及到header上下文传递,但是呢性能不好,线程池呢会涉及到上下文传递问题,这个地方我就不会扩散了
2、这些配置适用于所有使用默认配置的 Hystrix 命令。如果你想为特定的命令配置不同的属性,可以使用命令的名称替换 default,例如 hystrix.command.myCommandName,比如hystrix.command.vota-api-core
3、当使用信号量隔离策略时,maxConcurrentRequests 是一个重要的配置,它决定了在任何给定时刻可以并发执行的请求数量。断路器的配置 (circuitBreaker) 用于控制何时以及如何打开和关闭断路器,以保护服务免受故障传播的影响
4、请求缓存 (requestCache) 可以减少对后端服务的重复调用,当相同的输入再次请求时,直接从缓存中返回结果
线程池资源隔离模式
hystrix:
command:
vota-api-core:
execution:
isolation:
strategy: THREAD
timeoutInMilliseconds: 2401000
这样明确指定了隔离模式才行,否则还是走的默认的,而且只有线程池资源隔离才会有超时概念,否则信号量资源隔离是没有的 ,只有并发数的配置
信号量资源隔离模式
hystrix:
command:
vota-api-core:
execution:
isolation:
strategy: SEMAPHORE
semaphore:
maxConcurrentRequests: 10
timeoutInMilliseconds: 2401000
这里默认是10,可以调整的50/100,上面这两种配置都是整合hystrx的,但是目前hystrx是Netflix旗下的组建以及不维护了,现在启用的都是CircuitBreaker
spring:
application:
name: vota-api-gateway
cloud:
gateway:
discovery:
locator:
# 表明 Gateway 开启服务注册和发现的功能,并且 Spring Cloud Gateway 自动根据服务发现为每一个服务创建了一个 router,这个 router 将以服务名开头的请求路径转发到对应的服务
enabled: true
# 是将请求路径上的服务名配置为小写(因为服务注册的时候,向注册中心注册时服务名被转成大写了)
lower-case-service-id: true
routes:
- id: vota-api-proxy
uri: lb://vota-api-core/v50/vehicle/api/
predicates:
# - Path=/v50/vehicle/api/register,/v50/vehicle/api/{segment}/current/time
- Path=/v50/vehicle/api/**
- Method=POST
filters:
- name: CircuitBreaker
args:
name: fallbackCmdA
fallbackUri: forward:/fallbackA
- name: RequestRateLimiter
args:
# 解析限流 Key 的 Bean 对象的名字,使用 SpEL 表达式
key-resolver: '#{@vehicleKeyResolver}'
# 限流实现
rate-limiter: '#{@redisRateLimiter}'
# 令牌桶每秒填充平均速率
redis-rate-limiter.replenishRate: 2000
# 令牌桶总容量
redis-rate-limiter.burstCapacity: 5000
public static void main(String[] args) {
SpringApplication.run(VehicleGatewayApplication.class, args);
}
/**
* <p>限流和防重放的区别,分别的定义</p>
* <p>令牌桶限流</p>
* <p>注册接口使用 REGISTER + vin 作为 Key</p>
* <p>非注册接口使用 API_NAME + deviceId 作为 Key</p>
* <p>令牌桶算法基于 Lua + Redis 实现,Lua 脚本位置为:spring-cloud-gateway-core-2.1.5.RELEASE
* .jar/META-INF/scripts/request_rate_limiter.lua</p>
* <p>如需自定义算法,则继承 AbstractRateLimiter 类</p>
*
* @return KeyResolver
* @see org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter
* @see org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory
*/
@Bean
public KeyResolver vehicleKeyResolver() {
return exchange -> {
String value = exchange
.getRequest()
.getPath()
.value();
return Mono.just(exchange.getRequest().getPath().value());
};
}