IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringCloud 2021.0.1 SpringCloudGateway 3.1.1新版中GlobalFilter使用OpenFeign失败(503)的问题 -> 正文阅读

[Java知识库]SpringCloud 2021.0.1 SpringCloudGateway 3.1.1新版中GlobalFilter使用OpenFeign失败(503)的问题

SpringCloud 2021.0.1 SpringCloudGateway 3.1.1新版中GlobalFilter使用OpenFeign失败的问题

简单说下好了,这个问题其实在springCloud移除ribbon之后就出现的
之前我用的版本是SpringCloud Hoxton.SR8,具体这个版本里还有没有ribbon也没有去看了,反正这会在gateway里使用feign是没有任何问题的
也可能依赖中单独添加了ribbon没注意,这不因为springCloudGateway爆出来的漏洞嘛(某台生产服务器已经被黑过,
直接往redis里搞了一条gateway的路由信息,导致整个应用进不去,还好这个大哥只是试试水,别的并没有干什么),所以无奈必须升级

各依赖版本

SpringCloud : 2021.0.1 对应gateway是3.1.1
alibabaNacos: 2021.1
springBoot: 2.6.6 (这个也是因为漏洞问题,虽然没说非war包会不会咋样,一并升了吧,之前用的2.5.1版本并不低,升级不算太困难,如果是2.3.0以下的小伙伴可就有的折腾了)

这里只说明升级之后SpringCloudGateway的使用openFeign(3.1.1)的问题
首先,可以完全确认,上面版本中无论是springCloud还是nacos,都已经没有集成任何默认的负载均衡组件,所以升级后第一件事就是添加一个负载均衡组件,否则启动不了或者是无法路由服务,ribbon已被抛弃,直接引入spring-cloud-loadbalancer即可(每个服务都要依赖)

		<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-loadbalancer</artifactId>
             <version>3.1.1</version>
        </dependency>

然后就是openFeign在网关过滤器中的使用问题,我想应该大多数人用gateway处理鉴权应该都是实现的GlobalFilter这个接口来做的过滤器吧,问题就出在这里了,其他版本我不清楚,没有一一尝试了

但是3.1.1这个版本,无论你用webClient也好,还是把feign单独用异步Future包裹一道也罢你不管作何处理,在GlobalFilter的实现类中,要么一直503,要么每次启动第一次可以正常使用feign调取到其他服务数据,后面继续503,没有任何出路,不用费心研究添加Decoder的bean,改写服务接口,@Autowired的时候加@Lazy,甚至使用冷门的reactive-feign组件,以上现象并不会得到任何改变。虽然官方的git的issure里好像是提过一下webClient可以解决第一次可用,后续不可用的问题,但是亲身实践,并不可行,别说用webClient取代feign去调用服务,就算你服务也是web-flux的,都不行。

唯一解法只有一个,修改实现接口,改成WebFilter,这个接口和GlobalFilter基本一致,除了参数有一个不一样,还有ServerWebExchange中某些gateway封装的请求头不及GlobalFilter全面以外,其他暂时没有发现太大区别

// 这是GlobalFiter的filter方法
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
// 这是WebFilter的filter方法
Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
// 基本没什么变化,内部代码也几乎不用更改,除了部分固定请求头,比如获取一些固定请求头在WebFilter里可能不存在
exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
// 这两个可能比较常用一点,这两个反正是获取不到的,没有挨个试过,暂且理解为ServerWebExchangeUtils里的几个常量请求头都没法获取吧
// 毕竟GlobalFiter和WebFilter是异步两条线程在执行的,这些请求头多数是默认GlobalFilter里定义的

这里改了之后,也还是不能直接@Autowired一个Feign来使用,倒是没出现其他文章里说的无法启动网关之类的问题,但是调用的时候会直接报下图异常
在这里插入图片描述
所以还差一步,把需要使用的feign,包裹一层Future。

@Component
public class FeignHolder {

    @Autowired
    @Lazy
    private AuthFeign authFeign;
    @Async
    public Future<AuthenDTO> isLogin(String token){
        AuthenDTO dto = FeignReturnDataGzip.Unzip(authFeign.isLogin(token), AuthenDTO.class);
        return new AsyncResult<>(dto);
    }

    @Async
    public Future<CurrentUser> getLoginUserInfo(String token){
        CurrentUser currentUser = FeignReturnDataGzip.Unzip(authFeign.getLoginUserInfo(token), CurrentUser.class);
        return new AsyncResult<>(currentUser);
    }
}

然后可以在网关过滤器中直接注入FeignHolder

@Component
public class GatewayAuthorizationFilter implements WebFilter, Ordered {
	
	@Autowired
    private FeignHolder feignHolder;
    
	@Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    	...
    	Future<AuthenDTO> authFuture = feignHolder.isLogin(token);
        AuthenDTO authenDTO;
        try {
            authenDTO = authFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            authenDTO = new AuthenDTO();
            log.error("[鉴权中心]调用鉴权中心Feign失败,失败原因:{},失败信息:{}", e.getClass().getSimpleName(), e.getMessage());
        }
    	...
    }
}

这样来处理之后,即可正常使用,网关建议都单独添加一个类似FeignHolder的配置类来统一处理openFeign调用,当然也可以直接使用
com.playtika.reactivefeign这个组件(国内外范围内参考资料都超级少,官方git说明也不是很全面,上手难度很高.),这个版本的网关中凡是使用openFeign的地方,必须要异步处理,不能同步调用feign接口,否则都会抛出异常

java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, 
which is not supported in thread xxxx-xxxx-xxxx

另外不要相信使用SpringApplicationContext来获取bean/service就能不使用异步,只要你请求了其他服务,并且使用的是spring-cloud-loadbalancer作负载均衡,就必须异步调用,使用ribbon情况会不会有所不同就说不准了,有兴趣的自己试下吧

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:29:56  更:2022-08-06 10:32:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:05:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码