Оптимизация производительности нагруженных веб-систем на Java
1. Оптимизация
производительности
нагруженных веб-систем на Java
Личный опыт и не только
2. Давайте
познакомимся
• alexander.chistyakov@dataart.com
• Разрабатываю с 1998-го
• Разрабатываю на Java с осени 2000-го
• Кроме разработки, занимаюсь
консультированием
команд, разрабатывающих веб-приложения
• Читаю доклады по оптимизации
производительности
3. Вы?
• Разработчики на Java
• Разработчики веб-приложений на Java?
• Архитекторы приложений?
• IT operations engineers?
• Performance engineers?
4. Почему веб-
приложения?
• У веб-приложений много пользователей
• В интернете при решении даже простых
бизнес-задач легко столкнуться с большими
нагрузками
• Интернет большой, и уменьшения числа
пользователей не предвидится – в будущем
любое успешное веб-приложение будет
высоконагруженным
5. Постановка задачи
• Что такое «высокая нагрузка»?
• Все относительно
• Метрики: время обработки запроса и
процент успешно обработанных запросов
• У приложения нет периодов простоя, вас не
будят по ночам – эта презентация не для
вас
• Метрики неудовлетворительны – надо
искать выход
7. Шаманизм и
оптимизация
• http://ru.wikipedia.org/wiki/Карго-культ
• «Сделаем, как у больших (как у Google)»
• «Сделаем, как делал архитектор Вася в
прошлом проекте»
• «Сделаем, как написано в этом блоге»
• Shotgun programming: «Сделаем как-нибудь
и посмотрим» – может быть хорошим
подходом для начала
8. Если это был не
выход...
• Путь 1: Наймите консультанта
• Путь 2: Измеряйте, потом оптимизируйте!
• Что измерять?
• Все, до чего можете дотянуться, в первую
очередь:
• Параметры системы в целом
• Параметры вашего приложения
9. Параметры системы
• Состояние HDD – IOPS, latency
• Состояние оперативной памяти – размер
памяти приложений, размер файлового кэша
• Состояние CPU – user time, system time
• Состояние очереди планировщика – LA
• Состояние сетевой подсистемы – количество
подключений, объем трафика
• Состояние JVM – количество major/minor
garbage collections
10. Сбор параметров
системы
• Java-based: OpenNMS, … - жизнь слишком
коротка, других ресурсов тоже мало
• Zabbix – если вы работаете в Yandex, или у вас
есть время переписать код работы со стат.
данными
• Munin – требует мало ресурсов и не требует
первичной настройки
• Cacti – если используете DBMS MySQL
• Collectd – требует минимальное количество
ресурсов, агент написан на pure C.
11. Параметры
приложения
• Длительность выполнения разных участков
кода приложения
• Потребление памяти структурами данных
• Частота выделения памяти под новые
структуры данных
• Можно использовать профайлер
• Профайлеры: YourKit, JProfiler, …
• Можно использовать другие средства
профилирования
12. Недостатки
профайлера
• Профайлер знает о вашем приложении
гораздо меньше, чем вы
• Профайлер профилирует каждый вызов
• Профайлер может вносить сильную
погрешность и даже менять картину в
целом
• Использование профайлера предполагает
предварительное знакомство с ним
13. Другие средства
• Отладочная печать – служит разработчикам
ПО с 60-х годов прошлого века
• Thread stack sampling (kill -QUIT PID)
• BTrace – аналог DTrace для JVM
• Самостоятельная расстановка вызовов
профилирования в коде (вызовы
JAMon, запись данных во внешнее
хранилище для
постобработки, статистическая
предобработка)
14. Выбор средств
профилирования
• Используйте универсальные средства
• Серебряной пули нет
• А, поэтому, используйте любые средства
• Подумайте об интеграции ваших средств
профилирования со средствами
мониторинга системы
• Подумайте о возможности профилирования
системы в продакшн режиме
15. Нагрузочное
тестирование
• Средства создания тестовой нагрузки –
ab, siege, JMeter, Tsung
• ab и siege – недостаточно настроек
• JMeter – кому-нибудь удавалось создать с
его помощью нагрузку хотя бы в 400 rps с
одного хоста?
• Tsung – может работать в распределенном
режиме, но довольно капризен
16. Случай из жизни 1
• Tomcat, Spring, MySQL, многонодовая
конфигурация в Amazon Cloud
• Куплен профайлер
• Проблемы под тестовой нагрузкой
• Профайлер ничего не показывает
17. Брейндамп решения 1
• Попытка подключить VisualVM (практически
провалилась – RMI плохо работает через
SSH туннель)
• Thread stack sampling в консоли при помощи
стандартной утилиты jstack, сброс сэмплов в
файл и ручной анализ файла
18. Брейндамп 1 – анализ
тред стеков
• Много записи на диск (ведутся логи) –
изменили уровень логгинга
• Потоки стоят на блокировке при обращении
к БД – долго выполняются некоторые из
SQL-запросов (сами запросы написаны
неоптимально)
• Проблема вообще не в Java!
• (зря покупали профайлер)
19. Случай из жизни 2
• Приложение, написанное в 2002-м году
• Weblogic, сервлеты подключенные без
использования web.xml, Solaris
8, Oracle, JVM 1.2, часть бизнес-логики в
хранимых процедурах и другие радости
жизни
• Исходного кода приложения нет
• Первоначально задачи оптимизации
производительности не было, но мне
начали звонить по ночам...
20. Брейндамп решения 2
• Сложный путь апдейта JVM до версии 1.5
• Сбор данных о потреблении памяти, сбор
данных о поведении GC
• Тюнинг Oracle, чтобы он не мешал Java-
приложению
• Попытка тюнинга GC (ни к чему не привела)
• Разные опции запуска JVM, разные версии JVM
• Непонятна корреляция между падениями
системы и внешними событиями
21. Брейндамп решения 2
- продолжение
• Включение access log на время в момент
проблемы с доступностью
• Корень проблемы – брут-форс подбор логинов
и паролей
• Внедрение ehcache и временной блокировки
по IP на час после 10 неудачных попыток
логина в течение 5 минут
• Нагрузка исчезла
• Бывают такие легаси-системы, в которых все
непривычно
22. Случай из жизни 3
• Веб-сайт в Рунете с довольно большой
нагрузкой
• Resin, JSP, servlets, три физических сервера
• RDBMS Firebird
• Apache 1.3 как reverse proxy
• В моменты пиковой нагрузки проблемы с
производительностью вплоть до
недоступности серверов, необходим
рестарт
23. Брейндамп 3
• Команда консультантов поделилась на две
части
• Одна часть – «сисадмины» зачем-то
настраивала mod_accel
• Вторая часть пыталась разбираться с Java и
Firebird
• Анализ Firebird показал, что с ним все в
порядке и улучшить что-либо существенно
нельзя
24. Брейндамп 3 -
продолжение
• Попытка построить тестовое окружение и
профилировать приложение под YourKit
• Профайлер не показал узких мест на том
шаблоне нагрузки, который был применен для
тестирования
• Добавление в код приложения печати
отладочной информации в лог
• Несколько падений системы на глазах
команды, время восстановления после
рестарта по 3.5 часа – разогрев кэшей
25. Брейндамп 3 -
приложение
• Анализ отладочной информации из лога
показал узкое место
• Анализ кода выявил доступ к базе в
synchronized блоке
• Сужение области действия synchronized блока
(разбили на два блока) привело к уменьшению
времени разогрева кэша до нескольких минут
• Используйте lock-free структуры данных
• Не используйте Firebird!
26. Выводы
• Невозможное возможно
• Накапливайте и используйте факты и знания
о вашей системе, не пользуйтесь
религиозными представлениями
примитивных сообществ
• Сложные и дорогие инструменты часто
ничем не лучше простых и бесплатных