• Spring cloud gateway+apollo=bug?


    这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党

    spring cloud 版本

    • spring cloud: 2021.0.4
    • spring cloud gateway: 3.1.4

    背景

    最近在配置研究网关的超时时间,有这么一个需求。

    服务路由转发接口的超时时间总体是5s,但是部分特殊服务可能需要配置更长的超时时间,比如10s。

    实现需求

    要实现这个需求怎么处理呢?其实很简单,大致如下配置

    spring:
      cloud:
        gateway:
          httpclient:
            response-timeout: 3s
            pool:
              type: fixed
              max-connections: 200
              max-idle-time: 5000
              acquire-timeout: 10000
          routes: 
            - id: order-service
              predicates:
                - Path=/xiaozou/order-service/**
              filters:
                - StripPrefix=2
              uri: lb://order-service
            - id: pay-service
              predicates:
                - Path=/xiaozou/pay-service/**
              filters:
                - StripPrefix=1
              uri: http://localhost:9999/pay-service
              metadata:
                response-timeout: 5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    这里我们配置了两个服务路由order-servicepay-service

    配置了全局的请求超时时间

    spring.cloud.gateway.httpclient.response-timeout=3s

    然后配置了单个服务的超时时间5000(5s)

    正常看这个配置和操作是没问题

    apollo配置就有问题了?

    我们的配置中心使用的是apollo,所以配置都放在apollo

    然后我们通过debug查看源码NettyRoutingFilter发现一个bug

    在yaml配置的Integer类型变成string了

    导致判断

    if (responseTimeoutAttr != null && responseTimeoutAttr instanceof Number)
    
    • 1

    中的responseTimeoutAttr instanceof Number失效,从而导致metadata中配置的response-timeout失效

    这个是由于apollo底层实现使用了Properties作为配置存储,所以虽然在apollo解析yaml时能知道配置的类型(如Integer),但是在存储的时候都会统一转为String类型,如下图所示

    所以apollo在使用会有这个bug:@ConfigurationProperties注解导致类型从Integer转为String:https://github.com/apolloconfig/apollo/issues/2896

    感兴趣的可以查看这个issues,对此apollo并没有打算修复这个问题

    解决方式

    最简单的方式就是我们修改源码,这里就不用重新编译spring cloud gateway源码了

    我们直接在项目中新建一个org.springframework.cloud.gateway.filter

    然后新建类NettyRoutingFilter

    然后修改getResponseTimeout这个方法为如下

    private Duration getResponseTimeout(Route route) {
            Object responseTimeoutAttr = route.getMetadata().get(RESPONSE_TIMEOUT_ATTR);
            try {
                if (responseTimeoutAttr != null) {
                    long routeResponseTimeout = Long.parseLong((String) responseTimeoutAttr);
                    if (routeResponseTimeout >= 0) {
                        return Duration.ofMillis(routeResponseTimeout);
                    }
                    else {
                        return null;
                    }
                }
            } catch (Exception e) {
                log.error("get responseTimeoutAttr error, so use default responseTimeout, error ", e);
            }
            return properties.getResponseTimeout();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    核心是删除responseTimeoutAttr instanceof Number判断,添加类型转换

    这样就解决了

    总结

    我们在使用Apollo配置文件的时候一定要注意这个坑,就是@ConfigurationProperties注解导致类型从Integer转为String

  • 相关阅读:
    spyder打不开了
    c++进阶教程:我见过最好的c++教程
    安全好用性价比高的远程协同运维软件有吗?
    AMBA-CHI协议详解(三)
    go并发操作且限制数量
    【Webpack】样式处理 - 样式预处理
    Sql整理
    SaaS服务平台软件是什么?
    大数据毕业设计选题推荐-生产大数据平台-Hadoop-Spark-Hive
    国开现代汉语专题,形考答案形考任务
  • 原文地址:https://blog.csdn.net/qq_42651904/article/details/133023219