
Mehrere Benutzer führen Java-Anwendungen auf einem 60-Core-Rechnerserver (basierend auf Linux/Ubuntu) aus. Es gibt verschiedene Anwendungen und die meisten davon werden nicht intern entwickelt.
Der Systemadministrator ist zwar der Ansicht, dass es in Ordnung ist, wenn der Java-Prozess eines Benutzers zu einem beliebigen Zeitpunkt 10 Kerne verwendet, er möchte jedoch, dass nicht mehr als 10 verwendet werden.
Gibt es eine Java- oder Betriebssystemkonfiguration, mit der verhindert werden kann, dass der Prozess unbegrenzt Rechenressourcen beansprucht?
Antwort1
Zum Betriebssystem:
Ich würde sagen, die klassische Methode besteht darin, die CPU-Affinität mit einzustellen
taskset
.Eine bessere Alternative ist die Verwendung
cgroups
.Und die Lösung lautet: Führen Sie Ihre Anwendungen inDockerContainer. Vor Java 8 ist die JVM jedoch nicht in der Lage, die von Docker auferlegten Einschränkungen zu verstehen (erst verfügbar nach 8u131+ Backport, nicht sicher, ob es in Java9 für den CPU-Teil experimentell verfügbar ist, aber für den Speicher, und in Java10 vollständig verfügbar)
Antwort2
Ich würde sagen, es lohnt sich, dieses Video anzusehen.https://vimeo.com/181900266
Es gibt einen sehr guten Überblick über Java vs. Cgroups vs. Container und wie die JVM beispielsweise die Anzahl der CPUs herausfindet.
Basierend darauf würde ich sagen, dass die JVM bis Java 8 die Anzahl der verfügbaren CPUs so ermittelt, dass sie immer davon ausgeht, dass alle "online" CPUs für sie verfügbar sind, da sie zu diesem Zweck sysconf(_SC_NPROCESSORS_ONLN) verwendet. Selbst wenn sie in einer cgroup oder einem Container abgelegt ist.
Ab Java 9 verwendet die JVM sched_getaffinity() und es ist hilfreich, wenn cpuset verwendet wird, um die Anzahl der CPUs für die JVM zu steuern. D. h. die JVM sieht nur die konfigurierten CPUs. Wenn man beispielsweise die cpuset-cpus-Option von Docker verwendet, wird tatsächlich eine Begrenzung für die JVM erstellt. Hinweis! Wenn cpushare für die JVM konfiguriert ist, bietet dies noch keine Lösung für das Problem. Die JVM sieht weiterhin alle CPUs im System (unabhängig davon, ob es sich in einem Container befindet), wenn nur cpushare konfiguriert ist.
Antwort3
Eine weitere Alternative zusätzlich zu dem, was andere erwähnt haben (Cgroup-Quote, Cgroup-Cpuset) besteht darin, dass Sie Java explizit mitteilen können, wie viele CPUs es melden soll, wenn Bibliotheken danach fragen, indem Sie einen Wert für die -XX:ActiveProcessorCount
Option angeben. Alle Bibliotheken, die die Thread-Anzahl automatisch basierend auf dem Wert von auswählen Runtime.getRuntime().availableProcessors()
(wie z. B. Reactors Schedulers.parallel()
), konfigurieren sich entsprechend. Es kann auch die automatische Konfiguration des Garbage Collectors informieren.