1. 问题
系统正常使用没有问题,但是有极个别的用户出现系统异常,通过日志发现某个get请求,传入的城市list太多,就会抛出异常 java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map。
2. 排查过程
看了服务方没有打印日志,刚开始以为是客户端的问题,就在客户端侧打断点进行调试,但是结论是请求发给服务端了,并返回的结果,通过postman进行重新调佣,返回的结果如下
<!doctype html><html lang="en"><head><title>HTTP Status 400 – Bad Request</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400 – Bad Request</h1></body></html>
显示结果为HTTP Status 400 – Bad Request。
因此将服务方代码在本地启动逐个地方打断点
-
在dispatcherServlet打断点,请求没有走到断点处
-
在某几个Filter的doFilter方法打断点,请求没有走到断点处
-
在standardWapperValve处打断点,请求没有走到断点处
-
在Http11Processor处打断点,请求进入了
最后发现是tomcat默认请求头最长为8192,而get请求的参数全部在请求头里。所以在Http11Processor类中做请求头校验时校验未通过,从而返回了400。
3. 问题优化
由于tomcat对请求头默认限制字节数量为8192,不符合实际业务使用场景,所以可以在配置文件里对该限制进行自定义限制,即在在application.yml,或者是application.properties中添加
server.max-http-header-size=40960
这样,就可以加大请求头字节数量限制。这样虽然可以解决当前问题,但是指标不治本,对于请求参数过多的接口,最好是更换为post请求,或者从业务上思考,更换实现方式,减少类似大数据量传参。
参考:
tomcat(8.5)修改 http请求头部的最大长度_tomcat设置请求头大小_zhangtxsir的博客-CSDN博客