微服务架构-服务网关(Gateway)-网关层限流

  • Post author:
  • Post category:其他




网关层限流

前面一节我们学习了如何在网关层对服务调用异常做统一封装,这一节我们来了解一下Gateway的另一个用法——限流。

前面的小节我们都是采用的基于Java代码的路由规则,这次我们换个路子,用基于yml 的配置方式配置路由规则,这两种式只是配置形式不同,但效果是一样的,而且Gateway中可以同时使用这两种方式做配置,在yml和Java中的配置规则都会生效。



1、网关限流三步走

这里采用令牌桶计数的方式做限流,问: 把客户请求放到令牌桶,总共分几步? 三步



1.1)准备工作

我们的Best Practice是基于Redis来实现限流,因此要保证本地启动了Redis服务,同时将下列配置加入到Gateway的配置文件中:

spring:
  application:
    name: gateway-service
  redis:
      host: localhost
      port: 6379
      database: 0

这里是配置Redis连接信息的,假如你不配置的话,Gateway也会尝试用默认配置项来连接Redis,但如果你在Redis配置信息中提供了错误的IP或者Potr的话,调用方法时依然会成功,不过限流功能就失效了,因为底层的Netty服务无法连接到Redis,也就无法提供限流支持。但GateWay为了保证服务可用性,限流功能的异常并不会阻碍正常的方法调用。



1.2)Key Resolver

Gateway的限流组件要求定义一个Key Resolver用来对每次路由请求生成一个Key,这Key就是一个限流分组的标识,每个Key相当于一个令牌桶。假如我们限定了一个服务每秒只解被调用3次,这个限制会对不同的Key单独计数、我们把调用方机器的Host Name作为限流Key,那么来自同一台机器的调用将落到同一个Key下面,也就是说在这个场景下,每台机器都独立计算单位时间调用量。

创建Key Resolver的方式很简单:

@Bean
public KeyResolver remoteAddrKeyResolver() {
    return exchange -> Mono.just(
        exchange.getRequest().getRemoteAddress().getHostName());
}

上面的例子创建了基于Host Name的今牌生成器,我们可以根据自己的业务来选择合适的Key,比如说可以在接口层面做限流(使用接口的Path作为Key),还可以从Request中提取业务字段作为Key (比如用户ID等)。



1.3)配置过滤器

spring:
  cloud:
    gateway:
      routes:
      - id:  feignapi
        uri: lb://FEIGN-SERVICE-PROVIDER
        predicates:
        - Path=/feign-api/**
        filters:
        - StripPrefix=1
        - name: RequestRateLimiter
          args:
            key-resolver: '#{@remoteAddrKeyResolver}'
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20

在上面的限流配置中,我们主要关注最后3行中的属性:

  • **key-resolver:**这里注入的就是在上一步中我们定义的Key Resolver,它使用SpEL表达式从Spring上下文中获取指定Bean;
  • **replenishRate:**今牌桶每秒的平均填充速度;

  • burstCapacity:

    今牌桶总量



版权声明:本文为jianghao233原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。