在我的公司,我们今天遇到了严重问题:我们的生产服务器出现故障。大多数通过浏览器访问我们软件的人无法获得连接,但是已经使用该软件的人能够继续使用它。甚至我们的热备用服务器也无法与生产服务器通信,它使用HTTP进行通信,甚至无法访问更广泛的互联网。服务器可以通过ping和ssh访问的整个时间,实际上是非常负载 - 它通常以5%的CPU负载运行,而且此时甚至更低。我们几乎没有磁盘i / o。
问题开始几天后,我们有了一个新的变化:端口443(HTTPS)正在响应,但端口80停止响应。服务器负载非常低。重新启动tomcat后,端口80立即开始响应。
我们使用tomcat7,maxThreads =" 200",并使用maxConnections = 10000。我们从主内存中提供所有数据,因此每个HTTP请求都很快完成,但是我们有大量用户进行非常简单的交互(这是高中科目选择)。但是我们似乎不太可能同时拥有10,000个用户同时在我们的页面上打开浏览器。
我的问题有几个部分:
但主要的问题是,"我们如何修复我们的服务器?"
Stefan和Sharpy要求的更多信息:
更多信息: 当我们意识到我们使用BIO的默认Tomcat7设置(每个连接有一个线程,并且我们有maxThreads = 200)时,看起来我们已经解决了问题。实际上' netstat -an'显示了大约297个连接,其中200个队列为100个。因此我们将其更改为NIO并重新启动了tomcat。不幸的是,第二天发生了同样的问题。我们可能错误配置了server.xml。
这里提供了catalina.out的server.xml和摘录: https://www.dropbox.com/sh/sxgd0fbzyvuldy7/AACZWoBKXNKfXjsSmkgkVgW_a?dl=0
更多信息: 我做了负载测试。我能够从我的开发笔记本电脑创建500个连接,并且每个都进行3次HTTP GET,没有任何问题。除非我的负载测试无效(Java类也在上面的链接中)。
答案 0 :(得分:3)
如果没有亲自动手的调试,很难确定,但我要检查的第一件事就是文件描述符限制(即ulimit -n
)。 TCP连接使用文件描述符,并且根据正在使用的实现,使用SelectableChannel
进行轮询的nio连接可能会为每个打开的套接字吃掉几个文件描述符。
检查这是否是原因:
ps
ulimit
流程是否运行:cat /proc/<PID>/limits | fgrep 'open files'
ls /proc/<PID>/fd | wc -l
如果使用的描述符数量明显低于限制,则还有其他原因导致问题。但如果它等于或非常接近极限,那么这就是造成问题的限制。在这种情况下,您应该为运行Tomcat帐户的用户增加/etc/security/limits.conf
的限制,并从新打开的shell重新启动进程,如果实际使用了新限制,请使用/proc/<PID>/limits
进行检查,并查看如果Tomcat的行为得到改善。
答案 1 :(得分:2)
虽然我没有直接的答案来解决你的问题,但我想提供我的方法来找出问题所在。
直观地有3个假设:
要找出此问题的原因,您最好尝试在测试环境中重播该方案。执行更全面的测试并记录更详细的日志,包括但不限于:
答案 2 :(得分:1)
你绝对确定你没有达到maxThreads限制吗?你试过改变吗?
目前浏览器将同时连接限制为每个主机名/ ip最多4个,因此如果您有50个并发浏览器,则可以轻松达到该限制。虽然希望您的webapp能够快速响应以应对此问题。如今,漫长的民意调查越来越受欢迎(直到网页插播更为普遍),所以你可能有200个长期民意调查。
另一个原因可能是你使用HTTP [S]进行app-to-app通信(也就是说,不涉及浏览器)。有时,应用程序编写者很邋and并创建新的连接以并行执行多个任务,从而导致TCP和HTTP开销。仔细检查您是否没有获得任何请求。日志文件通常可以帮助您,或者您可以使用wireshark来计算HTTP请求或HTTP [S]连接的数量。如果可能,请修改您的API以在一个HTTP请求中处理多个API调用。
与最后一个相关,如果您有多个HTTP / 1.1请求通过一个连接,并且中间代理可能会将它们拆分为多个连接以实现负载平衡。听起来很疯狂我知道,但我已经看到它发生了。
最后,一些抓取机器人会忽略robots.txt中设置的抓取延迟。同样,日志文件和/或wireshark可以帮助您确定这一点。
总体而言,通过更多更改运行更多实验。在使用maxConnections跳到结论之前,请使用maxThreads,https等。
答案 3 :(得分:1)
答案简短:
答案很长:
我们使用的是BIO连接器而不是NIO连接器。两者之间的区别在于BIO是“每个连接一个线程”而NIO是“一个线程可以为多个连接提供服务”。因此,如果我们不增加“maxThreads”,那么增加“maxConnections”就无关紧要了,因为我们没有理解BIO / NIO的差异。
要将其更改为NIO,请将其放在server.xml中的元素中: 协议= “org.apache.coyote.http11.Http11NioProtocol”
据我所知,使用BIO没有任何好处所以我不知道为什么它是默认的。我们只使用它,因为它是默认设置,我们假设默认设置是合理的,我们不想成为tomcat调优的专家,达到我们现在的程度。
但是:即使在进行此更改之后,我们也发生了类似的事情:在同一天,即使HTTP正在运行,HTTPS也没有响应,然后稍后相反的情况发生了。这有点令人沮丧。我们检查了'catalina.out',实际上正在使用NIO连接器,而且确实如此。所以我们开始了很长一段时间来分析'netstat'和wireshark。我们注意到连接数量出现了一些高峰期 - 在一个案例中,当基线大约为70时,多达900个连接。当我们在主要生产服务器和我们为每个客户安装的“设备”之间同步数据库时,出现了这些高峰网站(学校)。我们进行同步的次数越多,我们造成的中断就越多,这导致我们在下降的螺旋中进行更多的同步。
似乎正在发生的事情是,新南威尔士州教育部代理服务器将我们的数据库同步流量拆分为多个连接,以便1000个页面请求变为1000个连接,而且直到TCP 4分钟超时才能正常关闭它们。代理服务器只能这样做,因为我们使用的是HTTP。他们这样做的原因可能是负载平衡 - 他们认为通过在4个服务器上拆分页面请求,他们可以获得更好的负载平衡。当我们切换到HTTPS时,他们无法执行此操作并被迫仅使用一个连接。因此消除了这个特殊问题 - 我们不再看到连接数量突然增加。
人们建议增加“maxThreads”。实际上这会改进一些东西,但这不是“正确的”解决方案 - 我们的默认值为200,但在任何给定的时间,几乎没有任何东西做任何事情,实际上几乎没有任何一个甚至分配给页面请求
答案 4 :(得分:0)
我认为您需要使用Apache JMeter调试应用程序的连接数,并使用Jconsole或Zabbix为tomcat服务器查找堆空间或线程转储。
Apache tomcat的Nio连接器可以有10000的最大连接但我不认为提供那么多连接到一个tomcat实例的好主意更好的方法是运行tomcat的多个实例。
在我看来,生产服务器的最佳方式:在前面运行Apache http服务器,并使用AJP连接器将tomcat实例指向该http服务器。
希望这有帮助。