Такая сборка позволяет работать как с InfluxDB v2 так и в режими совместимости с InfluxDB v1. Чтобы создать к backet-ам возможность подключения как к v1 базам данных, нужно выполнить в консоли команды
Тут INFLUX_HOST, INFLUX_TOKEN, INFLUX_ORG_ID - параметры подключения к серверу
5d69c811b871b876 -- это bucket, а ClientMetrics -- то как будет называться база данных
Таким образом, для ускорения используются:
больше памяти для сервера
настройки GO для работы с памятью более аккуратно
настройки influxdb, чтобы не выделять очень много памяти на запросы
настройки сервера, чтобы influxdb мог работать с тысячами файлов без ошибок
И еще есть nginx, который кеширует ответы для метода query и включает поддержку CORS для influxdb, так как в самом InfluxDB v2 нет поддержки CORS вообще.
Потеря контекста. Инженеры по производительности могут не иметь достаточного понимания логики работы приложений и сервисов, которые они тестируют. Это может привести к неправильному планированию, моделированию и анализу тестов производительности.
Что тут имеется в виду? Почему инженерам команды продукта не хватало времени на понимание продукта, если они занимались performance-ом в команде, что им мешало узнать продукт ближе?
В этом году конференция очень нагрузочная. Докладов по нагрузке 8. А еще круглый стол по карьере в нагрузке. И не только.
Пусть и habr будет быстрее!
Когда смотрел на раздел Нагрузка https://habr.com/ru/company/jugru/blog/690438/#load, то заметил, что изображения грузятся долго. И подумал, как так, это же habr, тут же отдельный быстрый и надежный хостинг фото?
Фото Анатолия размытоИ оно размыто более 1 секунды (это снимок из результатов тестов sitespeed.io)
И поэтому минимальное время загрузки изображения 200-300 + 2 мсек при повторном открытии. Или 200-300 + 600-700 при первом открытии. А могло быть лишь 2 мсек почти всегда!
Убедиться в этом можно, используя инструменты разработчика вашего браузера:
1344 мсек на habrastorage.org, потом редирект и еще 966 мсек на hsto.org
К сожалению такие проблемки есть много где, и на проекте, где сам работаю - знаю о них, все будет ускорено. Искать их несложно и интересно.
Кирилл, спасибо! Тут любой вопрос дорогой. Вот вы делали, в том числе эксперименты, командой 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 запросов в сек.
Сколько памяти нужно серверу сказать сложно. У меня базы данных, размером около 15 ГБайт:
При этом сервису выделено 25 ГБайт HEAP, а на самом сервере 32 ГБайт ОЗУ
Базы данных достаточно нагруженные, потребление ресурсов такое:
Res: 9 ГБайт (всего выделено 25 ГБайт Heap, а памяти на сервере 30 ГБайт физически)
Virt: 40 ГБайт
Shr: 633 МБайт (для контейнера задан
--shm-size 2g)
Под нагрузкой все 8 ядер процессора используются. Технически такую базу данных можно перести на сервер, где будет только 16 ГБайт ОЗУ и
GOMEMLIMIT=11GiB
А также можно сократить и настройку shm до 1g -- тоже хватит
Но ядра CPU нужны
Всем привет!
Прошло время, я обновился до InfluxDB v2
Стал использовать станцию
Instance type
m5a.2xlarge -- 32 ГБайт ОЗУ
https://instances.vantage.sh/aws/ec2/m5a.2xlarge
Запускаю сервис вот так:
Где файл env.list это файл, в котором задано использование только 25 ГБайт ОЗУ из 32-х и другие более строгие лимиты по памяти:
Кроме того в файле /etc/security/limits.conf были увеличены лимиты на файлы
а также добавлены блоки в конфиги, чтобы эта правка применялась при каждой перезагрузке тоже
И увеличены лимиты для системы:
Такая сборка позволяет работать как с InfluxDB v2 так и в режими совместимости с InfluxDB v1. Чтобы создать к backet-ам возможность подключения как к v1 базам данных, нужно выполнить в консоли команды
Тут INFLUX_HOST, INFLUX_TOKEN, INFLUX_ORG_ID - параметры подключения к серверу
5d69c811b871b876 -- это bucket, а ClientMetrics -- то как будет называться база данных
Таким образом, для ускорения используются:
больше памяти для сервера
настройки GO для работы с памятью более аккуратно
настройки influxdb, чтобы не выделять очень много памяти на запросы
настройки сервера, чтобы influxdb мог работать с тысячами файлов без ошибок
И еще есть nginx, который кеширует ответы для метода query и включает поддержку CORS для influxdb, так как в самом InfluxDB v2 нет поддержки CORS вообще.
nginx.conf:
Скрытый текст
Что тут имеется в виду? Почему инженерам команды продукта не хватало времени на понимание продукта, если они занимались 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 запросов в сек.