背景
近期参与项目,有一个功能在线标注非结构化数据,并把标注内容保存在后台,功能如下:
意外就这样不出意外的出现了,保存请求400
排查
第一阶段
- 参数key没有对应上吗?
- 事与愿违,如果这么简单,这篇贴子就不会出现了
第二阶段
- 在前段调试的时候,有一个参数parmas.wsContent引起了我的怀疑:2M?!
- 去掉这个参数,请求成功
- 这个参数截取前50个字符,请求成功
第三阶段
- 经过第二阶段基本确定是参数过长导致的请求400
- 网上也确实有说tomcat通过maxPostSize参数限制post请求的参数
- 需要修改为maxPostSize<=0即可
- 修改server.xml的Connector标签,增加maxPostSize=0
- 为什么我改为0不用负数?这就是我随便写的。这正是我这个随便,产生了第四阶段的排查
- 增加maxPostSize后,意外再次不出意外的出现,artery解析空指针(没有获取到itemid)
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.thunisoft.artery.util.ArteryReflectUtil.invokeMethod(ArteryReflectUtil.java:97)
... 70 common frames omitted
Caused by: java.lang.NullPointerException: null
at com.thunisoft.artery.parse.visitor.FindItemByIdVisitor.<init>(FindItemByIdVisitor.java:23)
at com.thunisoft.artery.service.plugin.util.ArteryPluginUtil.findItemById(ArteryPluginUtil.java:38)
at com.thunisoft.artery.form.FormEngine.runItemScript(FormEngine.java:419)
... 75 common frames omitted
第四阶段
- 我尝试着把maxPostSize=-1,请求竟然成功了
- tomcat官网的maxPostSize参数解释:
- less than or equal to 0
- 默认2M,单位是byte(我在排查第三阶段尝试过maxPostSize=10240,我以为单位是kb)
为什么maxPostSize=0没用?
- 之前的less than or equal to 0的tomcat版本5.5,当时没有注意
- 后续tomcat版本这个参数已经变为less than zero了
- tomcat的changelog
- 在tomcat7.0.63版本这个参数就调整为负数了
jetty的相关配置
- 为什么产品一直没有出现问题,难道是jetty默认这个参数比较大?
- 本地搭建jetty,启动,发现请求依旧400,只是描述变成了unable to parse form content
- 网上说这个错误和postSize参数导致
- jetty的配置参数,jetty的配置文件已经增加了注释
- springboot的内置tas参数
- com.thunisoft.tas.springboot.autoconfigure.config.props.TasProperties
- 默认200KB
@NestedConfigurationProperty
private DataSize maxHttpPostSize = DataSize.ofBytes(200000L);
总结
前端和后台参数key对应不上和前端请求参数过长都会导致post请求返回码400。
- 解决方案:
- 统一前后端参数key
- 修改中间件MaxPostSize参数