坑爹的springboot版本害我改了三天的BUG

最近项目中遇到了一个问题,费好大劲才发现问题所在,并且修复了问题,下面分享一下这个问题的定位和修复的新路旅程。

先说下背景:该项目用的是SpringBoot框架,主要功能为对外提供一些Restful API,使用的Servlet容器是默认的Tomcat,Json解析工具是默认的Jackson,通过@RequestBody注解来解析body。

再说下问题:用户通过https方法调用POST方法的接口,会偶现Jackson解析Json体失败的问题。这个问题比较离奇,同样的数据,同样的接口,有时候会发生解析失败。大概成功10+次会失败一次的频率。报错信息如下:

 

JSON parse error: Unexpected end-of-input: expected close marker for Object (start marker at [Source: (PushbackInputStream); line: 1, column: 1]); 

nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input: expected close marker for Object (start marker at 

[Source: (PushbackInputStream); line: 1, column: 1])\n at [Source: (PushbackInputStream); line: 1, column: 3]。

值得一提的是,line和column的值每次都会不一样。

 

由于服务部署在公有云上,依赖的周边服务有不少,所以要先进行问题的定界。

 

 

不通过公有云注册的API,而是直接通过公网IP:PORT的形式调用,问题复现。排除APIG服务问题。

进入容器节点,直接调用容器内的pod ip,问题复现。排除k8s或者CCE服务的问题。

至此,已经能排除公有云服务的问题,可以专注定位是否是框架或者实现有问题。

接下来观察一下报错信息,显然是解析body体出了问题,看起来像是body体不完整导致的,而且每次提示的line和column值都不一样,感觉是body体在哪里被截断了。那很自然的会做以下猜测:

 

body体本身不合法。不再赘述,推荐一个在线平台 bejson。

https请求对body内容做了拦截。查看请求头中是否包含Content-Length,如果包含的话,可能就是这个值有问题,把这个Content-Length从请求头中删除掉

body体被spring框架拦截。

body体被spring内的tomcat拦截。

--server.max-http-header-size=8192000

--server.tomcat.max-http-post-size=-1

--spring.server.tomcat.max-http-header-size=52428800

--spring.server.tomcat.max-http-post-size=-1

--spring.http.multipart.max-file-size=1000m

--spring.http.multipart.max-request-size=1000m

spring和tomcat的配置有很多,找了很多参数,都没有解决问题,行吧,只能打断点看了。

经过测试本地无法复现,那就只能对远程服务器上的deployment进行远程debug。基于IDEA进行springboot工程的远程调试方法见我之前的blog:基于IDEA对springboot做远程调试

 

根据日志打出来的栈信息,不难找到是在AbstractJackson2HttpMessageConverter. readJavaType方法报的错,这个Converter方法其实就是spring-web的http消息转换器,

readJavaType方法定义:

private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException

报错信息显示在这一行:

return this.objectMapper.readValue(inputMessage.getBody(), javaType)

这里调用了Jackson的readValue方法对message这个流进行解析,那我们从这里开始单步调试,下一步应该进到jackson的readValue方法了,此时通过ctrl+左键进入这个方法,

发现jackson-core的版本为2.11.2,而报错的栈信息中jackson-core版本为2.10.2,两边的版本不一致?

 

 

由于spring-web版本是spring starter中指定的,带着疑问,我尝试着把starter的版本升级到最新的2.3.0.RELEASE,对环境上的应用进行了升级,

问题不再复现…好吧,终于解决。之前用的starter是2.2.5.RELEASE,有可能是仓库中的该版本包有问题,亦或是这个版本下spring-web的版本就是有BUG,这个不得而知了…

 

参考:

https://www.debugger.wiki/article/html/1599454800281337

本文原创,商业转载请联系作者获得授权,非商业转载请注明出处。

评论

发送评论 编辑评论


                        

后端技术分类热门文章

标签热门文章排行

☛免责声明 ☛本站使用教程
Theme Argon With Ry-Plus By 清欢
我的第16391位朋友,历经92684次回眸才与你相遇