Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz 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 rozmiar 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 mają heurystyki umożliwiające określenie 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.
Konteneryzowanie nowej aplikacji
Podczas konteneryzacji 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ń. JVM ma domyślną ergonomię ze wstępnie zdefiniowanymi wartościami opartymi na liczbie dostępnych procesorów i wielkości pamięci w systemie. Wartości domyślne wyświetlane w poniższych tabelach są używane podczas uruchamiania maszyny wirtualnej JVM bez określonych flag uruchamiania lub parametrów.
W poniższej tabeli przedstawiono domyślną GC używaną 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 pracy, 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
W przypadku przydzielenia pamięci stertowej JVM maszyny JVM potrzebuje więcej pamięci niż to, co jest używane na stercie JVM. Ustawiając maksymalną pamięć stertową JVM, nie powinna ona nigdy być równa ilości pamięci kontenera, ponieważ powoduje to błędy braku pamięci (OOM) i awarie kontenera.
Wskazówka
Przydziel 75% pamięci kontenera na stertę JVM.
Od OpenJDK 11 i nowszych można ustawić rozmiar sterty JVM w następujący sposób:
| Opis | Flaga | Przykłady |
|---|---|---|
| Stała wartość | -Xmx |
-Xmx4g |
| Wartość dynamiczna | -XX:MaxRAMPercentage |
-XX:MaxRAMPercentage=75 |
Minimalny/początkowy rozmiar sterty
Jeśli środowisko ma zagwarantowaną określoną ilość pamięci zarezerwowaną dla instancji JVM, na przykład w kontenerze, powinieneś ustawić minimalny lub początkowy rozmiar stosu na taki sam, jak maksymalny rozmiar stosu. 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
Flaga -XX:MinRAMPercentage, pomimo tego, co sugeruje nazwa, jest używana do ustawiania domyślnej maksymalnej wartości procentowej 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 ilość pamięci stertowej JVM, którą masz, jest często czynnikiem podczas wybierania GC. W poniższej tabeli opisano cechy każdej GC.
| Czynniki | SerialGC | ParallelGC | G1GC | ZGC | ShenandoahGC |
|---|---|---|---|---|---|
| Liczba rdzeni | 1 | 2 | 2 | 2 | 2 |
| Wielowątkowy | 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 | Wielordzeniowe małe sterty lub obciążenia wsadowe z dowolnym rozmiarem 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ślanie, ile rdzeni procesora CPU jest potrzebnych
W przypadku dowolnego GC innego niż SerialGC zalecamy co najmniej dwa rdzenie wirtualne procesora — lub przynajmniej 2000m w przypadku cpu_limit na platformie Kubernetes. Nie zalecamy wybierania 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
Zalecamy rozpoczęcie od dwóch replik lub instancji w środowiskach 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 | GC | Repliki |
|---|---|---|---|---|
| 2 | 4 GB | 75% | ParallelGC | 2 |
Użyj następujących parametrów JVM:
-XX:+UseParallelGC -XX:MaxRAMPercentage=75
Konteneryzowanie istniejącej aplikacji lokalnej
Jeśli aplikacja jest już uruchomiona lokalnie lub na maszynie wirtualnej w chmurze, zalecamy rozpoczęcie 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 dostępna kombinacja rdzeni procesorów wirtualnych lub pamięci kontenera nie istnieje, wybierz najbliższą dostępną opcję, zaokrąglając w górę liczbę rdzeni procesorów wirtualnych i pamięć kontenera.
Dalsze kroki
Teraz, po zapoznaniu się z ogólnymi zaleceniami dotyczącymi konteneryzowania aplikacji Java, przejdź do następującego artykułu, aby ustanowić punkt odniesienia konteneryzacji: