Потеря контекста. Инженеры по производительности могут не иметь достаточного понимания логики работы приложений и сервисов, которые они тестируют. Это может привести к неправильному планированию, моделированию и анализу тестов производительности.
Что тут имеется в виду? Почему инженерам команды продукта не хватало времени на понимание продукта, если они занимались performance-ом в команде, что им мешало узнать продукт ближе?
В этом году конференция очень нагрузочная. Докладов по нагрузке 8. А еще круглый стол по карьере в нагрузке. И не только.
Пусть и habr будет быстрее!
Когда смотрел на раздел Нагрузка https://habr.com/ru/company/jugru/blog/690438/#load, то заметил, что изображения грузятся долго. И подумал, как так, это же habr, тут же отдельный быстрый и надежный хостинг фото?
И поэтому минимальное время загрузки изображения 200-300 + 2 мсек при повторном открытии. Или 200-300 + 600-700 при первом открытии. А могло быть лишь 2 мсек почти всегда!
Убедиться в этом можно, используя инструменты разработчика вашего браузера:
К сожалению такие проблемки есть много где, и на проекте, где сам работаю - знаю о них, все будет ускорено. Искать их несложно и интересно.
Кирилл, спасибо! Тут любой вопрос дорогой. Вот вы делали, в том числе эксперименты, командой 2-4 человека в течение 4 месяцев. Это 12 человеко-месяцев, мифических. Мне хочется сделать за спринт или за пару дней ))
И поэтому я думаю вообще не писать тесты пока, массово не писать. Вот есть статистика, пусть в Elastic, есть понятные способы ее обработки и мониторинга. И уже можно завести дефекты на ряд очевидных случаев.
Для неочевидных случаев, где нужно профилировать на тестовом стенде, в качестве исключения можно написать тесты. Сначала самые дешевые и простые. Потом посложнее, с параметрами, если простых не хватит.
Еще важный момент — определить какой профиль нагрузки сейчас актуален, если хочется повторить ситуацию продакшена. Поэтому у нас есть автосборщик, интегрированный с нашей библиотекой, который внутрь теста подкидывает актуальные данные. Так можно с определенной точностью оценить, как текущий релиз жил бы на продакшене, если бы зарелизился прямо сейчас.
Вы собираете профиль нагрузки с продуктива.
Что используется в качестве основы? Как идет работа с параметрами запросов? Есть ли что-то аналогичные property based testing, но для нагрузки в вашем подходе?
Например, (GET) /{categoryID}/positions — есть такой метод для меню доставки товаров, и вы решили его нагрузить
Если его передать в запрос вот прямо вот так:
(GET) /30/positions, то это будет запрос без фильтров и с параметрами по умолчанию
(GET) /30/positions?type=ALL&limit=100 Возвращает сначала 10 000 элементов и оставляет из них 100, у такого запроса пусть узкое место в том, что там фильтрация Limit 100 внутри сделана не средствами SQL-запроса, а средствами фильтрации коллекции ответов в памяти бекенда на Java/Kotlin
(GET) /30/positions?type=ALL&limit=100&search=Pizza Возвращает сначала 5 элементов пиццы и оставляет из них 5 — этот запрос пусть работает всегда быстрее, чем предыдущие два варианта, потому что тут результатов мало из-за более строгой фильтрации
В тесте будут использоваться полные URL или может только первый вариант без параметров? Деперсонализация базы данных позволит использовать оригинальные ID-шки в тестовых запросах
Может быть, нужно провести полноценное обучение? Научить всех быть супер-спецами. Они будут делать красное нагрузочное тестирование, и все запоет-засияет. Обучили какой-то состав, ребята стали супер-спецами… и ушли в другую компанию, потому что там больше платят, например.
Вот тут я напрягся
Сейчас мы находимся на этапе планового внедрения его в каждую команду Самоката и проводим микрообучения.
Вот тут отпустило
То есть обучение нужно, но пререквизитом идет стандартизация, шаблонизация, некая база?
Можно собрать k6 с дополнительным модулем xk6-browser (задача непростая) или скачать собранный. Использовать функцию setup, чтобы один раз открыть страницу и получить ее ресурсы используя Route — https://try.playwright.tech/?e=intercept-requests.
// Log and continue all network requests
page.route('**', (route, request) => {
if(request.method() == 'GET' &&
request.url().toString().indexOf('testserver:5000/')>0) {
console.log(request.url()); // тут копирование в список
}
route.continue();
});
Положить ссылки на ресурсы в список или в map, где ключ будет базовой ссылкой, а значениями — список ссылок на связанные ресурсы. Написать два теста. Один, который загружает только базовую ссылку, пусть в 95% случаев и второй, которой имитирует загрузку с пустым кешем браузера, пусть в 5% случаев. Загрузка с пустым кешем — это загрузка всех ссылок
Это сложный способ описал. Простой может кто-то еще подскажет
Статья хорошая. Для целей отслеживания деградаций я бы порекомендовал заменить подход с нагрузкой в пользователях/потоках без пауз: startVUs: 100, target: 1000 на профиль с фиксированной нагрузкой. Так можно будет оценивать время ответа.
Если этого не сделать, то вот приложение обрабатывало запросы от 100 потоков пусть за 100 мсек и мы получали 1000 rps. Вот оно стало оптимальнее, и готово обрабатывать запросы за 50 мсек, но в него приходит нагрузка в 2000 rps и мы получаем все равно тормоза и те же 100 мсек - не видим разницы.
В подходе с пулом подключений основная метрика не http_req_duration а
Виктор, привет! Спасибо за твою статью про JFR, ссылался на нее в выступлении.
Да, ты прав. С включением профилирования налету, а в частности, с включением Offline-профилирования есть, в дополнение, такие наблюдения.
Запускать offline-профилирование (массовое на группу сервисов) надо с задержкой не менее 1 минуты от старта JVM. Иначе JVM в Kubernets, может вообще не стартовать. Профилировать с 0-й секунды после старта JVM не получается. У меня ни разу не получилось запустить сервис с профилированием прямо со старта.
У сервиса есть readness и leavness-пробы. Пусть 10 минут. А профилирование, запущенное до ввода сервиса в балансировку, может замедлить старт сервиса и сервис стартанет только через 15 минут. А через 10 минут его перезагрузит Kubernetes, так как истечет таймаут на запуск. И чтобы такого не происходило надо или пробы увеличивать. Или оставлять в настройках профилирования самый минимум - профилирование кода семплированием потоков. Может быть сбор исключений. Может быть какую-то еще дополнительную статистику. Не больше. И запускать профилирование с таймером 15 минут от момента старта сервиса. Чтобы сервис сначала нормально стартанул. Включился в балансировку. А уже потом запустилось профилирование.
Спасибо. Я и правда называл VisualVM, как JVisualVM. Позже подготовлю для Антона список правок. Например, заметил, что когда говорил про нативную инструментацию и gcc, то получилось по статье, как про JCC.
Чтобы в SVG-изображениях не использовался шрифт Times New Roman, а использовался Roboto, надо скачать и поставить локально шрифт https://fonts.google.com/specimen/Roboto (ссылка в правом верхнем углу страницы - Download family по ссылке выше)
Если появятся вопросы, буду рад. Задавайте тут. Или в telegram: https://t.me/qa_load
и по возможности повторить замер. Или провести замер, подавая нагрузку со станции внутри кластера.
Также некоторые инструменты не закрывают TCP-подключение к серверу, поэтому они иногда заявляют, что обгоняют по производительности инструменты которые закрывают и открывают снова.
Инструменты, которые закрывают подключения после каждого теста:
Apache.JMeter, но если в конфигурационный файл jmeter.properties внести настройку httpclient.reset_state_on_thread_group_iteration=false, то тоже не будет закрывать
Gatling, но если в настройки http-протокола добавить shareConnections , то тоже не будут, пример.
Инструменты, которые не закрывают подключения:
k6
ab
Как поступает Soap UI не знаю, и не знаю если ли у него настройки для изменения поведения.
Резюмируя: изменение инструмента или его настроек также можно повысить RPS
Можно предположить, что вся команда отлично знает базы данных. Так как поддерживает механизм подчистки. Мой опыт такой, что поддерживать такие скрипты можно, но для отдельных микросервисов. А для всех сервисов - сложно
Другое предположение, что основные сценарии только на чтение и ничего не создают. Это интересная мысль. Пробовали в команде такое сделать однажды, но для функциональных автоматических тестов, которые ничего не создают, а проверяют, что стенд работает.
И симуляция реального пользователя для большой нагрузки (100-1000 запросов в сек) вредна и не нужна. Проблемы автора, думаю, от этой идеи фикс. Но так можно делать для малой нагрузки.
Иногда идея фикс принимает форму: нам нужна нагрузка от 100 000 пользователей, значит нам нужно 100 000 потоков в JMeter.
Иногда такую: пользователь зайдя на сайт с вероятностью 80% ищет телефон, с вероятностью 70% красный, он может уточнить свой поиск, если наше телефон,… В результате люди пишут сложный функциональный тест на JMeter/Gatling, вместо того, чтобы заниматься нагрузкой.
А на деле все проще. От нагрузки требуется создать лишь интенсивность. По возможности повторить время жизни сессии — но это можно делать отдельно, не в JMeter/Gatling/… уже, а в параллельном автотесте, который работает в 1 поток.
Раз автор хочет все сразу, то у него нагрузка малая — до 10 запросов в сек.
Возможно, я серьёзно недоглядел чего-то в документации, но мне не удалось найти способа, допустим, настроить периодическое событие, запускаемое каждые 30 секунд и выполняющее определённые действия при ответе на сообщение WebSocket, а также производящее действия по HTTP, и всё это в рамках одной HTTP-сессии. Я не нашёл такой возможности ни в одном инструменте нагрузочного тестирования
Это чрезмерное усложнение. Всегда можно создать отдельный поток, отдельное подключение, чтобы реализовать задуманное. Да подключений будет больше, но на производительность и функциональность это чаще всего не влияет.
А стремление создать в тесте производительности поведение реального пользователя — чаще всего недостижимо. И сделать профиль нагрузки на бумажке, лишь опираясь на логи — хороший подход. Тут согласен. Пример такой, по логам можно узнать интенсивность входов. А у аналитика узнать, что треть пользователей выполняет операцию Х. И вот теперь, на листочке, можно примерно оценить интенсивность операции Х, как функции от интенсивности входа, даже если по Х не было никакой статистики.
Что тут имеется в виду? Почему инженерам команды продукта не хватало времени на понимание продукта, если они занимались performance-ом в команде, что им мешало узнать продукт ближе?
Спасибо за статью, Виктор! Каждый раз к ней обращаюсь, когда настраиваю профилирование
upd: написал разработчикам о проблеме и варианте решения
В этом году конференция очень нагрузочная. Докладов по нагрузке 8. А еще круглый стол по карьере в нагрузке. И не только.
Пусть и habr будет быстрее!
Когда смотрел на раздел Нагрузка https://habr.com/ru/company/jugru/blog/690438/#load, то заметил, что изображения грузятся долго. И подумал, как так, это же habr, тут же отдельный быстрый и надежный хостинг фото?
Разобрался, при загрузке изображения на сайт предоставляется ссылка:
https://habrastorage.org/getpro/habr/upload_files/5fb/14d/3b8/5fb14d3b82545757b366e83cdf6efda6.jpeg (ответ отдается за 200-300 мсек)
и она используется в публикации. Ответ на такой запрос отдается всегда без кеширования и содержит редирект на другой сайт
https://hsto.org/getpro/habr/upload_files/5fb/14d/3b8/5fb14d3b82545757b366e83cdf6efda6.jpeg (ответ за 600-700 мсек для первого ответа, и 2 мсек для ответа из кеша).
А этот ответ уже успешно кешируется
И поэтому минимальное время загрузки изображения 200-300 + 2 мсек при повторном открытии. Или 200-300 + 600-700 при первом открытии. А могло быть лишь 2 мсек почти всегда!
Убедиться в этом можно, используя инструменты разработчика вашего браузера:
К сожалению такие проблемки есть много где, и на проекте, где сам работаю - знаю о них, все будет ускорено. Искать их несложно и интересно.
Надеюсь, что заинтересовал темой. До встречи!
Кирилл, спасибо! Тут любой вопрос дорогой. Вот вы делали, в том числе эксперименты, командой 2-4 человека в течение 4 месяцев. Это 12 человеко-месяцев, мифических. Мне хочется сделать за спринт или за пару дней ))
И поэтому я думаю вообще не писать тесты пока, массово не писать. Вот есть статистика, пусть в Elastic, есть понятные способы ее обработки и мониторинга. И уже можно завести дефекты на ряд очевидных случаев.
Для неочевидных случаев, где нужно профилировать на тестовом стенде, в качестве исключения можно написать тесты. Сначала самые дешевые и простые. Потом посложнее, с параметрами, если простых не хватит.
Вы собираете профиль нагрузки с продуктива.
Что используется в качестве основы? Как идет работа с параметрами запросов? Есть ли что-то аналогичные property based testing, но для нагрузки в вашем подходе?
Например, (GET) /{categoryID}/positions — есть такой метод для меню доставки товаров, и вы решили его нагрузить
Если его передать в запрос вот прямо вот так:
(GET) /30/positions, то это будет запрос без фильтров и с параметрами по умолчанию
(GET) /30/positions?type=ALL&limit=100
Возвращает сначала 10 000 элементов и оставляет из них 100, у такого запроса пусть узкое место в том, что там фильтрация Limit 100 внутри сделана не средствами SQL-запроса, а средствами фильтрации коллекции ответов в памяти бекенда на Java/Kotlin
(GET) /30/positions?type=ALL&limit=100&search=Pizza
Возвращает сначала 5 элементов пиццы и оставляет из них 5 — этот запрос пусть работает всегда быстрее, чем предыдущие два варианта, потому что тут результатов мало из-за более строгой фильтрации
В тесте будут использоваться полные URL или может только первый вариант без параметров? Деперсонализация базы данных позволит использовать оригинальные ID-шки в тестовых запросах
Вот тут я напрягся
Вот тут отпустило
То есть обучение нужно, но пререквизитом идет стандартизация, шаблонизация, некая база?
Можно собрать k6 с дополнительным модулем xk6-browser (задача непростая) или скачать собранный. Использовать функцию setup, чтобы один раз открыть страницу и получить ее ресурсы используя Route — https://try.playwright.tech/?e=intercept-requests.
Положить ссылки на ресурсы в список или в map, где ключ будет базовой ссылкой, а значениями — список ссылок на связанные ресурсы. Написать два теста. Один, который загружает только базовую ссылку, пусть в 95% случаев и второй, которой имитирует загрузку с пустым кешем браузера, пусть в 5% случаев. Загрузка с пустым кешем — это загрузка всех ссылок
Это сложный способ описал. Простой может кто-то еще подскажет
Статья хорошая. Для целей отслеживания деградаций я бы порекомендовал заменить подход с нагрузкой в пользователях/потоках без пауз: startVUs: 100, target: 1000 на профиль с фиксированной нагрузкой. Так можно будет оценивать время ответа.
Если этого не сделать, то вот приложение обрабатывало запросы от 100 потоков пусть за 100 мсек и мы получали 1000 rps. Вот оно стало оптимальнее, и готово обрабатывать запросы за 50 мсек, но в него приходит нагрузка в 2000 rps и мы получаем все равно тормоза и те же 100 мсек - не видим разницы.
В подходе с пулом подключений основная метрика не http_req_duration а
http_reqs......................: 10908 1081.901504/s
Если стало ниже, чем вчера - стало хуже.
А вот если подавать постоянную нагрузку, пусть в 150 rps, например, как на продуктиве или близко, вот так
https://k6.io/docs/using-k6/scenarios/executors/constant-arrival-rate
то будет тест для регрессионного тестирования, в котором можно замерять время ответа.
Привет! А как выполняется работа с транзакциями? Понимаю, что можно явно написать в тексте SQL-запроса:
Commit
Rollback
Есть ли настройки для Autocommit, какие они по умолчанию? В коде нашел задание настройки только для Batch-операции, и она false: https://github.com/Tinkoff/gatling-jdbc-plugin/blob/v0.5.0/src/main/scala/ru/tinkoff/load/jdbc/db/JDBCClient.scala#L49
Виктор, привет! Спасибо за твою статью про JFR, ссылался на нее в выступлении.
Да, ты прав. С включением профилирования налету, а в частности, с включением Offline-профилирования есть, в дополнение, такие наблюдения.
Запускать offline-профилирование (массовое на группу сервисов) надо с задержкой не менее 1 минуты от старта JVM. Иначе JVM в Kubernets, может вообще не стартовать. Профилировать с 0-й секунды после старта JVM не получается. У меня ни разу не получилось запустить сервис с профилированием прямо со старта.
У сервиса есть readness и leavness-пробы. Пусть 10 минут. А профилирование, запущенное до ввода сервиса в балансировку, может замедлить старт сервиса и сервис стартанет только через 15 минут. А через 10 минут его перезагрузит Kubernetes, так как истечет таймаут на запуск. И чтобы такого не происходило надо или пробы увеличивать. Или оставлять в настройках профилирования самый минимум - профилирование кода семплированием потоков. Может быть сбор исключений. Может быть какую-то еще дополнительную статистику. Не больше. И запускать профилирование с таймером 15 минут от момента старта сервиса. Чтобы сервис сначала нормально стартанул. Включился в балансировку. А уже потом запустилось профилирование.
Спасибо. Я и правда называл VisualVM, как JVisualVM. Позже подготовлю для Антона список правок. Например, заметил, что когда говорил про нативную инструментацию и gcc, то получилось по статье, как про JCC.
Антон, спасибо! Здорово!
Если понадобится скрипты, например, для SJK скопировать со слайдов, то слайды тут: https://polarnik.github.io/JVM-profiling-in-Kubernetes/
Чтобы в SVG-изображениях не использовался шрифт Times New Roman, а использовался Roboto, надо скачать и поставить локально шрифт https://fonts.google.com/specimen/Roboto (ссылка в правом верхнем углу страницы - Download family по ссылке выше)
Если появятся вопросы, буду рад. Задавайте тут. Или в telegram: https://t.me/qa_load
Привет! Тестовый агент с SoapUI запускался на локальной станции, на ноутбуке?
Результат в RPS мог получиться скромным из-за запуска теста через интернет. По ряду причин:
исчерпание TCP-подключений, проблема TCP Time Wait в Windows также актуальна, как и в Linux
лимиты сетевого провайдера, иногда это троттлинг (защита от DoS со стороны абонента) иногда просто ограничение пропускной способности
лимиты Azure (защита от DDoS/DoS на стороне площадки)
Скорее всего первая причина
Стоит проверить рекомендации из статьи базы знаний Microsoft:
https://docs.microsoft.com/ru-ru/windows/client-management/troubleshoot-tcpip-port-exhaust
и по возможности повторить замер. Или провести замер, подавая нагрузку со станции внутри кластера.
Также некоторые инструменты не закрывают TCP-подключение к серверу, поэтому они иногда заявляют, что обгоняют по производительности инструменты которые закрывают и открывают снова.
Инструменты, которые закрывают подключения после каждого теста:
Apache.JMeter, но если в конфигурационный файл jmeter.properties внести настройку httpclient.reset_state_on_thread_group_iteration=false, то тоже не будет закрывать
Gatling, но если в настройки http-протокола добавить shareConnections , то тоже не будут, пример.
Инструменты, которые не закрывают подключения:
k6
ab
Как поступает Soap UI не знаю, и не знаю если ли у него настройки для изменения поведения.
Резюмируя: изменение инструмента или его настроек также можно повысить RPS
Что выступает агентом мониторинга, который кладет данные в Clickhouse?
Используется отправка JSON через Kafka или Graphite-интерфейс или HTTP-протокол ClickHouse?
Или это какая-то интеграция с Prometheus, Victoria, InfluxDB перекладывает метрики в ClickHouse?
Можно предположить, что вся команда отлично знает базы данных. Так как поддерживает механизм подчистки. Мой опыт такой, что поддерживать такие скрипты можно, но для отдельных микросервисов. А для всех сервисов - сложно
Другое предположение, что основные сценарии только на чтение и ничего не создают. Это интересная мысль. Пробовали в команде такое сделать однажды, но для функциональных автоматических тестов, которые ничего не создают, а проверяют, что стенд работает.
Коллеги из Перфоманс Лаб сделали хороший вариант статьи про ускорение JMeter на английском языке:
И симуляция реального пользователя для большой нагрузки (100-1000 запросов в сек) вредна и не нужна. Проблемы автора, думаю, от этой идеи фикс. Но так можно делать для малой нагрузки.
Иногда идея фикс принимает форму: нам нужна нагрузка от 100 000 пользователей, значит нам нужно 100 000 потоков в JMeter.
Иногда такую: пользователь зайдя на сайт с вероятностью 80% ищет телефон, с вероятностью 70% красный, он может уточнить свой поиск, если наше телефон,… В результате люди пишут сложный функциональный тест на JMeter/Gatling, вместо того, чтобы заниматься нагрузкой.
А на деле все проще. От нагрузки требуется создать лишь интенсивность. По возможности повторить время жизни сессии — но это можно делать отдельно, не в JMeter/Gatling/… уже, а в параллельном автотесте, который работает в 1 поток.
Раз автор хочет все сразу, то у него нагрузка малая — до 10 запросов в сек.
Это чрезмерное усложнение. Всегда можно создать отдельный поток, отдельное подключение, чтобы реализовать задуманное. Да подключений будет больше, но на производительность и функциональность это чаще всего не влияет.
А стремление создать в тесте производительности поведение реального пользователя — чаще всего недостижимо. И сделать профиль нагрузки на бумажке, лишь опираясь на логи — хороший подход. Тут согласен. Пример такой, по логам можно узнать интенсивность входов. А у аналитика узнать, что треть пользователей выполняет операцию Х. И вот теперь, на листочке, можно примерно оценить интенсивность операции Х, как функции от интенсивности входа, даже если по Х не было никакой статистики.
Согласно текущему состоянию матрицы:
https://github.com/open-telemetry/opentelemetry-specification/blob/master/spec-compliance-matrix.md
Для Java нет поддержки Zipkin и Jaeger. Телеметрия в лог не так интересна. А как использовать OLTP/gRPC пока не представляю:
Но поддержка Zipkin и Jaeger есть при использовании Python и .NET, именно это и имел в виду.
Если я неверно прочел таблицу. И варианты:
это варианты подключения Zipkin/Jaeger API, то тогда был не прав — поддержка есть везде во всех языках.