Статьи

Правда о вертикальном масштабировании PaaS и почему вы «перепроданы»


Как вы знаете, 
Jelastic PaaS  имеет автоматическое вертикальное масштабирование, которое позволяет вам платить меньше — платить за 
фактическое  потребление ресурсов, а не за размер экземпляра. Истинное автоматическое вертикальное масштабирование является одним из ключевых отличий. Он предоставляет вашему приложению именно тот объем ОЗУ и ЦП, который ему необходим, и восстанавливает эти ресурсы, когда ваше приложение больше не нуждается в них. Другие платформы PaaS не обеспечивают истинного масштабирования ресурсов. Они не дают возможности масштабировать экземпляры по вертикали, что означает, что вы платите за пределы своих экземпляров. Общее название этой старой тактики — это 
перепроданность, Бизнес-модель всей хостинговой индустрии и PaaS-решений старого поколения основана на перепродаже. Таким образом, важность справедливой оплаты за фактическое потребление ресурсов довольно очевидна.

пересчетЧестно говоря, создать истинное вертикальное масштабирование было нелегко, потому что есть несколько технических ограничений. Один из них связан с ограничениями JVM. В этой статье я хотел бы поделиться некоторой информацией, которая может быть полезна для понимания этих ограничений JVM. Я надеюсь, что это поможет большему количеству драйверов java-сообщества адаптировать JVM для PaaS.

В начале, когда создавалась JVM, никто не знал об облаке или виртуализации, и, кроме того, никто не думал о плотности в PaaS. Сегодня виртуализация изменила игру индустрии хостинга, и революция еще не закончена. Сегодня мы можем использовать ресурсы более эффективно и с большей эластичностью. Jelastic — единственный PaaS, который предлагает истинное автоматическое вертикальное масштабирование для приложений Java и PHP. Тем не менее, я вижу хорошие движения ключевых драйверов Java в этой сфере.  Я говорил с  Микаэлом Видстедтом  — одним из главных архитекторов JVM в Oracle, и он согласился с тем, что JVM вообще не была разработана для PaaS, и Oracle собирается улучшить это. Плюс, ребята из IBM тоже усердно работают над этим. Некоторые примечания к динамическому поведению JVM можно найти в Основные моменты IBM JavaOne Keynote 2012 .

Одним из наиболее важных моментов вертикального масштабирования является понимание того, как JVM выделяет больше оперативной памяти, когда это необходимо, и как выделенная оперативная память возвращается в ОС, когда она больше не нужна. Алгоритм, который обеспечивает выделение ОЗУ, работает нормально, но компактизация (возврат ОЗУ в ОС) сегодня не работает. Это работает, если вы знаете детали, но есть много места для улучшений. Таким образом, JVM должна быть значительно улучшена в этой части.

Когда мы изначально разрабатывали Jelastic, одним из наиболее важных моментов было понимание того, как вертикальное масштабирование зависит от сборщика мусора JVM (GC). Мы протестировали множество различных комбинаций и обнаружили критически важные отношения и ограничения, которые препятствуют вертикальному сокращению приложений. Таким образом, проблема сборок мусора была довольно высокой в ​​списке вещей, которые должны работать хорошо, все время.

Как работает сборка мусора Java

На тот случай, если вы не совсем уверены, как работает сборка мусора в Java, не знаете, что это такое, или просто нуждаетесь в быстром обновлении, вот обзор того, как она работает. Чтобы получить более подробное представление об этом   , посетите Java Enterprise Performance Book или блог Джавина Пола,  Javarevisted .

В Java динамическое размещение объектов достигается с помощью  нового оператор. Созданный объект использует некоторое количество памяти, и память остается выделенной до тех пор, пока не останется никаких ссылок на использование объекта. Если для объекта нет ссылок, предполагается, что он больше не нужен, и память, занятая объектом, может быть восстановлена. Нет явной необходимости уничтожать объект, так как Java автоматически обрабатывает удаление. Сборка мусора это техника, которая выполняет это. Программы, которые не выделяют память, могут в конечном итоге аварийно завершить работу, если в системе не осталось памяти для выделения. Говорят, что эти программы имеют «утечки памяти». В Java сборка мусора происходит автоматически во время жизни Java-программы, что устраняет необходимость в выделении памяти и позволяет избежать утечек памяти.

Какой сборщик мусора используется с Jelastic?

Поскольку мы собирались решить, какой сборщик мусора использовать с Jelastic по умолчанию, нам пришлось сузить поле. Мы обнаружили, что самой большой проблемой будет одна из особенностей Jelastic, которой мы больше всего гордимся, — вертикальное масштабирование. Когда мы решали, как настроить сборку мусора в Java, эта функция представляла проблему.

Чтобы помочь нам решить, какой тип GC использовать, мы создали приложение, которое контролировало использование ресурсов.  Оказывается, что JVM на самом деле не очень хорошо справляется с вертикальным масштабированием . Если приложение запускается с небольшим объемом оперативной памяти, а затем добавляет больше, JVM не справляется с возвратом этой оперативной памяти в ОС, когда она больше не нужна. Мы выяснили, что изначально это было сделано специально: разработчики JVM использовали этот подход, чтобы ускорить процесс выделения памяти, поставив ее в очередь. Этот процесс не работал с нашей платформой, если у нас будет вертикальное масштабирование, и мы намеревались это сделать.

Итак, мы начали тестировать разные сборщики мусора. Мы протестировали Серийный сборщик мусора, Параллельный сборщик мусора, Сборщик мусора с одновременной очисткой маркеров и Сборщик мусора G1. Некоторая статистическая информация, которая была собрана, когда мы начали работать над Jelastic, включена ниже.

Серийный сборщик мусора (-XX: + UseSerialGC)

Сначала мы опробовали Серийный сборщик мусора. Он использует один поток для выполнения всей работы по сбору мусора. Это   коллекционер, который останавливает мир и имеет определенные ограничения.

Ниже вы можете увидеть простые тесты в Java 6 и Java 7.

Тест на серийный сборщик мусора

public class Memoryleak {
  public static void main(String[] args) {
          System.out.println("START....");
          while (true) {
             System.out.println("next loop...");
             try {
 int count =  1000 * 1024;
 byte [] array = new byte[1024 * count];
 
                 Thread.sleep(5000);
                 array = null;
                 System.gc();
 System.gc();
 Thread.sleep(5000);
 } catch (InterruptedException ex) {
          }
         }
      }
  }

Мы запустили JVM с этими параметрами:

-XX: + UseSerialGC -Xmx1024m -Xmn64m -Xms128m -Xminf0.1 -Xmaxf0.3

где

  • -XX: + UseSerialGC  — использовать Serial Garbage Collector (этот параметр будет изменен в следующих тестах);
  • -Xmx1024m  — максимальное использование ОЗУ — 1024 МБ;
  • -Xmn64m  — размер кучи для молодого поколения — 64МБ;
  • -Xms128m  — начальный размер кучи Java — 128 МБ;
  • -Xminf0.1 —  этот параметр управляет минимальным свободным пространством в куче и дает указание JVM расширить кучу, если после выполнения сборки мусора у нее не менее 10% свободного места;
  • -Xmaxf0.3 —  этот параметр контролирует, как расширяется куча, и дает указание JVM сжать  кучу, если объем свободного пространства превышает 30%.

Значения по умолчанию для  -Xminf  и  Xmaxf  равны 0,3 и 0,6 соответственно, поэтому JVM пытается поддерживать кучу, которая всегда свободна на 30–60 процентов. Но мы устанавливаем эти параметры в более агрессивных пределах — это увеличивает амплитуду вертикального масштабирования

Как вы можете видеть на графике ниже, динамическая память выделяется и освобождается.

GC1

Следующая диаграмма показывает общее потребление памяти ОС.

GC2

Как видите, в этом случае вертикальное масштабирование работает нормально. К сожалению, Serial Garbage Collector предназначен для использования небольшими приложениями, GC работает в одном потоке.

Плюсы и минусы для серийного сборщика мусора

Плюсы:

  • Показывает хорошие результаты в масштабировании
  • Может выполнять дефрагментацию памяти и возвращает неиспользуемые ресурсы обратно в ОС.
  • Отлично подходит для приложений с небольшими наборами данных

Минусы:

  • Большие паузы, когда это работает с большими наборами данных
  • Большие приложения не нужны

Параллельный сборщик мусора (-XX: + UseParallelGC)

Parallel Garbage Collector выполняет параллельную сборку мусора параллельно, что может значительно сократить издержки на сборку мусора. Это полезно для приложений со средними и крупными наборами данных, которые выполняются на многопроцессорном или многопоточном оборудовании. Мы повторили тестирование, чтобы сравнить результаты.

Тест для параллельного сборщика мусора

Единый процесс:

GC4

Ниже приведено общее потребление памяти ОС:

GC5

Параллельный сборщик мусора имеет много преимуществ по сравнению с последовательным сборщиком мусора. Может работать с многопоточными приложениями и многопроцессорными машинами. Это также хорошо работает с большими наборами данных. Но, как вы можете видеть на приведенных выше графиках, он не очень хорошо возвращает ресурсы в ОС. Таким образом, Parallel GC не подходит для вертикального масштабирования.

