过去一周,我一直在应对一次激进的机器人爬虫/攻击。该机器人使用随机 IP 和代理字符串进行分发,因此很难阻止,但我有另一个线程来解决这个问题。这个问题是,大量的 http 请求可能会导致 Tomcat 死机。
Tomcat 进程仍然正常,并且没有内存不足,它只是停止接受 http 或 https 请求。它会使任何 http 请求超时,但仍会接受 https 请求(如果 http 受到攻击,有时 https 也会停止)。
我之前看到过“打开文件过多”的错误,所以我将文件限制从 10000 改为 50000,这似乎有帮助,至少 https 崩溃了,但 http 仍然崩溃。我最近没有看到“打开文件过多”的错误。
似乎打开的文件数量过多,为什么 Tomcat 会打开这么多文件,在高负载下会发生文件泄漏吗?服务器有时 6 个月内都正常(因此在正常情况下不会发生泄漏),但之前在高负载下死机过。
该网站规模较大,拥有超过 100 万个页面(动态内容),每日点击量超过 100 万次。
当 Tomcat 收到大量 http 请求(例如长时间每秒 >100 个)时会发生什么?我假设请求将开始备份,如果使用线程池,将没有剩余的线程,它会继续池化请求直到出现故障,还是会开始拒绝请求?
有没有办法在备份一定量后开始拒绝请求?这似乎是防止极端负载下死机或崩溃的唯一方法。
我的 http 和 https 配置不同,所以这可能与 http 死亡的原因有关。https 使用 maxThreads 而 http 没有使用,(默认有多少个线程?)
<Connector port="80" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="443"
URIEncoding="UTF-8" />
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="..." keystorePass="..."
URIEncoding="UTF-8"/>
使用 Tomcat v8.5.47、CentOS 7.6、Oracle Java 1.8
答案1
这两个连接器都将使用 NIO 实现。
对于 8.5.47,maxConnections 的默认值为 10000,backlog 为 100。
实际情况是,前 10000 个连接将被接受,并依次分配给线程池中的线程(默认 200 个线程)进行处理。处理这些连接需要多长时间取决于应用程序。
如果当前有 10000 个连接,则接下来的 100 个请求将被保留在积压队列中。虽然 Java 尝试将其配置为 100,但操作系统可能会选择忽略该设置。
一旦积压已满,后续连接将被丢弃。
当您看到 HTTP 没有响应时,您可以(希望)通过间隔约 5 秒进行三次线程转储来找出 HTTP 无响应的原因。