JavaRush /Java блог /Random UA /Як пов'язані контейнери та Java?
Павел
11 рівень

Як пов'язані контейнери та Java?

Стаття з групи Random UA
Для тих, хто почитав про контейнери і Docker , але не розуміє яким боком до контейнерів причепився Java. Спочатку освіжимо свою пам'ять про пам'ять Java . Нагадаю, що пам'ять складається з Stack і Heap, які використовують RAM (оперативну пам'ять) сервера, говорячи далі про пам'ять - матимемо на увазі саме RAM. А тепер розглянемо контейнер у розрізі. Як пов'язані контейнери та Java?  - 1 Ні, звичайно, огузок і підборідок нас не цікавить, ми будемо дивитися на структуру пам'яті в контейнері. Її можна розділити на три частини: • Heap Memory – власне купа; • Off Heap – це все, що не в купі; • OS Overhead – це накладні витрати пам'яті на реалізацію процесів усередині контейнера. Як пов'язані контейнери та Java?  - 2 Допустимо: Ми виділабо на контейнер 1 Gb, на малюнку це буде Container Limit – його межі позначені синім прямокутником. На згадку Java в контейнері ми виділабо 80%, тобто 0,8 Gb і Heap зайняв у нас приблизно 80% від контейнера, тобто трохи менше 0,8 Gb, тому що частина ресурсів забрав собі OS Overhead (накладні витрати) на підтримка процесів. Близько 20% контейнера залишилося на все, що пов'язано не з купою ( Off Heap ). Область Used на малюнку показує використовувану область пам'яті виконання роботи програми. Тепер треба поговорити про ситуації, коли пам'ять у контейнері може скінчитися. OutOfMemoryError Якщо споживання пам'яті програмою (область Used ) досягне меж купи ( Heap ) ми зловимо OutOfMemoryError (OOM Error) . Яке каже, що не вистачає місце в купі, а саме, в області пам'яті, в яку поміщаються об'єкти, що створюються програмно у додатку. Як пов'язані контейнери та Java?  - 3 Якщо ще не зовсім зрозуміло, то поясню на котиках. OOM Error - це коли кіт, довго-довго кричить перед дверима на балкон, а коли ці двері відчинять, то він стоїть у отворі і не проходить ні туди ні сюди, часто кажуть, що котик завис. Якщо його вчасно підштовхнути, він відвисне і піде на балкон у своїх котячих справах. Як пов'язані контейнери та Java?  - 4 OOM Killer Це ще одна ситуація, яка може статися в контейнері, коли закінчується пам'ять. Як пов'язані контейнери та Java?  - 5 Якщо програма залізе за межі контейнера, то отримаємо OutOfMemory Killer (OOM Killer) - це процес, який завершує програму, щоб врятувати ядро ​​від збою. Він жертвує програмою, щоб зберегти роботу контейнера. Контейнер не факт, що впаде, але додаток, який в ньому працює впаде точно. Таке буває якщо залишити споживання пам'яті Java програмою без контролю. Знову на кішках. Якщо ви вирішабо в суботу якомога довше поспати і забули насипати котикам їжі, то OOM Killerквіточкам забезпечений, горщики може і не постраждають, а ось квіти доведеться садити заново. Як пов'язані контейнери та Java?  - 6 Яка різниця між OOM Error та OOM Killer? OOM Error ви можете обробити та вчинити якісь дії (наприклад: масштабувати програму), а OOM Killer просто вб'є весь процес. OOM Killer аналогічний kill-9 (kill мінус дев'ять) – команда, яка вбиває процес у Linux . Як пов'язані контейнери та Java?  - 7 Вся справа в тому, що найпопулярнішою реалізацією контейнера, є Docker контейнер, який базується на Linux , навіть якщо запустити його під Windows , все одно ядро ​​буде від Linux . У Linux нам цікаво одне поняття: CGroups (англ. control group) — механізм ядра Linux, який обмежує та ізолює обчислювальні ресурси (процесорні, мережеві, ресурси пам'яті, ресурси введення-виведення) для груп процесів. Просто кажучи, цей механізм дозволяє у контейнері керувати ресурсами, у нашому випадку пам'яттю. Як із цим пов'язана Java? Саме механізмом CGroups Java може зачепитися за пам'ять контейнера. Але це залежить від версії Java. Наприклад, Java 7 не вміє користуватися CGroups і ліміти контейнера їй невідомі. За замовчуванням maximal heap size = ¼ фізичної пам'яті. Якщо програма перевищить ліміти контейнера, то буде OOM Killer , а якщо ліміти контейнера не встановлені, то програма буде забирати пам'ять у інших програм на сервері (ліміти краще поставити, а то ляжуть усі). Можна, звичайно, використовувати налаштування heap або використовувати спеціальні образи, які вирішують цю проблему, але найлегше використовувати правильну версію Java. Правильні версії починаються з Java 8 x131 (портована з Java 9), вона починає розуміти CGroups . А в Java 10 з'явився support для контейнерів: UseContainerSupport , пізніше ця функція була портована в Java 8 x 191 . Або можна просто використовувати Java: 11+ . Який можна зробити висновок: При використанні пам'яті контейнера можна отримати OutOfMemoryError (OOM Error) або OutOfMemoryKiller (OOM Killer). При першому, програма відразу не впаде, OOM Error можна зловити, обробити та вчинити керовані дії. Наприклад, масштабувати програму. Якщо ж стався OOM Killer, то програма впаде відразу, жодних варіантів на його порятунок не залишиться. І найнеприємніше, що зовні сам контейнер буде в порядку, тобто можна навіть не підозрювати що там щось упало. Для взаємодії з пам'яттю контейнера та Java використовуються Linux механізми. Але не будь-яка Java їх реалізує. Щоб не було проблем для Java 8 потрібно використовувати версію починаючи від 131, а краще від 191. Або використовувати Java: 11+. Для практики: OutOfMemoryError: зрозумій, якщо зможеш
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