Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Ten artykuł zawiera omówienie zalecanych strategii i ustawień konteneryzowania aplikacji Java. Podczas konteneryzowania aplikacji Java należy dokładnie zastanowić się, ile czasu procesora CPU ma dostępny kontener. Następnie zastanów się, ile pamięci jest dostępne zarówno pod względem całkowitej ilości pamięci, jak i rozmiaru sterty maszyny wirtualnej Java (JVM). W środowiskach konteneryzowanych aplikacje mogą mieć dostęp do wszystkich procesorów i dlatego mogą równolegle uruchamiać wiele wątków. Często jednak kontenery mają zastosowany limit procesora, który może ograniczać dostęp do procesorów.
Maszyny JVM używają heurystyki do określenia liczby "dostępnych procesorów" na podstawie limitu przydziału procesora CPU, co może znacząco wpłynąć na wydajność aplikacji Java. Pamięć przydzielona do samego kontenera oraz rozmiar obszaru sterty dla maszyny wirtualnej Java (JVM) są równie ważne jak procesory. Czynniki te określają zachowanie kolektora śmieci (GC) i wydajność całego systemu.
Wskazówka
Jeśli nie chcesz ręcznie konfigurować tych ustawień, Azure Command Launcher for Java (jaz) automatycznie zastosuje za Ciebie domyślne ustawienia JVM dla środowisk chmurowych. Jest to bezpośredni zamiennik polecenia java, który wykrywa limity kontenerów i dobiera optymalny rozmiar sterty oraz flagi GC. Aby uzyskać więcej informacji, zobacz Automatyczne dostrajanie maszyny wirtualnej JVM za pomocą modułu uruchamiania poleceń Azure dla Java.
Konteneryzowanie nowej aplikacji
Podczas konteneryzowania obciążenia Java dla nowej aplikacji należy wziąć pod uwagę dwie kwestie podczas myślenia o pamięci:
- Pamięć przydzielona dla samego kontenera.
- Ilość pamięci dostępnej dla procesu Java.
Omówienie domyślnej anatomii maszyny wirtualnej JVM
Aplikacje wymagają punktu początkowego i ustawień. Maszyna JVM ma domyślne ustawienia ergonomiczne ze wstępnie zdefiniowanymi wartościami, które są oparte na liczbie dostępnych procesorów i ilości pamięci w systemie. Podczas uruchamiania maszyny wirtualnej JVM używa wartości domyślnych pokazanych w poniższych tabelach bez określonych flag uruchamiania lub parametrów.
W poniższej tabeli przedstawiono domyślną GC dla dostępnych zasobów:
| Dostępne zasoby | Domyślna GC |
|---|---|
| Dowolna liczba procesorów Do 1791 MB pamięci |
SerialGC |
| 2 lub więcej procesorów 1792 MB lub więcej pamięci |
G1GC |
W poniższej tabeli przedstawiono domyślny maksymalny rozmiar sterty w zależności od ilości pamięci dostępnej w środowisku, w którym działa maszyna wirtualna JVM:
| Dostępna pamięć | Domyślny maksymalny rozmiar sterty |
|---|---|
| Do 256 MB | 50% dostępnej pamięci |
| Od 256 MB do 512 MB | ~127 MB |
| Więcej niż 512 MB | 25% dostępnej pamięci RAM |
Domyślny początkowy rozmiar sterty to 1/64 dostępnej pamięci. Te wartości są ważne dla OpenJDK 11 i nowszych — oraz dla większości dystrybucji, w tym Microsoft Build of OpenJDK, Azul Zulu, Eclipse Temurin, Oracle OpenJDK i innych.
Określanie pamięci kontenera
Wybierz ilość pamięci kontenera, która najlepiej obsługuje obciążenie, w zależności od potrzeb aplikacji i jej charakterystycznych wzorców użycia. Jeśli na przykład aplikacja tworzy duże grafy obiektów, prawdopodobnie potrzebujesz więcej pamięci niż w przypadku aplikacji z wieloma małymi grafami obiektów.
Wskazówka
Jeśli nie wiesz, ile pamięci należy przydzielić, dobrym punktem wyjścia jest 4 GB.
Określanie pamięci stert JVM
Przy przydzielaniu pamięci sterty JVM pamiętaj, że JVM potrzebuje więcej pamięci niż wynosi ilość pamięci przydzielonej na stertę JVM. Nie należy ustawiać maksymalnej ilości pamięci stertowej JVM równej ilości pamięci kontenera. To ustawienie może powodować błędy braku pamięci (OOM) kontenera i awarie kontenera.
Wskazówka
Przydziel 75% pamięci kontenera na stertę JVM.
W OpenJDK 11 i nowszych wersjach ustaw rozmiar sterty JVM w jeden z następujących sposobów:
| Opis | Flaga | Przykłady |
|---|---|---|
| Stała wartość | -Xmx |
-Xmx4g |
| Wartość dynamiczna | -XX:MaxRAMPercentage |
-XX:MaxRAMPercentage=75 |
Minimalny lub początkowy rozmiar sterty
Jeśli środowisko gwarantuje określoną ilość pamięci zarezerwowanej dla instancji JVM, na przykład w kontenerze, ustaw minimalny lub początkowy rozmiar sterty na taki sam jak jej maksymalny rozmiar. To ustawienie informuje JVM, że nie powinno wykonywać zadania zwalniania pamięci do systemu operacyjnego.
Aby ustawić minimalny rozmiar sterty, użyj wartości -Xms bezwzględnych lub -XX:InitialRAMPercentage wartości procentowych.
Ważne
Pomimo tego, co sugeruje nazwa, flaga -XX:MinRAMPercentage ustawia domyślny maksymalny procent pamięci RAM dla systemów z maksymalnie 256 MB pamięci RAM dostępnej w systemie.
Określić, który GC użyć
Wcześniej określiłeś, ile pamięci stertowej JVM należy przydzielić na początek. Następnym krokiem jest wybranie swojego GC. Maksymalna wielkość pamięci sterty JVM, jaką dysponujesz, często wpływa na wybór GC. W poniższej tabeli opisano cechy każdej GC.
| Czynniki | SerialGC | ParallelGC | G1GC | ZGC | ShenandoahGC |
|---|---|---|---|---|---|
| Liczba rdzeni | 1 | 2 | 2 | 2 | 2 |
| Wielowątkowe | Nie. | Tak | Tak | Tak | Tak |
| Rozmiar sterty Java | <4 GB | <4 GB | >4 GB | >4 GB | >4 GB |
| Wstrzymanie | Tak | Tak | Tak | Tak (<1 ms) | Tak (<10 ms) |
| Koszty ogólne | Minimalny | Minimalny | Umiarkowane | Umiarkowane | Umiarkowane |
| Efekt opóźnienia końcowego | Wysoki | Wysoki | Wysoki | Niski | Umiarkowane |
| Wersja zestawu JDK | Wszystko | Wszystko | JDK 8+ | JDK 17+ | JDK 11+ |
| Najlepsze dla | Mała sterta z pojedynczym rdzeniem | Małe sterty wielordzeniowe lub obciążenia wsadowe o dowolnym rozmiarze sterty | Responsywność w pracy ze średnimi i dużymi stosami (interakcje żądanie-odpowiedź/bazodanowe) | Responsywność w pracy ze średnimi i dużymi stosami (interakcje żądanie-odpowiedź/bazodanowe) | Responsywność w pracy ze średnimi i dużymi stosami (interakcje żądanie-odpowiedź/bazodanowe) |
Wskazówka
W przypadku większości aplikacji mikrousług ogólnego przeznaczenia zacznij od równoległego GC.
Określ, ile rdzeni CPU potrzebujesz
Dla każdego GC innego niż SerialGC użyj dwóch lub więcej rdzeni vCPU — lub co najmniej 2000m dla cpu_limit w Kubernetes. Nie wybieraj mniej niż jednego rdzenia procesorów wirtualnych w środowiskach konteneryzowanych.
Wskazówka
Jeśli nie wiesz, od ilu rdzeni vCPU zacząć, dobrym wyborem są dwa rdzenie.
Wybierz punkt początkowy
Zacznij od dwóch replik lub instancji w środowiskach do orkiestracji kontenerów, takich jak Kubernetes, OpenShift, Azure Spring Apps, Azure Container Apps i Azure App Service. Poniższa tabela zawiera podsumowanie zalecanych punktów początkowych dla konteneryzacji nowej aplikacji Java.
| Rdzenie vCPU | Pamięć kontenera | Rozmiar sterty JVM | usuwanie elementów bezużytecznych | Repliki |
|---|---|---|---|---|
| 2 | 4 GB | 75% | ParallelGC | 2 |
Użyj następujących parametrów JVM:
-XX:+UseParallelGC -XX:MaxRAMPercentage=75
Automatyczne dostrajanie maszyny wirtualnej JVM za pomocą modułu uruchamiania poleceń Azure dla Java
W poprzednich sekcjach opisano sposób ręcznego wybierania flag JVM na podstawie pamięci kontenera, rdzeni procesora CPU i typu obciążenia. Jeśli nie chcesz samodzielnie utrzymywać tych ustawień, narzędzie Azure Command Launcher for Java (jaz) automatycznie stosuje domyślne ustawienia JVM natywne dla chmury.
Azure Command Launcher for Java to lekkie narzędzie, które działa między poleceniem uruchamiania a maszyną wirtualną Javy (JVM). Wykrywa środowisko chmury, w tym limity pamięci kontenera i procesora CPU, a następnie wybiera flagi dostrajania najlepiej dopasowane do rozmiaru sterty, wybór GC i diagnostykę. Takie podejście zmniejsza narzut związany z konfiguracją i od razu poprawia wykorzystanie zasobów.
Aby użyć narzędzia, zastąp polecenie java poleceniem jaz w skrypcie startowym lub pliku Dockerfile. Na przykład zamiast ręcznie dostrajać opcje JVM:
java -XX:+UseParallelGC -XX:MaxRAMPercentage=75 -jar myapp.jar
Użyj jaz:
jaz -jar myapp.jar
Narzędzie jest dołączone do obrazów kontenerów dla Microsoft Build of OpenJDK, więc nie jest konieczna dodatkowa konfiguracja. Poniższy plik Dockerfile używa jaz do uruchamiania aplikacji Java z jar pliku:
# Use any Microsoft Build of OpenJDK base image
FROM mcr.microsoft.com/openjdk/jdk:25-ubuntu
# Add your application.jar
COPY application.jar /application.jar
# Use jaz to launch your Java application
CMD ["jaz", "-jar", "application.jar"]
Aby uzyskać informacje na temat opcji instalacji, obsługiwanych środowisk i szczegółów konfiguracji, zobacz Azure Command Launcher for Java (Uruchamianie poleceń Azure).
Konteneryzowanie istniejącej aplikacji lokalnej
Jeśli aplikacja jest już uruchomiona lokalnie lub na maszynie wirtualnej w chmurze, zacznij od następującej konfiguracji:
- Ta sama ilość pamięci, do której aplikacja ma obecnie dostęp.
- Ta sama liczba procesorów CPU lub rdzeni wirtualnych CPU, które aplikacja ma obecnie dostępne.
- Te same parametry JVM, których obecnie używasz.
Jeśli kombinacja liczby rdzeni vCPU i pamięci kontenera nie jest dostępna, wybierz najbliższą dostępną, zaokrąglając liczbę rdzeni vCPU i pamięć kontenera w górę.
Dalsze kroki
Teraz, po zapoznaniu się z ogólnymi zaleceniami dotyczącymi konteneryzowania aplikacji Java, przejdź do następujących artykułów, aby ustanowić punkt odniesienia konteneryzacji i uprościć dostrajanie JVM: