Spring Cloud Gateway 04 扩展

Spring Cloud Gateway 04 扩展

参考:
https://cloud.tencent.com/developer/article/1538107
https://blog.51cto.com/zero01/2430532

一、Spring Cloud Gateway 的监控端点

说到监控,就应该能想到Spring Boot Actuator。而Spring Cloud Gateway基于Actuator提供了许多的监控端点。只需要在项目中添加spring-boot-starter-actuator依赖,并将 gateway 端点暴露,即可获得若干监控端点。配置示例:
==spring-cloud-gateway-server 4.x ==

management:
  endpoint:
    gateway:
      enabled: true
  endpoints:
    web:
      exposure:
        include: gateway  # 或者配置“*”暴露全部端点

Spring Cloud Gateway的监控端点如下表:

端点请求方法描述
globalfiltersGET展示所有的全局过滤器信息
routefiltersGET展示所有的过滤器工厂信息
refreshPOST(无消息体)清空路由缓存,即刷新路由信息
routesGET展示所有的路由信息列表
routes/{id}GET展示指定id的路由的信息
routes/{id}POST(有消息体)新增一个路由
routes/{id}DELETE(无消息体)删除一个路由

Gateway所有的监控端点都挂载在 /actuator/gateway 路径下

  1. 查看 gateway 下的挂载点
  • http://127.0.0.1:{{port}}/actuator/gateway
[{"href": "/actuator/gateway/routedefinitions", "methods": [GET"]},
{"href": "/actuator/gateway/globalfilters", "methods": ["GET"]},
{"href": "/actuator/gateway/routefilters", "methods": ["GET"]},
{"href": "/actuator/gateway/routes/ReactiveCompositeDiscoveryClient_YUNJIAN.ZK.GATEWAY/combinedfilters", "methods": ["GET"]},
{"href": "/actuator/gateway/routes/ReactiveCompositeDiscoveryClient_YUNJIAN.ZK.SYSTEM/combinedfilters", "methods": ["GET"]},
{"href": "/actuator/gateway/routes/test/combinedfilters", "methods": [GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.system/combinedfilters", "methods": [GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.wechat/combinedfilters", "methods": [GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.dev.tool/combinedfilters", "methods": [GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.mail/combinedfilters", "methods": [GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.file/combinedfilters", "methods": [GET"]},
{"href": "/actuator/gateway/routes", "methods": [POST",GET"]},
{"href": "/actuator/gateway/routes/ReactiveCompositeDiscoveryClient_YUNJIAN.ZK.GATEWAY", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/ReactiveCompositeDiscoveryClient_YUNJIAN.ZK.SYSTEM", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/test", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.system", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.wechat", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.dev.tool", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.mail", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/routes/yunjian.zk.file", "methods": [POST",DELETE",GET"]},
{"href": "/actuator/gateway/", "methods": [GET"]},
{"href": "/actuator/gateway/routepredicates", "methods": [GET"]},
{"href": "/actuator/gateway/refresh", "methods": [POST"]}]

例如globalfilters端点的完整访问路径是 /actuator/gateway/globalfilters。该端点主要是查看Gateway启用了哪些全局过滤器以及它们的执行顺序(数字越小越优先执行)。
2. 查看Gateway启用的全局过滤器

  • http://127.0.0.1:{{port}}/actuator/gateway/globalfilters
    结果如下:
{
    "org.springframework.cloud.gateway.filter.NettyRoutingFilter@2fb70301": 2147483647,
    "org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@34b462e0": 10000,
    "org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter@53d808ea": 10150,
    "org.springframework.cloud.gateway.filter.ForwardRoutingFilter@1e592ef2": 2147483647,
    "org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@3bbc47c9": -1,
    "org.springframework.cloud.gateway.filter.ForwardPathFilter@6bf77ee": 0,
    "org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@71f4aeb6": -2147482648,
    "org.springframework.cloud.gateway.filter.GatewayMetricsFilter@25109d84": 0,
    "org.springframework.cloud.gateway.filter.LoadBalancerServiceInstanceCookieFilter@404dc999": 10151,
    "org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@c3d4bd7": 2147483646,
    "org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@5b0575d0": -2147483648
}
  1. 查看 Gateway 启用的过滤器工厂
  • http://127.0.0.1:{{port}}/actuator/gateway/routefilters
{
    "[RemoveRequestParameterGatewayFilterFactory@6296e4bf configClass = AbstractGatewayFilterFactory.NameConfig]": null,
    "[SetPathGatewayFilterFactory@33a8f553 configClass = SetPathGatewayFilterFactory.Config]": null,
    "[CacheRequestBodyGatewayFilterFactory@43f7f48d configClass = CacheRequestBodyGatewayFilterFactory.Config]": null,
    "[RewritePathGatewayFilterFactory@71d78cac configClass = RewritePathGatewayFilterFactory.Config]": null,
    "[ModifyRequestBodyGatewayFilterFactory@dd77e0d configClass = ModifyRequestBodyGatewayFilterFactory.Config]": null,
    "[RetryGatewayFilterFactory@6e12f38c configClass = RetryGatewayFilterFactory.RetryConfig]": null,
    "[SaveSessionGatewayFilterFactory@176e839e configClass = Object]": null,
    "[AddRequestHeaderGatewayFilterFactory@61fa3583 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
    "[AddRequestParameterGatewayFilterFactory@1abbc1d4 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
    "[RequestSizeGatewayFilterFactory@4866e0a7 configClass = RequestSizeGatewayFilterFactory.RequestSizeConfig]": null,
    "[SetResponseHeaderGatewayFilterFactory@240291d9 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
    "[RequestHeaderToRequestUriGatewayFilterFactory@16361e61 configClass = AbstractGatewayFilterFactory.NameConfig]": null,
    "[PrefixPathGatewayFilterFactory@1e14b269 configClass = PrefixPathGatewayFilterFactory.Config]": null,
    "[SetRequestHeaderGatewayFilterFactory@284b487f configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
    "[AddRequestHeadersIfNotPresentGatewayFilterFactory@2a19c36b configClass = Object]": null,
    "[RewriteLocationResponseHeaderGatewayFilterFactory@451a4187 configClass = RewriteLocationResponseHeaderGatewayFilterFactory.Config]": null,
    "[RemoveRequestHeaderGatewayFilterFactory@23dc70c1 configClass = AbstractGatewayFilterFactory.NameConfig]": null,
    "[AddResponseHeaderGatewayFilterFactory@4b20aa21 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
    "[DedupeResponseHeaderGatewayFilterFactory@4eec5fa6 configClass = DedupeResponseHeaderGatewayFilterFactory.Config]": null,
    "[RedirectToGatewayFilterFactory@2a0ce342 configClass = RedirectToGatewayFilterFactory.Config]": null,
    "[RemoveJsonAttributesResponseBodyGatewayFilterFactory@3cae4518 configClass = Object]": null,
    "[RewriteRequestParameterGatewayFilterFactory@3340ff7c configClass = RewriteRequestParameterGatewayFilterFactory.Config]": null,
    "[MapRequestHeaderGatewayFilterFactory@364c93e6 configClass = MapRequestHeaderGatewayFilterFactory.Config]": null,
    "[StripPrefixGatewayFilterFactory@52963839 configClass = StripPrefixGatewayFilterFactory.Config]": null,
    "[RewriteResponseHeaderGatewayFilterFactory@6ee186f3 configClass = RewriteResponseHeaderGatewayFilterFactory.Config]": null,
    "[SetRequestHostHeaderGatewayFilterFactory@2b4954a4 configClass = SetRequestHostHeaderGatewayFilterFactory.Config]": null,
    "[SecureHeadersGatewayFilterFactory@6b94c200 configClass = SecureHeadersGatewayFilterFactory.Config]": null,
    "[RequestHeaderSizeGatewayFilterFactory@6b6c0b7c configClass = RequestHeaderSizeGatewayFilterFactory.Config]": null,
    "[ModifyResponseBodyGatewayFilterFactory@65c689e7 configClass = ModifyResponseBodyGatewayFilterFactory.Config]": null,
    "[SetStatusGatewayFilterFactory@60fe75f7 configClass = SetStatusGatewayFilterFactory.Config]": null,
    "[RemoveResponseHeaderGatewayFilterFactory@4d3990a5 configClass = AbstractGatewayFilterFactory.NameConfig]": null,
    "[PreserveHostHeaderGatewayFilterFactory@77d3c3d7 configClass = Object]": null
}
  1. 查看 Gateway里定义的路由
  • http://127.0.0.1:{{port}}/actuator/gateway/routefilters
[{
    "predicate": "Paths: [/test/baidu], match trailing slash: true",
    "route_id": "test",
    "filters": ["[[StripPrefix parts = 2], order = 1]"],
    "uri": "https://www.baidu.com:443",
    "order": 0
} ... ]

二、Spring Cloud Gateway 限流相关

在高并发的系统中,限流往往是一个绕不开的话题,我们都知道网关是流量的入口,所以在网关上做限流也是理所当然的。Spring Cloud Gateway内置了一个过滤器工厂,用于提供限流功能,这个过滤器工厂就是是RequestRateLimiterGatewayFilterFactory,该过滤器工厂基于令牌桶算法实现限流功能。

目前,该过滤器工厂默认使用 RedisRateLimiter 作为限速器,需要依赖Redis来存储限流配置,以及统计数据等。当然你也可以实现自己的RateLimiter,只需实现 org.springframework.cloud.gateway.filter.ratelimit.RateLimiter 接口,或者继承 org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter抽象类

Tips:

动手实践
  1. 添加Redis依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
  1. 添加 redis 配置:
spring:
  cloud:
    gateway:
      routes:
        - id: user-center
          uri: lb://user-center
          predicates:
            - Path=/user-center/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                # 令牌桶每秒填充平均速率
                redis-rate-limiter.replenishRate: 1
                # 令牌桶的上限
                redis-rate-limiter.burstCapacity: 2
                # 使用SpEL表达式从Spring容器中获取Bean对象
                key-resolver: "#{@pathKeyResolver}"
  # redis相关              
  redis:
    host: 127.0.0.1
    port: 6379
  1. 编写一个KeyResolver,用于定义针对什么进行限流。例如按照访问路径限流,就写一个针对访问路径的KeyResolver;按照请求参数限流,那就写一个针对请求参数的KeyResolver,以此类推。这里我们按照访问路径限流,具体实现代码如下:
@Configuration
public class RaConfiguration {

    /**
     * 按照Path限流
     *
     * @return key
     */
    @Bean
    public KeyResolver pathKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest()
                        // 获取path
                        .getPath()
                        .toString()
        );
    }
}

从代码的实现不难看出,实际就只是返回了一个访问路径,这样限流规则就会作用到访问路径上。例如访问:http:// G A T E W A Y U R L / u s e r s / 1 ,对于这个路径,它的 r e d i s − r a t e − l i m i t e r . r e p l e n i s h R a t e = 1 , r e d i s − r a t e − l i m i t e r . b u r s t C a p a c i t y = 2 。访问: h t t p : / / {GATEWAY_URL}/users/1,对于这个路径,它的redis-rate-limiter.replenishRate = 1,redis-rate-limiter.burstCapacity = 2。 访问:http:// GATEWAYURL/users/1,对于这个路径,它的redisratelimiter.replenishRate=1redisratelimiter.burstCapacity=2。访问:http://{GATEWAY_URL}/shares/1,对于这个路径,它的redis-rate-limiter.replenishRate = 1,redis-rate-limiter.burstCapacity = 2;以此类推…

测试

接下来进行一个简单的测试,看看限流是否起作用了。持续频繁访问某个路径,当令牌桶的令牌被消耗完了,就会返回 429 这个HTTP状态码。


若有凝问或错误,请指出,我好及时改正,让我们一起进步!
email : binary_space@126.com
qq : 103 586 2795
敲门砖: 代码谱写人生

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

征客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值