如果我设置了tomcat并从中流传输了一个静态文件,我注意到如果客户端从该套接字“暂停”(停止接收)大于20s的任何时间,那么tomcat似乎 会 任意 切断 连接(即使请求URI标头包含已收到并且连接仍为“已连接” [客户端仍然有效])。哪个配置参数控制着它?该文档提到connectionTimeout但仅与初始标头解析和读取请求正文有关,而与读取服务器的响应无关[?]这里是否存在某种不活动超时?
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}"
它可以与其他服务器配合使用,因此可能无法发挥某种操作系统的作用。它只是普通的Tomcat,因此没有mod_jk或工人在玩…
影响此“非活动超时”的唯一因素似乎是
<Connector port="8080" ... connectionTimeout=30000 /> 设置。
<Connector port="8080" ... connectionTimeout=30000 />
并且仅当它试图将数据“主动发送”到线路上时(但不能,因为客户端正在主动拒绝它,或者连接丢失了)。如果servlet只是忙于在后台执行cpu,然后写入线路(并且它已被内核接收或缓冲),没问题,它可以超过connectionTimeout,所以不是this。
我的直觉是Tomcat似乎有一个“内置”(未记录?无法单独指定?)写超时设置,默认为connectionTimeout值,例如(从tomcat来源随机选择):
java/org/apache/tomcat/util/net/NioEndpoint.java 625: ka.setWriteTimeout(getConnectionTimeout());
现在,这是否是“不好的”尚待解释。在TCP通道以某种方式被中断(足以停止传输)或客户端在接收到字节时“阻塞” FWIW之后,就会发生此错误,这是由tomcat造成的连接“断开” …
FWIW connectionTimeout设置影响很多事情:
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.
现在显然也是writeTimeout。
最终结果:我们拥有一个flakey网络,因此这些超时是“预期的”超时。