rog*_*ack 4 java sockets tomcat
如果我设置 tomcat 并从中传输静态文件,我注意到如果客户端从该套接字“暂停”(停止接收)超过 20 秒,那么 tomcat 似乎会任意切断连接(即使请求 URI 标头具有已收到且连接仍处于“已连接”状态 [客户端仍处于活动状态])。什么配置参数控制这个?文档提到但仅与初始标头解析和读取请求正文有关,而不是读取服务器的响应[connectionTimeout
?]这里是否发生某种不活动超时?
它是可重现的,从任何 tomcat 应用程序流式传输(大)静态文件,并通过暂停的客户端接收它,例如 test.rb:
require "socket"
host = "localhost"
port = 8080
socket = TCPSocket.new host,port
url = "/your_webapp/large_static_filename.ext"
request = "GET #{url} HTTP/1.0\r\nHost:#{host}\r\n\r\n"
socket.print request
puts "reading"
response = socket.sysread 1_000_000
puts response.length
puts response[0..300]
puts "sleeping 25" # with 10s or several reads separated by 10s, it is OK
sleep 25
response2 = socket.read
# this should equal the total size, but doesn't...
puts "sum=#{response2.length + response.length}"
Run Code Online (Sandbox Code Playgroud)
它与其他服务器一起工作得很好,所以可能没有某种操作系统限制。这只是普通的 Tomcat,所以没有 mod_jk 或工人在起作用......
影响此“不活动超时”的唯一因素似乎是
<Connector port="8080" ... connectionTimeout=30000 />
环境。
并且仅当它尝试主动“发送数据”到线路上时(但不能,因为客户端主动拒绝它或连接已丢失)。如果servlet只是在后台忙于处理cpu,然后写入线路(并且由内核接收或缓冲),没问题,它可以超过connectionTimeout,所以不是this。
我的预感是Tomcat似乎有一个“内置”(未记录?无法单独指定?)写入超时设置,默认为connectionTimeout值,ex(来自tomcat源,随机选择):
java/org/apache/tomcat/util/net/NioEndpoint.java
625: ka.setWriteTimeout(getConnectionTimeout());
Run Code Online (Sandbox Code Playgroud)
现在这是否“不好”还有待解释。在 TCP 通道以某种方式中断(足以停止传输)或客户端在接收字节时“阻塞”之后,会发生 Tomcat 的这种“切断”连接,FWIW ...
FWIW 连接超时设置会影响很多事情:
The total amount of time it takes to receive an HTTP GET request.
The total amount of time between receipt of TCP packets on a POST or PUT request.
The total amount of time between ACKs on transmissions of TCP packets in responses.
Run Code Online (Sandbox Code Playgroud)
现在显然还有一个 writeTimeout。
最终结果:我们的网络不稳定,因此这些是“预期”超时/断开的连接(通过具有不同名称的配置,哈哈)。