尝试通过 ALB 将存档上传到 Tomcat 服务器时出现 SocketTimeoutException

问题描述

我遇到了阻止我使用 AWS ALB 将 zip 存档(约 4500kb)上传到 tomcat 服务器(7.0.90 版)的问题。 Curl 满足以下异常:

java.net.socketTimeoutException
    at org.apache.tomcat.util.net.NioBlockingSelector.read(NioBlockingSelector.java:202)
    at org.apache.tomcat.util.net.NioSelectorPool.read(NioSelectorPool.java:246)
    at org.apache.tomcat.util.net.NioSelectorPool.read(NioSelectorPool.java:227)
    at org.apache.coyote.http11.InternalNioInputBuffer.readSocket(InternalNioInputBuffer.java:439)
    at org.apache.coyote.http11.InternalNioInputBuffer.fill(InternalNioInputBuffer.java:813)
    at org.apache.coyote.http11.InternalNioInputBuffer$SocketInputBuffer.doRead(InternalNioInputBuffer.java:838)
    at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:137)
    at org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:293)
    at org.apache.coyote.Request.doRead(Request.java:438)
    at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:290)
    at org.apache.tomcat.util.buf.ByteChunk.checkEof(ByteChunk.java:422)
    at org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:404)
    at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315)
    at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:200)
    at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:999)
    at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:903)
    at java.io.InputStream.read(InputStream.java:101)
    at org.apache.commons.io.IoUtils.copyLarge(IoUtils.java:1792)
    at org.apache.commons.io.IoUtils.copyLarge(IoUtils.java:1769)
    at org.apache.commons.io.IoUtils.copy(IoUtils.java:1744)

这种行为非常随机,因为通常情况下,请求在多次重复 (3-4) 次相同请求后成功,但有时在第一次之后。

我正在使用的查询

curl -v -k --form archive=@/path_To_archive/archive.zip';type=application/zip' https://alb-example.com/install 2>&1 | tee /path_to_log/log

日志文件内容如下:

...
...
* Using HTTP2,server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
} [5 bytes data]
* Using Stream ID: 1 (easy handle 0x23c6bf0)
} [5 bytes data]
> POST /install HTTP/2
> Host: https://alb-example.com
> User-Agent: curl/7.61.1
> Accept: */*
> Content-Type: multipart/form-data; boundary=------------------------613bb4ddb0f6dcce
> 
{ [5 bytes data]
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
} [5 bytes data]
< HTTP/2 200 
< date: Mon,15 Mar 2021 14:19:54 GMT
< set-cookie: AWSALB=some cookie; Expires=some date; Path=/
< set-cookie: AWSALBCORS=some cookie; Expires=some date; Path=/; SameSite=None; Secure
< server: Apache-Coyote/1.1
< p3p: CP="ALL DSP COR and so on ..."
< set-cookie: specialCookie=some cookie; Path=/; Secure; HttpOnly; SameSite=None
< content-language: en-US
< 
{ [16 bytes data]

 11 4447k    0    16   11  496k     20   649k  0:00:06 --:--:--  0:00:06  648k
 11 4447k    0    16   11  496k      9   281k  0:00:15  0:00:01  0:00:14  281k
 11 4447k    0    16   11  496k      5   179k  0:00:24  0:00:02  0:00:22  179k
 11 4447k    0    16   11  496k      4   131k  0:00:33  0:00:03  0:00:30  131k
 11 4447k    0    16   11  496k      3   104k  0:00:42  0:00:04  0:00:38  104k
 11 4447k    0    16   11  496k      2  88116  0:00:51  0:00:05  0:00:46     0
 11 4447k    0    16   11  496k      2  75089  0:01:00  0:00:06  0:00:54     0
 11 4447k    0    16   11  496k      2  65417  0:01:09  0:00:07  0:01:02     0
 11 4447k    0    16   11  496k      1  57953  0:01:18  0:00:08  0:01:10     0
 11 4447k    0    16   11  496k      1  52018  0:01:27  0:00:09  0:01:18     0
 11 4447k    0    16   11  496k      1  47185  0:01:36  0:00:10  0:01:26     0
 11 4447k    0    16   11  496k      1  43174  0:01:45  0:00:11  0:01:34     0
 11 4447k    0    16   11  496k      1  39791  0:01:54  0:00:12  0:01:42     0
 11 4447k    0    16   11  496k      1  36900  0:02:03  0:00:13  0:01:50     0
 11 4447k    0    16   11  496k      1  34401  0:02:12  0:00:14  0:01:58     0
 11 4447k    0    16   11  496k      1  32219  0:02:21  0:00:15  0:02:06     0
 11 4447k    0    16   11  496k      0  30297  0:02:30  0:00:16  0:02:14     0
 11 4447k    0    16   11  496k      0  28591  0:02:39  0:00:17  0:02:22     0
 11 4447k    0    16   11  496k      0  27068  0:02:48  0:00:18  0:02:30     0
 11 4447k    0    16   11  496k      0  25698  0:02:57  0:00:19  0:02:38     0
Parsing archive
java.net.socketTimeoutException
    at org.apache.tomcat.util.net.NioBlockingSelector.read(NioBlockingSelector.java:202)
    at org.apache.tomcat.util.net.NioSelectorPool.read(NioSelectorPool.java:246)
    at org.apache.tomcat.util.net.NioSelectorPool.read(NioSelectorPool.java:227)
    at org.apache.coyote.http11.InternalNioInputBuffer.readSocket(InternalNioInputBuffer.java:439)
    at org.apache.coyote.http11.InternalNioInputBuffer.fill(InternalNioInputBuffer.java:813)
    at org.apache.coyote.http11.InternalNioInputBuffer$SocketInputBuffer.doRead(InternalNioInputBuffer.java:838)
    at org.apache.coyote.http11.filters.ChunkedInputFilter.readBytes(ChunkedInputFilter.java:315)
    at org.apache.coyote.http11.filters.ChunkedInputFilter.doRead(ChunkedInputFilter.java:203)
    at org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:293)
    at org.apache.coyote.Request.doRead(Request.java:438)
    at org.apache.catalina.connector.InputBuffer.realReadBytes(InputBuffer.java:290)
    at org.apache.tomcat.util.buf.ByteChunk.checkEof(ByteChunk.java:422)
    at org.apache.tomcat.util.buf.ByteChunk.substract(ByteChunk.java:404)
    at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:315)
    at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:200)
    at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:999)
    at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:903)
    at java.io.InputStream.read(InputStream.java:101)
    at org.apache.commons.io.IoUtils.copyLarge(IoUtils.java:1792)
    at org.apache.commons.io.IoUtils.copyLarge(IoUtils.java:1769)
    at org.apache.commons.io.IoUtils.copy(IoUtils.java:1744)
    ...
    ...
100 4455k    0  7890  100 4447k    356   200k  0:00:22  0:00:22 --:--:--  621k
100 4455k    0  7890  100 4447k    356   200k  0:00:22  0:00:22 --:--:--  736k
* Connection #0 to host alb-example.com left intact

使用ELB路由到同一台服务器时,不会发生SocketTimeoutException

在日志文件中类似以下内容

> POST /install HTTP/1.1
> Host: elb-example.com
> User-Agent: curl/7.53.1
> Accept: */*
> Content-Length: 4554573
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------6a7c0b9ed67735a1
> 
< HTTP/1.1 100 Continue
} [150 bytes data]
< HTTP/1.1 200 OK
< Content-Language: en-US
< Date: Mon,15 Mar 2021 15:46:35 GMT
< p3p: CP="ALL DSP COR and so on ..."
< Server: Apache-Coyote/1.1
< Set-Cookie: specialCookie=some cookie; Path=/; Secure; HttpOnly; SameSite=None
< transfer-encoding: chunked
< Connection: keep-alive
< 
{ [22 bytes data]

100 4447k    0   107  100 4447k    144  6022k --:--:-- --:--:-- --:--:-- 6018k
100 4447k    0   107  100 4447k    144  6020k --:--:-- --:--:-- --:--:-- 6018k
* Connection #0 to host elb-example.com left intact
Parsing archive
OK

疑难解答:

  • tomcat_home/conf/server.xml 中的 connectionTimeout 从 20 秒更新到 60 秒
  • 在 ALB 中禁用 HTTP/2
  • 使用 --http 1.1 标志调整 curl

还是不稳定

注意:Tomcat 服务器已包含以下更改:https://aldaris.github.io/dev/2017/08/25/hunting-down-a-bug-in-tomcat.html

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)