Производительность против надёжности: почему Java-приложения похожи на болиды F1

Рассказывает Стив Бёртон


Вы ещё считаете, что производительность и надежность — одно и то же? Подумайте ещё раз.

Связаны ли производительность и надёжность (productivity и reliability в оригинале), или же это — взаимоисключающие понятия? На мой взгляд, правильным является второй вариант. В наше время большинство людей в сфере IT считает, что производительность и надёжность приложений — это синонимичные понятия, но они как никогда ошибаются.

Давайте взглянем, как команды Формулы 1 относятся к производительности и надёжности. В прошлом сезоне McLaren Honda были медленными и ненадёжными. Ferrari были быстрыми в квалификационных заездах, но ненадёжными в основных. Mercedes же в последние два года были супер-быстрыми и супер-надёжными.

Производительность

Болид F1 обычно оценивается по трём вещам: силовой установке, трёхмерной характеристике двигателя и аэродинамическим характеристикам. Трёхмерная характеристика двигателя показывает уровень потребления ресурсов силовой установкой, а аэродинамика болида зависит от того, как ведёт себя поток воздуха при движении авто. Чем выше мощность и чем ниже посадка, тем меньше сопротивление, быстрее разгон и выше максимальная скорость. От прижимной силы зависит скорость и точность вхождения в повороты.

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

Аналогично, производительность приложений зависит от трёх вещей: JVM-среды (потоков, процессора, памяти), логики приложения и потока транзакций. Логика приложения потребляет ресурсы JVM-среды (потоки, память и т.д.), а поток транзакций характеризуется количеством переходов по компонентам инфраструктуры или сторонним сервисам.

Производительность — это совокупность тайминга запросов пользователей и понимания задержек между логическим аппаратом приложения и поток транзакций. Разработчики, как и инженеры F1, вносят сотни изменений для оптимизации приложения и получения прибыли. Основным параметром производительности является время отклика, и для его измерения используются средства мониторинга производительности приложения (Application Performance Monitoring, APM), такие как AppDynamics, New Relic и Dynatrace.

Надёжность

Надёжность болида F1 зависит от качества его компонентов, электронного блока управления и миллиона странных данных, параметров и функций, поступающих от сенсоров. Стоит не учесть пару параметров, и машина тут же остановится. В прошлом году такое дважды происходило с одним пилотом, хотя у него была одна из самых быстрых машин.

Надёжность — это умение различать два вопроса: почему вещи ломаются и почему они работают медленно.

С приложениями всё так же, только когда падает приложение, это значит, что где-то произошла логическая ошибка или сгенерировалось исключение. Это сильно отличается от случая, когда приложение работает медленно.

Логический аппарат принимает данные, обрабатывает их и что-то выводит. Как и у гоночных болидов, у приложений есть тысячи компонентов (функций) с миллионами строк кода, обрабатывающими сотни тысяч параметров (объектов и переменных) в каждый момент времени. Производительность не имеет смысла без надёжности. Ошибки и исключения «живут» в логах.

Вопрос: Что более важно: скорость поиска авиарейсов или отсутствие ошибок при резервировании билета?

Ответ: И то, и то одинаково важно для всей системы, поэтому заниматься нужно и тем, и тем.

Ошибка при резервировании билета

Добро пожаловать в мир ненужных данных

Положим, что вышеуказанные APM-решения прекрасно справляются с управлением производительностью. Наша индустрия до сих пор считает, что лог-файлы (или «big data», как называют их некоторые) являются ключом к пониманию причин падения приложений. Я бы назвал эти данные, мягко говоря, ненужными.

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

  1. Трассировка стека приложения — показывает, какие компоненты приложения были частью ошибки;
  2. Исходный код приложения — показывает, какая строка кода вызвала ошибку;
  3. Состояние приложения — показывает параметры приложения, которые обрабатывались компонентами/ исходным кодом.

Большинство логов содержат миллионы повторяющихся трассировок стека. Именно поэтому Splunk (компания-разработчик программного обеспечения для обработки и анализа машинно-генерируемых данных) стоит 6 миллиардов долларов, ведь работа с каждой трассировкой стоит денег. Да, разработчики могут кастомизировать лог-файлы, помещая в них любые данные. Плохо то, что нельзя помещать в логи всё (из-за оверхэда), а создание осмысленных сообщений об ошибках часто подразумевает знание того, что в приложении может сломаться.

Без дара предвидения невозможно создать действительно эффективные лог-файлы — поэтому команды часами, а то и днями ищут иголку в стоге сена. Отсутствие исходного кода или состояния приложения означает, что разработчикам придётся действовать наугад, что плохо.

К сожалению, трассировки стека недостаточно. Всё равно, что команда болида F1 сказала бы инженерам: «Телеметрия показала, что руль машины сломан, но больше мы ничего не знаем — ну-ка быстренько во всём разобрались и починили». И что подумают инженеры? К сожалению, именно в такую ситуацию попадает большинство разработчиков, когда в приложении возникают ошибки.

Источник: Блог Takipi