前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springcloud gateway代理get正常、post请求报错的问题

springcloud gateway代理get正常、post请求报错的问题

作者头像
天涯泪小武
发布2019-01-17 12:09:00
4.3K7
发布2019-01-17 12:09:00
举报
文章被收录于专栏:SpringCloud专栏SpringCloud专栏

在上一篇时,我们在使用gateway的反向代理功能时,发现了一个很严重的问题,那就是通过gateway去访问后端服务时,如果发起的是Get请求,就一切正常,如果是Post请求,就会报错。无论是使用什么filter。

代码语言:javascript
复制
java.lang.IllegalStateException: Only one connection receive subscriber allowed.
	at reactor.ipc.netty.channel.FluxReceive.startReceiver(FluxReceive.java:279) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.FluxReceive.lambda$subscribe$2(FluxReceive.java:129) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at reactor.ipc.netty.channel.FluxReceive$$Lambda$714/21949105.run(Unknown Source) [reactor-netty-0.7.10.RELEASE.jar:0.7.10.RELEASE]
	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:446) [netty-transport-4.1.29.Final.jar:4.1.29.Final]
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884) [netty-common-4.1.29.Final.jar:4.1.29.Final]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_40]

如果使用的是Springboot2.0.5之前的版本,不存在该问题,之后的但凡是非Get请求,就会报该错误。

该异常意思是请求体只能被消费一次,也就是说这个请求的body已经被读取过一次了,再次封装转发时会报错。这个问题比较怪异,很早之前我们知道@RequestBody接收的参数,是不能被读取第二次的,假如被网关的日志读取消费过了,那么后续的服务就无法再接收到该参数了。要想保持参数还在,就只能自己再去构造一个同样的RequestBody,发给后端的服务。但是,这次是普通的Post的form表单,居然也报这个错,就比较奇怪了。

gateway反向代理的原理是,首先读取原请求的数据,然后构造一个新的请求,将原请求的数据封装到新的请求中,然后再转发出去。

该错误是Springboot的升级导致的,具体的详细解析在https://github.com/spring-cloud/spring-cloud-gateway/issues/541

最终作者也给了解决方案

代码语言:javascript
复制
 @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
                return chain.filter(exchange);
            }
        };
    }

加上上面这一段就OK了。

实测,确实OK。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年10月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档