最近升级springboot3、springcloud微服务真是一挖一个坑,特此记录一下
一、openfeign 循环依赖问题
springcloud升级到 2022.0.4 后,启动项目发现提示 循环依赖 异常。
从上面图也能清楚地看到,就是A依赖B,B依赖C,C又依赖A,导致循环依赖。
翻查了一下github的 issue ,发现有人也遇到此类问题,如下图,原来早在2019年的时候,已经是不支持在 filter 里面使用 feign 调用了。
而且在2020版的 Spring Cloud Gateway 也已经移除了 robbion。
目前能找到的解决方式有两种:
1)改用 webclient
提及比较多的是这个项目 feign-reactive ,但是对于笔者而已对现有项目的改动比较大,最终没有采纳,大家有兴趣可以看看。
这里也有一篇文章有介绍如何使用 Reactive Feign
2)使用 @Lazy 注解
这个估计是目前最简单的方式,使用的延迟加载的方式来规避
刚好,给我发现了一篇文章,说到了这个类似的问题的原因,博主一步步debug源码分析,传送门
大致的问题出在框架本身、 feign client 加载 、过滤器加载顺序有关,导致最终被加载了两次,具体的分析方法文章博主也很详细的说明,在此就不再描述。
这里也有一篇文章是关于 GatewayAutoConfiguration 源码分析,有兴趣的也可以看一下。
二、异步问题
如果使用 @Lazy 注解方式来解决 循环依赖问题,那么马上又迎来第二个问题,异步调用问题。
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:83)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.web.cors.reactive.CorsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP GET "/api/users/getUserInfo" [ExceptionHandlingWebHandler]
原因是,不能在Spring Cloud Gateway中使用同步调用,而普通的feign调用又是同步的。升级后的组件已经开始使用 webflux 响应式开发,走的异步方式提升性能,对于使用阻塞的请求全部会抛异常,哪怕是同步的http请求也不行。
解决方式目前有两种:
1)使用 webclient,接入 ReactiveFeign
2)强制同步转异步,将 feign 调用封装成异步任务
这是曲线救国的方法,使用 Future 方式包装一层feign调用,其实际还是同步阻塞请求。
//获取账号
CompletableFuture<PlatformAccountResponse> platformAccountResponseCompletableFuture = CompletableFuture.supplyAsync(() -> {
PlatformAccountResponse platformAccountResponse = cloudPlatformAccountService.queryByDeviceId(deviceId);
return platformAccountResponse;
});
//阻塞同步获取返回结果
PlatformAccountResponse response = platformAccountResponseCompletableFuture.get();
三、shiro 鉴权
本想着使用 shiro 鉴权,然后发现 shiro 必须使用web-mvc(依赖spring-boot-starter-web),但是web-mvc与web-flux不兼容,而springcloud-gateway必须依赖web-flux,所以shiro无法集成到springcloud-gateway,会失效。
好家伙,还好在整合前先了解了一下...