前言
最近在SpringCloudGateway网关加上动态路由和限流的功能,使用RequestRateLimiter配置令牌桶时,启动应用报了异常,异常信息为Unable to find GatewayFilterFactory with name RequestRateLimiter
exception.jpg原因是:引入
org.springframework.boot:spring-boot-starter-data-redis-reactive
依赖时,排除了lettuce-core依赖(当时一个同事使用Lettuce操作Redis遇到问题,排除这个依赖使用Jedis了),导致生成RequestRateLimiterGatewayFilterFactory实例的时候生成不了,但是项目中又配置了限流,导致获取限流的Factory获取不到。
删除掉排除的lettuce-core依赖即可恢复正常。
定位过程
看到一个异常,一般先根据异常堆栈找到报错的代码,然后再报错代码附近打上断点进行Debug,根据报错信息往上一层层推,有一部分可能源码调用链嵌套很多,很难找出报错的代码,另一种方法就是根据报错的Message直接搜项目代码(包括Jar包里面,搜索不能完全用报错信息搜,拷贝部分报错信息,因为有些是变量拼接的,一部分一部分试)。
在这个问题里面,我是直接搜索异常信息,搜索 Unable to find
search.jpg发现是在 RouteDefinitionRouteLocator类的loadGatewayFilters方法中,直接打上断点去调试
loadGatewayFilters.jpgfatory是从当前类的gatewayFilterFactories中去取的,然后看下这个属性是如何初始化的
RouteDefinitionRouteLocator-constructor.jpg这个属性也是从其他类传进来的,只是将传进来的GatewayFilterFactory的List转成Map,在往上看
GatewayAutoConfiguration.jpg是在GatewayAutoConfiguration配置类里面进行实例化RouteDefinitionRouteLocator类的,所以gatewayFilters是每个GatewayFilterFactory通过配置导入到Spring容器的,我们直接看限流使用到的RequestRateLimiterGatewayFilterFactory是在哪配置的,搜索这个类使用情况,发现是在GatewayAutoConfiguration类中配置的,配置代码如下
RequestRateLimiterGatewayFilterFactory.jpg可以看到这里注入和很多(截图只截了三个)GatewayFilterFactory,RequestRateLimiterGatewayFilterFactory这个Bean的实例化是依赖RateLimiter的,因为限流默认是使用Redis的,直接看RedisRateLimiter这个类的配置,搜索这个类的使用情况,是在GatewayRedisAutoConfiguration类中配置的
RedisRateLimiter.jpgRedisRateLimiter这个Bean又依赖ReactiveStringRedisTemplate,ReactiveStringRedisTemplate这个类是在RedisReactiveAutoConfiguration类中配置的
ReactiveStringRedisTemplate.jpgReactiveStringRedisTemplate又依赖于ReactiveRedisConnectionFactory,这个Redis连接工厂唯一的实现类是LettuceConnectionFactory,LettuceConnectionFactory是基于Lettuce的,所以这个bean是不会实例化的,层层依赖导致RequestRateLimiterGatewayFilterFactory创建不了实例。
总结
遇到问题及时解决,不应该在项目中留下隐患,可能会给其他人员带来很大的技术债。
解决问题时一步步调试,多DEBUG,DEBUG过程中会对变量、方法调用过程有更清晰的认识,比如刚开始抛异常时,new RequestRateLimiterGatewayFilterFactory这句代码是不会跑的,即使打了断点,但是new其他的GatewayFilterFactory我也打了断点试了,却是会跑的,就把方向放在了RequestRateLimiterGatewayFilterFactory这个类的实例化上,再一步步往下调,所以我截图上代码基本都是有断点的。
网友评论