Плюсы и минусы параллельного сборщика мусора

Плюсы:

  • Хорошо работает с большими наборами данных и приложениями
  • Отлично работает с многопоточными приложениями и многопроцессорными машинами

Минусы:

  • Не справляется с возвратом ресурсов в ОС
  • Работает нормально, если вам не нужно вертикальное масштабирование

Одновременный сборщик мусора с
меткой (-XX: + UseConcMarkSweepGC)

Concurrent Mark Sweep Garbage Collector выполняет большую часть своей работы одновременно, чтобы сделать короткие паузы сбора мусора короткими. Он предназначен для приложений со средними и крупными наборами данных, для которых время отклика важнее, чем общая пропускная способность.

Мы повторили те же тесты, что и раньше, и получили следующие результаты.

Тест для одновременного сбора метки мусора

Единый процесс:

GC6

Общее потребление памяти ОС:

gc7

Несмотря на то, что у Concurrent Mark Sweep Garbage Collector есть свои преимущества с определенными типами приложений, мы столкнулись в основном с теми же проблемами, что и с Parallel Garbage Collector — он не подходит для вертикального масштабирования.

Плюсы и минусы для одновременного сбора мусора

Плюсы:

  • Хорошо работает с большими наборами данных и приложениями
  • Хорошо работать с многопоточными приложениями и многопроцессорными машинами
  • Время отклика

Минусы:

  • Не справляется с возвратом ресурсов в ОС
  • Пропускная способность является более низким приоритетом
  • Вертикальное масштабирование не работает с ним

G1 Сборщик мусора (-XX: + UseG1GC)

Сборщик мусора G1 («Сначала мусор») был впервые представлен в Java 7, а затем в последующих обновлениях Java 6. Он разбивает кучу на регионы фиксированного размера и отслеживает текущие данные в этих регионах. Когда сбор мусора необходим, он сначала собирает из регионов с меньшим количеством живых данных. Он обладает всеми преимуществами Parallel GC и Mark Sweep GC и отвечает всем нашим требованиям.

Но когда мы проводили наши тесты, мы обнаружили, что в Java 6 после длительного периода работы произошла постоянная и стабильная утечка памяти.

Тест для сборщика мусора G1 ( Java 6)

Единый процесс:

GC8

Общее потребление памяти ОС:

gc9Когда мы нашли эту проблему, мы обратились к парням из Oracle. Мы первыми обнаружили и сообщили о проблеме утечки памяти в Java 6 в отношении G1 GC. Основываясь на нашем мнении, они исправили эту проблему « в полете » в JVM 7. Итак, ниже вы можете увидеть наши тесты после исправления, которое мы попросили их сделать.

Тест для сборщика мусора G1 ( Java 7)

GC10

Как вы можете видеть, исправление, которое ребята из Оракула сделали, действительно улучшило сборщик мусора G1. Мы очень благодарны им за помощь в решении этой проблемы.

Мы надеемся, что в скором времени в Java 6 также будет исправлена ​​проблема утечки памяти. Если вы в настоящее время используете JVM 6, вы можете протестировать его и обратиться в службу поддержки Oracle, как мы это сделали, чтобы ускорить процесс.

Плюсы и минусы для сборщика мусора G1

Минусы:

  • Все еще есть проблема с Java 6 (надеюсь, скоро будет решена)

Плюсы:

  • Хорошо работает как с большими, так и с маленькими наборами данных и приложениями
  • Хорошо работать с многопоточными приложениями и многопроцессорными машинами
  • Хорошо и своевременно возвращает ресурсы в ОС
  • Хорошее время отклика
  • Хорошая пропускная способность
  • Прекрасно работает для вертикального масштабирования

Вывод

Как вы понимаете, возможность платить только за фактически используемые ресурсы очень важна для каждого клиента и компании. Они не должны быть перепроданы и переплачивать. Тем не менее, есть еще несколько блокировщиков, которые препятствуют более быстрому развитию в этом направлении и должны быть исправлены. Jelastic — единственная платформа, которая впервые применила автоматическое вертикальное масштабирование. Мы уже изменили игру и сделаем все возможное, чтобы продолжить революцию в индустрии хостинга.

Вот видео, которое объясняет, как работает автоматическое вертикальное масштабирование в Jelastic:

Автомасштабирование Java-приложений в Jelastic   

* По некоторым причинам официальная ошибка согласно нашему отчету о накопительной утечке памяти G1 была удалена из базы данных ошибок Oracle. Более подробную информацию об этой ошибке можно найти  здесь .