为运行多个 Tomcat 的 Linux 机器选择 RAM 大小

为运行多个 Tomcat 的 Linux 机器选择 RAM 大小

我们的生产服务器运行在 Debian Linux 下,托管多个繁忙的 Tomcat 实例、数据库和支持服务。系统运行稳定了几年,但最近我们似乎遇到了速度变慢和内存问题。

在此期间,Tomcat 托管的应用程序规模不断扩大,用户越来越多,Tomcat 实例也越来越多。看来我们开始超出机器的内存限制了。

我开始熟悉使用 htop 和 Java JMX 等工具进行内存监控,试图确定当前的内存需求。JVM 端识别的旋钮是用于设置堆空间最大值和初始大小的开关。内存监控参数是虚拟 VIRT 和保留内存 RES。

我现在的问题是找出我们在机器中需要多少内存,因为托管应用程序的优化工作可能需要一段时间才能成功。

将所有虚拟大小相加会得出物理内存的倍数,这可能不是一个好数字,因为内核可能会处理相同的部分,如公共库代码。

将所有保留大小相加应该接近实际内存使用量(减去共享内存使用量)。但这是一个动态过程的结果,其中内核和不同应用程序的内存分配以及诸如启动各种 Tomcat 实例的顺序之类的因素可能会发挥作用。

在我开始采用二分法试错法,增加 RAM 并测量最终的系统性能直到我们达到更平静的状态之前,我发布了这个问题,希望能有一种方法可以更好地估计 RAM 需求。

更新:

$ cat /proc/meminfo
MemTotal:       66075980 kB
MemFree:         2117304 kB
Buffers:          396328 kB
Cached:          9286764 kB
SwapCached:       794700 kB
Active:         53198584 kB
Inactive:       10075240 kB
Active(anon):   50010632 kB
Inactive(anon):  3587764 kB
Active(file):    3187952 kB
Inactive(file):  6487476 kB
Unevictable:        5604 kB
Mlocked:            5604 kB
SwapTotal:       4194300 kB
SwapFree:            324 kB
Dirty:             49460 kB
Writeback:            72 kB
AnonPages:      52802056 kB
Mapped:            89356 kB
Shmem:              4448 kB
Slab:             388132 kB
SReclaimable:     324892 kB
SUnreclaim:        63240 kB
KernelStack:       11360 kB
PageTables:       126924 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    37232288 kB
Committed_AS:   47441088 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      386700 kB
VmallocChunk:   34325801336 kB
HardwareCorrupted:     0 kB
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       93868 kB
DirectMap2M:     8259584 kB
DirectMap1G:    58720256 kB
$

答案1

正如 asktyagi 提到的,可能是因为您的主机上运行了太多应用程序。通常,在单个主机上运行许多 JVM 可能会导致各种资源争用,其中内存只是其中之一 - 另一个例子是 GC 线程争用 CPU、磁盘 IO 等。

您提到通过运行多个 Tomcat 进程进行扩展。您可能想试验一下多少个进程才是适合您的正确选择 - 为此,单独的负载测试环境可能是必不可少的。

要了解程序需要多少内存,需要进行适当的监控。您可以使用 VisualVm 等基本分析器在本地机器上开始试验,观察 GC 行为并尝试不同的 -Xmx 设置。您可能还想根据您的工作负载以及延迟/吞吐量要求的重要性尝试不同的 GC 算法(例如 Shenandoah)。

在集群上,您应该打开 GC 日志,并可能通过 Java Flight Recorder 启用低开销分析。稍后,您可以使用 jClarity 的 Censum 等工具从 GC 日志中获取见解。

需要理解的重要一点是,您不能仅通过查看当前内存消耗水平来“猜测”应用的内存需求 - JVM 会尝试消耗您提供的尽可能多的内存,因此如果它消耗了 10 GB,并不一定意味着它需要它。它可能只需要 1 GB 就足够了(而且由于 GC 暂停时间可以更短,因此性能会更好)。

附注:过度使用(表现为 OOM 杀手)可能是一件坏事(请参阅http://www.etalabs.net/overcommit.html),尤其是对于服务器机器——您可能希望完全禁用交换。

答案2

老实说,将所有东西都放在一个盒子里并不是一个好主意,而且很难计算所需的确切内存,因为它取决于托管的应用程序。我建议在应用程序前面使用 LB,并在不同的主机上托管您的应用程序。

如果您仍想计算内存,则需要根据线程数和流量报告获取应用程序的历史内存趋势。这也取决于其他因素,例如同一台机器上托管的其他应用程序是什么等等。

希望这会有所帮助。

相关内容