1.问题表现
预发环境偶发请求失败异常,服务端显示错误信息为:
Required String parameter 'seriesbaid' is not present
对应controller的api为
乍一看,是一个非常简单的异常,请求参数里面没有带seriesbaid,导致失败。
但是,经过确认,前端请求参数已经携带了seriesbaid,而且为“偶发失败”,并不是常见的参数传递问题。
2.常见原因赛选
2.1网关参数丢失?
由于前端请求到达后端服务中会经过网关,所以一开始怀疑是否网关丢失了传递参数。
经过 调用链分析,在偶发的失败的请求中,也确认已经传递了querystring。所以网关没有丢失参数传递。
2.2特殊字符号导致参数转换失败?
既然已经传递了querystring到后端服务,那么一种常见的原因,由于queryString中带有特殊字符而导致解析成queryParam失败了。
会是这个问题吗?
我们通过在服务中继承一个spring-web的OncePerRequestFilter,对请求参数进行打印。
在偶发的失败的请求中,找到了以下日志
2021-12-29 15:36:05,536 INFO [com.xxx.interceptor.RequestLoggingFilter] - shouldLog - swanparameter:traceId:fb2266d3687911ecb5f3cf045ea19ac3; query:seriesbaid=3FO4K4SLX2IW&x_plugin=custom&x_bz=&locale=zh_CN&x_resourceId=&x_resourceVersion=; parameterMap:{};
比较遗憾,我们确认了请求中确实有querystring而没有成功解析为queryParam,但是这个querystring中,并没有期望的特殊字符,讲道理是可以解析成功的。
既然常见原因无法解释,只能去源码捞一把了。
2.3去源码捞一把
我们的网络容器使用了jetty,所以HttpServletRequest的实现是jetty的Request类。
Request类中,对queryString的解析是在 getParameters() 的时候。
我们发现,当异常请求进来的时候,这里的判断_queryParameter竟然不是null,而是一个空对象。
而正常请求,这里判断_queryParameter为null,然后进行解析。
所以,还是要从源码去分析了。