Connection closed prematurely
原因:提交参数,http请求链接过长导致网关报错。
生产环境出现的问题,在请求一个提交接口报的错,点进去看是netty报的错。各种官网搜索,都没找到合适解决方案,明明设置最大的请求连接长度为10M,但是4Mnetty就报错,是spring网关缺陷。
相关网关缺陷,参考:
https://github.com/spring-cloud/spring-cloud-gateway/issues/473
https://github.com/reactor/reactor-netty/issues/413
但是,没有提供怎么解决,spring也没有修复这个缺陷。
我的一个http请求,参数提交方式为formData,里面存在汉字,图片、地址等信息,导致链接长度达到4M。
formData的参数请求:
经过编码为:类似 B69%5D.items%5B139%5D.id=41&items%5B69%5D.items%5B139%5D.name=%E6%A3%80%E6%9F%A5%E9%A1%B9%E5%90%8D%E7%A7%B02&items%5B69%5D.items%5B139%5D.context=1%E3%80%81%E6%A3%80%E6%9F%A5%E5%86%85%E5% 的格式。每个字段上会多出一些东西。这样就很容易达到了4M。
B69%5D.items%5B139%5D.id=41&items%5B69%5D.items%5B139%5D.name=%E6%A3%80%E6%9F%A5%E9%A1%B9%E5%90%8D%E7%A7%B02&items%5B69%5D.items%5B139%5D.context=1%E3%80%81%E6%A3%80%E6%9F%A5%E5%86%85%E5%AE%B9%2F%E8%A6%81%E6%B1%822%0A2%E3%80%81%E6%98%AF%E5%90%A6%E5%AE%8C%E5%A5%BD&items%5B69%5D.items%5B139%5D.checkitemId=41&items%5B69%5D.items%5B139%5D.taskId=8442&items%5B69%5D.items%5B139%5D.pointId=104261&items%5B69%5D.items%5B139%5D.communityId=240111044332061479&items%5B69%5D.items%5B139%5D.status=0
2020-09-16 15:40:11.794 [reactor-http-client-epoll-16] ERROR [o.s.b.a.w.r.e.DefaultErrorWebExceptionHandler] - Failed to handle request [POST http://yuanqudev1.zuolin.com/evh/patrol/reportPatrolTasks]
java.io.IOException: Connection closed prematurelyat reactor.ipc.netty.http.client.HttpClientOperations.onInboundClose(HttpClientOperations.java:269)at reactor.ipc.netty.channel.ChannelOperationsHandler.channelInactive(ChannelOperationsHandler.java:113)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231)at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224)at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelInactive(CombinedChannelDuplexHandler.java:420)at io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:377)at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:342)at io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:282)at io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:223)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231)at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1429)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231)at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:947)at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:822)at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:322)at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:884)at java.lang.Thread.run(Thread.java:748)
2020-09-16 15:40:14.435 [lettuce-epollEventLoop-4-1] DEBUG [c.e.gateway.UserAuthGlobalFilter] - get the jwt_token string = eyJhbGciOiJub25lIn0.eyJ1c2VyTG9naW4iOiJ7XCJ1c2VySWRcIjo1NTA3MzksXCJsb2dpbklkXCI6NixcImRldmljZUlkZW50aWZpZXJcIjpcIlwiLFwibmFtZXNwYWNlSWRcIjoxMSxcInN0YXR1c1wiOjEsXCJsb2dpbkJvcmRlcklkXCI6NixcImxvZ2luSW5zdGFuY2VOdW1iZXJcIjoxNzc5NDk4NjQ0LFwibGFzdEFjY2Vzc1RpY2tcIjoxNjAwMDc0NTkzODU2LFwicHVzaGVySWRlbnRpZnlcIjpcImRldmVsb3BcIn0iLCJpc3MiOiJ1c2VyIiwiaWF0IjoxNjAwMjQxOTE5fQ.
2020-09-16 15:40:14.435 [lettuce-epollEventLoop-4-1] DEBUG [c.e.gateway.UserAuthGlobalFilter] - resume the request body, the body string = activityType=1&appKey=bf925ea0-a5e0-11e4-a67c-00163e024631&appVersionCode=15283&appVersionName=7.1.0&channelId=101&collectTimeMillis=1600270814425&deviceType=iPhone&imeiNumber=9f89c84a559f573636a47ff8daed0d33&nonce=8565&osInfo=iOS%2013.7&osType=1&signature=lAOKfcQMEKjUTQA9vEaifFX7l1o%3D×tamp=1600242014426
2020-09-16 15:40:14.439 [lettuce-epollEventLoop-4-1] DEBUG [c.e.gateway.UserAuthGlobalFilter] - get the jwt_token string = eyJhbGciOiJub25lIn0.eyJ1c2VyTG9naW4iOiJ7XCJ1c2VySWRcIjo1NTA3MzksXCJsb2dpbklkXCI6NixcImRldmljZUlkZW50aWZpZXJcIjpcIlwiLFwibmFtZXNwYWNlSWRcIjoxMSxcInN0YXR1c1wiOjEsXCJsb2dpbkJvcmRlcklkXCI6NixcImxvZ2luSW5zdGFuY2VOdW1iZXJcIjoxNzc5NDk4NjQ0LFwibGFzdEFjY2Vzc1RpY2tcIjoxNjAwMDc0NTkzODU2LFwicHVzaGVySWRlbnRpZnlcIjpcImRldmVsb3BcIn0iLCJpc3MiOiJ1c2VyIiwiaWF0IjoxNjAwMjQxOTE5fQ.
了解问题的原因,下面就是解决方案。
1、等着官方修复这个缺陷,显然等不了。
2、优化传参,把不必要的参数去掉,只穿必须参数,这样就可以少了一大部分数据量。
3、修改传参方式,由formData方式改为Json格式提交。
4、在Controller层添加注解@RequestBody,否则无法接受Json格式参数。
由原来的4M传输变为100k,解决了这个问题,适用了95%以上的场景了。但是如果真的出现即使优化了传参,更改了传参方式,
依然需要很大的传输数据量,不知道还能有什么好方法,只能等spring官方大佬来解决了。哈哈哈。。。。
每天努力一点,每天都在进步