背景
项目中,请求接口的时候部分成功部分失败,失败的接口返回400 Bad Request。接口是先通过网关,在网关中将用户的信息封装到header中,然后去请求具体的服务。
具体的报错日志如下:
排查过程
项目的业务逻辑背景:
接口是能正常到网关中的,通过各个过滤器后理论上下一步就是到具体的服务中去,但是具体的服务没有接收到这个请求。也就是网关处理完后到具体服务这个过程中,请求丢失了或失效的。
然后发现部分正常的接口中,请求头中封装的用户信息是比较少的,而不正常的接口中,请求头中封装的用户信息是比较多的。
问题定位:
请求发送后最直接的反馈是400 Bad Request 程序没有看到任何报错日志,过了一段时间后请求的服务在日志中会输出:
2021-11-26 17:29:03.577 INFO 28521 --- [io-32215-exec-2] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Request header is too large
at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:721) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.http11.Http11InputBuffer.parseHeader(Http11InputBuffer.java:874) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.http11.Http11InputBuffer.parseHeaders(Http11InputBuffer.java:564) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:309) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) [tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.27.jar:9.0.27]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_221]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.27.jar:9.0.27]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]
然后这个报错不一定是一直会输出的,测试了一个晚上后面回去看日志只输了4次。这个原因暂时不明确。
回去网关把增强封装用户信息的在网关打印出来,通过String类的getBytes函数对大小进行评估,发现有问题的请求头信息大小为17k.......
springboot2.x版本中,http/1.1请求的最大头大小默认是8k,在org.apache.coyote.http11包下的AbstractHttp11Protocol有个属性,如下:
问题解决
那么知道问题是因为请求头大小超过springboot允许的最大限制。那么针对业务对问题进行解决。
方案一:
限制请求头的大小,不要让请求头的大小超出允许限制。(本人采取的限制,因为业务中,请求头的信息是在网关中需要检验的用户信息,不需要流到具体的服务中去)
方案二:
调大springboot中允许的最大限制,在配置文件中设置即可。对应的参数:server.max-http-header-size .至于调大这个参数会不会导致其他连锁反应,暂时不请求。