其实网关是很强大,能做的事情很多,包含很多过滤器包括限流,具体的网关可以参考我的另外一篇博文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
上面的代码块通过熔断器这种超时实现,其实上面这样的配置是不会生效的,通过配置文件其实想要通过hystrx的线程隔离模式,但是呢,这样的配置不会生效的,这个地方很多人都会陷入误区,首先呢,hystrx在springcloud中要不被feign整合,要不被gateway整合,前者默认是线程池,后置默认是信号量,具体两者的区别,信号量是单线程不会涉及到header上下文传递,但是呢性能不好,线程池呢会涉及到上下文传递问题,这个地方我就不会扩散了
线程池资源隔离模式
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());
};
}