uzluga.ru
добавить свой файл


Оптимизация производительности нагруженных веб-систем на Java

Личный опыт и не только

Давайте познакомимся

  • alexander.chistyakov@dataart.com

  • Разрабатываю с 1998-го

  • Разрабатываю на Java с осени 2000-го

  • Кроме разработки, занимаюсь консультированием команд, разрабатывающих веб-приложения

  • Читаю доклады по оптимизации производительности



Вы?

  • Разработчики на Java

  • Разработчики веб-приложений на Java?

  • Архитекторы приложений?

  • IT operations engineers?

  • Performance engineers?



Почему веб-приложения?

  • У веб-приложений много пользователей

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

  • Интернет большой, и уменьшения числа пользователей не предвидится – в будущем любое успешное веб-приложение будет высоконагруженным



Постановка задачи

  • Что такое «высокая нагрузка»?

  • Все относительно

  • Метрики: время обработки запроса и процент успешно обработанных запросов

  • У приложения нет периодов простоя, вас не будят по ночам – эта презентация не для вас 

  • Метрики неудовлетворительны – надо искать выход



Где же выход?



Шаманизм и оптимизация

  • http://ru.wikipedia.org/wiki/Карго-культ

  • «Сделаем, как у больших (как у Google)»

  • «Сделаем, как делал архитектор Вася в прошлом проекте»

  • «Сделаем, как написано в этом блоге»

  • Shotgun programming: «Сделаем как-нибудь и посмотрим» – может быть хорошим подходом для начала



Если это был не выход...

  • Путь 1: Наймите консультанта

  • Путь 2: Измеряйте, потом оптимизируйте!

  • Что измерять?

  • Все, до чего можете дотянуться, в первую очередь:

  • Параметры системы в целом

  • Параметры вашего приложения



Параметры системы

  • Состояние HDD – IOPS, latency

  • Состояние оперативной памяти – размер памяти приложений, размер файлового кэша

  • Состояние CPU – user time, system time

  • Состояние очереди планировщика – LA

  • Состояние сетевой подсистемы – количество подключений, объем трафика

  • Состояние JVM – количество major/minor garbage collections



Сбор параметров системы

  • Java-based: OpenNMS, … - жизнь слишком коротка, других ресурсов тоже мало

  • Zabbix – если вы работаете в Yandex, или у вас есть время переписать код работы со стат. данными

  • Munin – требует мало ресурсов и не требует первичной настройки

  • Cacti – если используете DBMS MySQL

  • Collectd – требует минимальное количество ресурсов, агент написан на pure C.



Параметры приложения

  • Длительность выполнения разных участков кода приложения

  • Потребление памяти структурами данных

  • Частота выделения памяти под новые структуры данных

  • Можно использовать профайлер

  • Профайлеры: YourKit, JProfiler, …

  • Можно использовать другие средства профилирования



Недостатки профайлера

  • Профайлер знает о вашем приложении гораздо меньше, чем вы

  • Профайлер профилирует каждый вызов

  • Профайлер может вносить сильную погрешность и даже менять картину в целом

  • Использование профайлера предполагает предварительное знакомство с ним



Другие средства

  • Отладочная печать – служит разработчикам ПО с 60-х годов прошлого века

  • Thread stack sampling (kill -QUIT PID)

  • BTrace – аналог DTrace для JVM

  • Самостоятельная расстановка вызовов профилирования в коде (вызовы JAMon, запись данных во внешнее хранилище для постобработки, статистическая предобработка)



Выбор средств профилирования

  • Используйте универсальные средства

  • Серебряной пули нет

  • А, поэтому, используйте любые средства

  • Подумайте об интеграции ваших средств профилирования со средствами мониторинга системы

  • Подумайте о возможности профилирования системы в продакшн режиме



