Spring cloud gateway+apollo=bug?

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

spring cloud 版本

  • spring cloud: 2021.0.4
  • spring cloud gateway: 3.1.4

背景

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

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

实现需求

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

yaml 复制代码
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

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

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

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

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

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

apollo配置就有问题了?

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

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

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

导致判断

java 复制代码
if (responseTimeoutAttr != null && responseTimeoutAttr instanceof Number)

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

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

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

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

解决方式

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

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

然后新建类NettyRoutingFilter

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

java 复制代码
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();
    }

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

这样就解决了

总结

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

相关推荐
用户83562907805117 分钟前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我1234520 分钟前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒22 分钟前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记28 分钟前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk5987833 分钟前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端
雨中飘荡的记忆34 分钟前
Claude Code 入门必会:@、!、Slash Commands,一篇讲清楚
人工智能·后端
用户8356290780511 小时前
如何使用 Python 在 Word 文档中创建和格式化列表
后端·python
开心就好20251 小时前
uni-app 本地打包 iOS,在 Windows 上使用 KXBuild 产出 ipa 并上架的完整流程
后端·ios
百慕大三角1 小时前
从 CLAUDECODE 到 AI_AGENT:前端与 CLI 工具如何感知 AI 编码代理?
人工智能·后端·全栈
旋律4142 小时前
同义方法区别(增加类与删除类)
java·后端