Spring cloud网关gateway代理websocket报Max frame length of 65536 has been exceeded
Spring cloud网关gateway代理websocket报io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException Max frame length of 65536 has been exceeded.txt一、错误结果如下:二、解决方式:1.拷代码到springboot中2.修改关于包大小的业务逻辑三
Spring cloud网关gateway代理websocket报io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException Max frame length of 65536 has been exceeded
使用spring cloud代理websocket后,默认的包大小是64Kb,如果传比较大的图片或其他数据时会报Spring cloud网关gateway代理websocket报io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException Max frame length of 65536 has been exceeded错误,此记录
解决问题的过程。
一、错误结果如下:
2022-02-21 17:00:46,701 WARN [reactor-http-nio-14] reactor.netty.channel.FluxReceive.warn:294 - [id: 0x8f99a4bf, L:0.0.0.0/0.0.0.0:51471 ! R:/127.0.0.1:8081] An exception has been observed post termination, use DEBUG level to see the full stack: io.netty.handler.codec.http.websocketx.CorruptedWebSocketFrameException: Max frame length of 65536 has been exceeded.
二、解决方式:
先是通过这篇文章:https://www.freesion.com/article/2527480206/了解到了大概的问题是由于message超出了netty websocket限制的最大帧长度的原因,另外也给出了自己写个class继承ReactorNettyWebSocketClient
然后做一系列的操作,但看下来还是觉得太麻烦了,又要排除Gateway配置,又要引入其他的东西等,因此放弃。
但这也给了解决的思路,即然ReactorNettyWebSocketClient
源码中有关于包大小的代码,那就直接在这个类的代码复制出来,放在springboot工程中,然后修改重启即可。
我使用的springboot版本:2.3.12.RELEASE
,其他版本的代码可能有点不同,但都可以类似原理修改
1.拷代码到springboot中
org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient代码位置:spring-webflux-5.2.15.RELEASE.jar中,如下图
将org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient的代码直接同路径和包名拷到springboot工程中,如:
2.修改关于包大小的业务逻辑
修改改很简单,直接在ReactorNettyWebSocketClient的成员变量改即可。
修改前:
private int maxFramePayloadLength = NettyWebSocketSessionSupport.DEFAULT_FRAME_MAX_SIZE;
修改后:
private int maxFramePayloadLength = 64 * 1024 * 1024 ; //64MB
maxFramePayloadLength变量主要是在execute中用到的,如下,springboot版本不同,方法可能有些细小差别
三、重启springboot即可生效
重启springboot生效
四、延伸:为什么优先读取springboot中修改后的源码?
修改后的源码ReactorNettyWebSocketClient是和我们的应用代码在一起的,因此通过springboot打包后,会在BOOT-INF/classes中。
而其他的第三方jar会在classpath.idx中。
类在springboot打包的jar中查找的顺序为:先在BOOT-INF/classes中查询,如果找到就返回,找不到继续按在classpath.idx中列出的jar包顺序进行查找
因为我们改之后的源码在BOOT-INF/classes中,因为会优先生效,起到了覆盖原来的代码的效果
我们也可通过org.springframework.boot.loader.JarLauncher进行代码调试跟踪,在执行到ExecutableArchiveLauncher的createClassLoader方法时,会依次读取springboot打包后的jar文件,把里面的信息解析出来放urls
中,并作为org.springframework.boot.loader.LaunchedURLClassLoader类的构造参数。
在程序运行中需要加载类的时候,就以urls中列出的目录或jar集合顺序进行类的查询。
从上面看,也进一步验证了springboot加载类时是优先加载BOOT-INF/classes
的。
更多推荐
所有评论(0)