Files
spring-boot-demo/doc/entrypoint.md
Savosin Denis e6db3360c2 add entrypoint to dockerfile and doc
fix resource usage
2025-11-06 15:47:56 +07:00

279 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Entrypoint: Запуск JAR-файла и конфигурация JVM
_LLM-generated документация._
## Оглавление
- [Обзор](#обзор)
- [Параметры запуска](#параметры-запуска)
- [Алгоритм работы](#алгоритм-работы)
- [1. Определение ограничений памяти контейнера](#1-определение-ограничений-памяти-контейнера)
- [2. Конфигурация компонентов приложения](#2-конфигурация-компонентов-приложения)
- [Переменные окружения со значениями по умолчанию:](#переменные-окружения-со-значениями-по-умолчанию)
- [3. Расчет "складских" ресурсов](#3-расчет-складских-ресурсов)
- [4. Расчет доступной памяти для JVM](#4-расчет-доступной-памяти-для-jvm)
- [5. Настройка Non-Heap областей JVM](#5-настройка-non-heap-областей-jvm)
- [Конфигурация областей памяти:](#конфигурация-областей-памяти)
- [6. Расчет Heap памяти](#6-расчет-heap-памяти)
- [Этап 1: Память доступная для Heap + GC](#этап-1-память-доступная-для-heap--gc)
- [Этап 2: Резерв для GC overhead](#этап-2-резерв-для-gc-overhead)
- [Этап 3: Финальный размер Heap](#этап-3-финальный-размер-heap)
- [Этап 4: Процент от MaxRAM для JVM](#этап-4-процент-от-maxram-для-jvm)
- [JVM флаги и их назначение](#jvm-флаги-и-их-назначение)
- [Контейнерная поддержка](#контейнерная-поддержка)
- [Управление памятью](#управление-памятью)
- [Оптимизация производительности](#оптимизация-производительности)
- [Дополнительные опции](#дополнительные-опции)
- [Экспортируемые переменные](#экспортируемые-переменные)
- [Пример расчета](#пример-расчета)
- [Дано:](#дано)
- [Расчет:](#расчет)
- [Результирующая команда Java:](#результирующая-команда-java)
- [Мониторинг и отладка](#мониторинг-и-отладка)
- [Verbose режим (`-v`)](#verbose-режим--v)
- [Рекомендуемые размеры контейнеров](#рекомендуемые-размеры-контейнеров)
- [Рекомендации по настройке:](#рекомендации-по-настройке)
- [Troubleshooting](#troubleshooting)
- [Проблема: Приложение падает с OOM](#проблема-приложение-падает-с-oom)
- [Проблема: Медленная работа GC](#проблема-медленная-работа-gc)
- [Проблема: Много database connections timeout](#проблема-много-database-connections-timeout)
## Обзор
Скрипт `entrypoint.sh` выполняет интеллектуальную настройку JVM на основе ограничений памяти контейнера. Он автоматически вычисляет оптимальные размеры heap, non-heap областей и других параметров для обеспечения стабильной работы Spring Boot приложения.
### Параметры запуска
- **`-v`** - включает verbose режим с выводом отладочной информации о расчетах памяти
- **`JAR_FILE_NAME`** - имя JAR-файла для запуска (позиционный аргумент)
**Пример использования:**
```bash
./entrypoint.sh -v app.jar # С отладочной информацией
./entrypoint.sh app.jar # Без отладочной информации
```
## Алгоритм работы
### 1. Определение ограничений памяти контейнера
```bash
# Проверка версии cgroups и получение лимита памяти
if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then
# Cgroups v1
LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
elif [ -f /sys/fs/cgroup/memory.max ]; then
# Cgroups v2
LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES=$(cat /sys/fs/cgroup/memory.max)
else
# Ошибка: нет доступа к информации о памяти
exit 1
fi
```
**Результат:** Получение лимита памяти контейнера в байтах.
### 2. Конфигурация компонентов приложения
#### Переменные окружения со значениями по умолчанию:
| Переменная | Значение по умолчанию | Описание |
|-------------------------------|-------------------------------|----------------------------------------|
| `TOMCAT_THREADS_MAX` | 100 | Максимальное количество потоков Tomcat |
| `TOMCAT_THREADS_MIN` | = TOMCAT_THREADS_MAX | Минимальное количество потоков Tomcat |
| `HIKARI_DB_MAXIMUM_POOL_SIZE` | 10 | Максимальный размер пула соединений БД |
| `HIKARI_DB_MINIMUM_IDLE_SIZE` | = HIKARI_DB_MAXIMUM_POOL_SIZE | Минимальное количество idle соединений |
| `JVM_NATIVE_MB` | 120 | Резерв памяти для native кода JVM |
### 3. Расчет "складских" ресурсов
```bash
STOCK_SIZE_MB = (TOMCAT_THREADS_MAX / 2) + HIKARI_DB_MAXIMUM_POOL_SIZE + JVM_NATIVE_MB
```
**Логика расчета:**
- **Tomcat потоки:** каждый поток потребляет ~0.5 MB памяти
- **Пул соединений БД:** каждое соединение ~1 MB
- **Native память JVM:** фиксированный резерв для JNI, сжатия, etc.
**Пример:** При дефолтных значениях: `(100/2) + 10 + 120 = 180 MB`
### 4. Расчет доступной памяти для JVM
```bash
LIMITED_MAXRAM_JAVA_SIZE_MB = LIMITED_RAM_CONTAINER_CGROUP_SIZE_MB - STOCK_SIZE_MB
```
**Назначение:** Память, которую JVM может использовать без риска превышения лимитов контейнера.
### 5. Настройка Non-Heap областей JVM
#### Конфигурация областей памяти:
| Область | Переменная | Значение по умолчанию | Назначение |
|----------------------------|-------------------------------|-----------------------|----------------------------|
| **Code Cache** | `RESERVED_CODE_CACHE_SIZE_MB` | 64 MB | Компилированный JIT код |
| **Metaspace** | `MAX_METASPACE_SIZE_MB` | 80 MB | Метаданные классов |
| **Direct Buffers** | `DIRECT_BYTES_BUFFERS_MB` | 10 MB | NIO буферы |
| **Compressed Class Space** | `COMPRESSED_CLASS_SPACE_MB` | 16 MB | Сжатые указатели на классы |
```bash
NON_HEAP_SIZE_MB = RESERVED_CODE_CACHE_SIZE_MB + MAX_METASPACE_SIZE_MB +
DIRECT_BYTES_BUFFERS_MB + COMPRESSED_CLASS_SPACE_MB
```
### 6. Расчет Heap памяти
#### Этап 1: Память доступная для Heap + GC
```bash
HEAP_GC_SIZE_MB = LIMITED_MAXRAM_JAVA_SIZE_MB - NON_HEAP_SIZE_MB
```
#### Этап 2: Резерв для GC overhead
```bash
OVERHEAD_GC_SIZE_PERCENT = 5 # По умолчанию 5%
OVERHEAD_GC_SIZE_MB = (HEAP_GC_SIZE_MB * OVERHEAD_GC_SIZE_PERCENT) / 100
```
#### Этап 3: Финальный размер Heap
```bash
HEAP_SIZE_MB = HEAP_GC_SIZE_MB - OVERHEAD_GC_SIZE_MB
```
#### Этап 4: Процент от MaxRAM для JVM
```bash
MAX_RAM_PERCENTAGE = (HEAP_SIZE_MB * 100) / LIMITED_MAXRAM_JAVA_SIZE_MB
```
## JVM флаги и их назначение
### Контейнерная поддержка
- **`-XX:+UseContainerSupport`** - Включает автоопределение ресурсов контейнера
- **`-XX:MaxRAM="${LIMITED_MAXRAM_JAVA_SIZE_MB}m"`** - Максимальная память для JVM
- **`-XX:MaxRAMPercentage="$MAX_RAM_PERCENTAGE"`** - Процент MaxRAM для heap
### Управление памятью
- **`-XX:+ExitOnOutOfMemoryError`** - Принудительное завершение при OOM
- **`-XX:MaxMetaspaceSize="${MAX_METASPACE_SIZE_MB}m"`** - Лимит Metaspace
### Оптимизация производительности
- **`-XX:+SegmentedCodeCache`** - Сегментированный code cache для лучшей производительности
- **`-XX:ReservedCodeCacheSize="${RESERVED_CODE_CACHE_SIZE_MB}m"`** - Размер code cache
### Дополнительные опции
- **`$JAVA_OPTS_OVERRIDE`** - Переменная для переопределения опций
## Экспортируемые переменные
Скрипт экспортирует рассчитанные значения для использования приложением:
```bash
export TOMCAT_THREADS_MAX=$TOMCAT_THREADS_MAX
export TOMCAT_THREADS_MIN=$TOMCAT_THREADS_MIN
export HIKARI_DB_MAXIMUM_POOL_SIZE=$HIKARI_DB_MAXIMUM_POOL_SIZE
export HIKARI_DB_MINIMUM_IDLE_SIZE=$HIKARI_DB_MINIMUM_IDLE_SIZE
```
## Пример расчета
### Дано:
- Лимит контейнера: **512 MB**
- Дефолтные значения всех переменных
### Расчет:
1. **Складские ресурсы:**
```
STOCK_SIZE_MB = (100/2) + 10 + 120 = 180 MB
```
2. **Доступная память для JVM:**
```
LIMITED_MAXRAM_JAVA_SIZE_MB = 512 - 180 = 332 MB
```
3. **Non-heap память:**
```
NON_HEAP_SIZE_MB = 64 + 80 + 10 + 16 = 170 MB
```
4. **Память для Heap + GC:**
```
HEAP_GC_SIZE_MB = 332 - 170 = 162 MB
```
5. **GC overhead:**
```
OVERHEAD_GC_SIZE_MB = (162 * 5) / 100 = 8 MB
```
6. **Финальный размер Heap:**
```
HEAP_SIZE_MB = 162 - 8 = 154 MB
```
7. **Процент RAM для heap:**
```
MAX_RAM_PERCENTAGE = (154 * 100) / 332 = 46%
```
### Результирующая команда Java:
```bash
exec java \
-XX:+UseContainerSupport \
-XX:+ExitOnOutOfMemoryError \
-XX:MaxRAM="332m" \
-XX:MaxRAMPercentage="46" \
-XX:+SegmentedCodeCache \
-XX:ReservedCodeCacheSize="64m" \
-XX:MaxMetaspaceSize="80m" \
-jar /app/app.jar
```
## Мониторинг и отладка
### Verbose режим (`-v`)
При запуске с флагом `-v` скрипт выводит отладочную информацию:
```bash
# Версия cgroups
Cgroups v2 are used
# Расчеты памяти
LIMITED_MAXRAM_JAVA_SIZE_MB=332
HEAP_SIZE_MB=154
MAX_RAM_PERCENTAGE=46
```
**Без флага `-v`** - никаких отладочных сообщений не выводится, только стандартные логи приложения.
### Рекомендуемые размеры контейнеров
| Размер контейнера | Heap | Статус |
|-------------------|-----------------|---------------------|
| **≤ 352 MB** | ❌ Отрицательный | Не работает |
| **353 MB** | 🔴 3 MB | Критический минимум |
| **400 MB** | 🟡 47 MB | Базовый |
| **512 MB** | 🟢 154 MB | Рекомендуемый |
| **768 MB** | 🟢 380 MB | Комфортный |
### Рекомендации по настройке:
1. **Для высоко нагруженных приложений** - увеличьте `TOMCAT_THREADS_MAX`
2. **Для БД-интенсивных приложений** - увеличьте `HIKARI_DB_MAXIMUM_POOL_SIZE`
3. **Для приложений с большим количеством классов** - увеличьте `MAX_METASPACE_SIZE_MB`
4. **При частых OOM** - уменьшите `OVERHEAD_GC_SIZE_PERCENT` или увеличьте память контейнера
## Troubleshooting
### Проблема: Приложение падает с OOM
**Решение:** Проверьте соотношение heap/non-heap памяти, возможно нужно увеличить лимит контейнера.
### Проблема: Медленная работа GC
**Решение:** Увеличьте `OVERHEAD_GC_SIZE_PERCENT` или используйте альтернативный GC через `JAVA_OPTS_OVERRIDE`.
### Проблема: Много database connections timeout
**Решение:** Увеличьте `HIKARI_DB_MAXIMUM_POOL_SIZE` и соответственно лимит памяти контейнера.