Tomcat:增加maxThreads而不会有OutOfMemoryError的风险

时间:2013-07-01 09:57:58

标签: java multithreading jsp tomcat out-of-memory

我租了一台小tomcat服务器,通过dailyRazor上的jsp为Android应用提供http-get服务。最大java堆是“最大内存:92.81 MB”。

maxThreads的默认tomcat设置为25.随着使用我的服务的用户数增加,我在黄金时间获得了大量拒绝的服务器连接/超时(我认为这是因为线程池太小)。这就是为什么我将maxThreads增加到250.在这个晚上,服务器崩溃显示多个java.lang.OutOfMemoryError s。对于小堆来说250似乎有点重:p我暂时将maxThreads减少到50,这似乎很好,因为我不会再有任何错误。

由于我对tomcat了解不多,我想问一个找到maxThreads正确号码的好方法。我考虑过查看一个线程的最大内存使用量。然后maxThreads =(maxMemory / memoryOfOneThread)。有更好的解决方案吗?

感谢 danijoo

3 个答案:

答案 0 :(得分:3)

每个线程使用的内存量取决于您在线程中执行的操作。所以这取决于你的软件。

计算起来并不容易。

但对于tomcat而言,92MB,非常紧张。我会寻找一种方法来解决这个问题。

答案 1 :(得分:0)

您应该在公式中添加堆栈大小。它取决于JVM,例如对于HotSpot,32位JVM上的每个线程的默认堆栈大小约为512k。像你说的那样具有如此小的内存量并具有250个线程堆栈大小的BTW可能是实际问题。请注意,您可以使用-Xss选项更改它。

答案 2 :(得分:0)

答案是没有好办法,AFAIK。或者更准确地说,没有什么能比“试试看”更好。


但我回答的真正原因是指出你对问题和期望的理解存在一些缺陷。

  1. 线程不使用堆内存。或者至少不是直接的。

    线程的大部分内存使用是线程堆栈。线程堆栈大小是可调的,并且具有特定于平台的默认,可以高达1Mb。

    但是...... 线程堆栈未在Java堆中分配。它被分配在堆外存储器中。

  2. 如果你的系统在增加堆栈数量时由于OOME而崩溃,那么堆的使用是由于代码在线程上运行而不是线程本身。 (好吧,你可能知道这一点。)

  3. 如果您的请求被删除等问题,那么增加线程数通常解决方案。事实上,它很可能会使吞吐量变得更糟。


  4. 问题是,执行它的线程必须分配给处理器;即“核心”。您的Tomcat服务器可能有2个或4个核心(我猜)。这意味着任何时候都只能执行2个或4个线程。有25个线程意味着当所有25个线程都处于活动状态时,它们大约占核心CPU时间的1/6。有250个线程处于活动状态(如果曾经发生过),它们将获得1/60的核心。同时:

    • 每个请求都会创建一堆对象,在请求完成之前无法进行垃圾回收。

    • 这些请求中的每一个都可以竞争数据库周期,磁盘I / O带宽,网络带宽等。

    • 根据应用程序的性质,可能会增加对数据结构/数据库行的争用,从而导致线程上下文切换开销增加。

    将会有一个甜蜜点,线程数量可以为您提供最佳的请求吞吐量。如果您大大超过了这一点,吞吐量(每秒完成的请求数)将会下降,处理每个请求的平均时间将会增加。走得太远,系统将停止运转。 (OOME是可能发生这种情况的一种方式。另一种方式是请求服务时间过长,客户超时并停止等待响应。)

    基本上,您的应用程序(经过优化调整后)将达到一定的平均吞吐率。如果您的实际请求率超过了该值,那么最好的策略是处理您可以使用的那些,并快速删除其余的。丢弃请求可能看起来很糟糕,但它比响应请求者超时请求并启动新请求的替代方案更好。