Нагрузочное тестирование

  • Средства создания тестовой нагрузки – ab, siege, JMeter, Tsung

  • ab и siege – недостаточно настроек

  • JMeter – кому-нибудь удавалось создать с его помощью нагрузку хотя бы в 400 rps с одного хоста?

  • Tsung – может работать в распределенном режиме, но довольно капризен



Случай из жизни 1

  • Tomcat, Spring, MySQL, многонодовая конфигурация в Amazon Cloud

  • Куплен профайлер

  • Проблемы под тестовой нагрузкой

  • Профайлер ничего не показывает



Брейндамп решения 1

  • Попытка подключить VisualVM (практически провалилась – RMI плохо работает через SSH туннель)

  • Thread stack sampling в консоли при помощи стандартной утилиты jstack, сброс сэмплов в файл и ручной анализ файла



Брейндамп 1 – анализ тред стеков

  • Много записи на диск (ведутся логи) – изменили уровень логгинга

  • Потоки стоят на блокировке при обращении к БД – долго выполняются некоторые из SQL-запросов (сами запросы написаны неоптимально)

  • Проблема вообще не в Java!

  • (зря покупали профайлер)



Случай из жизни 2

  • Приложение, написанное в 2002-м году

  • Weblogic, сервлеты подключенные без использования web.xml, Solaris 8, Oracle, JVM 1.2, часть бизнес-логики в хранимых процедурах и другие радости жизни

  • Исходного кода приложения нет

  • Первоначально задачи оптимизации производительности не было, но мне начали звонить по ночам...



Брейндамп решения 2

  • Сложный путь апдейта JVM до версии 1.5

  • Сбор данных о потреблении памяти, сбор данных о поведении GC

  • Тюнинг Oracle, чтобы он не мешал Java-приложению

  • Попытка тюнинга GC (ни к чему не привела)

  • Разные опции запуска JVM, разные версии JVM

  • Непонятна корреляция между падениями системы и внешними событиями



Брейндамп решения 2 - продолжение

  • Включение access log на время в момент проблемы с доступностью

  • Корень проблемы – брут-форс подбор логинов и паролей

  • Внедрение ehcache и временной блокировки по IP на час после 10 неудачных попыток логина в течение 5 минут

  • Нагрузка исчезла

  • Бывают такие легаси-системы, в которых все непривычно



Случай из жизни 3

  • Веб-сайт в Рунете с довольно большой нагрузкой

  • Resin, JSP, servlets, три физических сервера

  • RDBMS Firebird

  • Apache 1.3 как reverse proxy

  • В моменты пиковой нагрузки проблемы с производительностью вплоть до недоступности серверов, необходим рестарт



Брейндамп 3

  • Команда консультантов поделилась на две части

  • Одна часть – «сисадмины» зачем-то настраивала mod_accel

  • Вторая часть пыталась разбираться с Java и Firebird

  • Анализ Firebird показал, что с ним все в порядке и улучшить что-либо существенно нельзя



Брейндамп 3 - продолжение

  • Попытка построить тестовое окружение и профилировать приложение под YourKit

  • Профайлер не показал узких мест на том шаблоне нагрузки, который был применен для тестирования

  • Добавление в код приложения печати отладочной информации в лог

  • Несколько падений системы на глазах команды, время восстановления после рестарта по 3.5 часа – разогрев кэшей



Брейндамп 3 - приложение

  • Анализ отладочной информации из лога показал узкое место

  • Анализ кода выявил доступ к базе в synchronized блоке

  • Сужение области действия synchronized блока (разбили на два блока) привело к уменьшению времени разогрева кэша до нескольких минут

  • Используйте lock-free структуры данных

  • Не используйте Firebird! 



Выводы

  • Невозможное возможно

  • Накапливайте и используйте факты и знания о вашей системе, не пользуйтесь религиозными представлениями примитивных сообществ

  • Сложные и дорогие инструменты часто ничем не лучше простых и бесплатных



Вопросы?



Спасибо за внимание!