Как стать автором
Обновить
49
0
Вячеслав @polarnik

Performance Engineer

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

Что тут имеется в виду? Почему инженерам команды продукта не хватало времени на понимание продукта, если они занимались performance-ом в команде, что им мешало узнать продукт ближе?

Спасибо за статью, Виктор! Каждый раз к ней обращаюсь, когда настраиваю профилирование

upd: написал разработчикам о проблеме и варианте решения

В этом году конференция очень нагрузочная. Докладов по нагрузке 8. А еще круглый стол по карьере в нагрузке. И не только.

Пусть и habr будет быстрее!

Когда смотрел на раздел Нагрузка https://habr.com/ru/company/jugru/blog/690438/#load, то заметил, что изображения грузятся долго. И подумал, как так, это же habr, тут же отдельный быстрый и надежный хостинг фото?

Фото Анатолия размыто
Фото Анатолия размыто
И оно размыто более 1 секунды (это снимок из результатов тестов sitespeed.io)
И оно размыто более 1 секунды (это снимок из результатов тестов sitespeed.io)

Разобрался, при загрузке изображения на сайт предоставляется ссылка:
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 мсек почти всегда!

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

1344 мсек на habrastorage.org, потом редирект и еще 966 мсек на hsto.org
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, чтобы один раз открыть страницу и получить ее ресурсы используя Routehttps://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 а

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 запросов в сек.

Возможно, я серьёзно недоглядел чего-то в документации, но мне не удалось найти способа, допустим, настроить периодическое событие, запускаемое каждые 30 секунд и выполняющее определённые действия при ответе на сообщение WebSocket, а также производящее действия по HTTP, и всё это в рамках одной HTTP-сессии. Я не нашёл такой возможности ни в одном инструменте нагрузочного тестирования

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


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

Согласно текущему состоянию матрицы:
https://github.com/open-telemetry/opentelemetry-specification/blob/master/spec-compliance-matrix.md
Для Java нет поддержки Zipkin и Jaeger. Телеметрия в лог не так интересна. А как использовать OLTP/gRPC пока не представляю:


Exporters


Но поддержка Zipkin и Jaeger есть при использовании Python и .NET, именно это и имел в виду.


Если я неверно прочел таблицу. И варианты:


  • Service name mapping
  • SpanKind mapping
  • InstrumentationLibrary mapping

это варианты подключения Zipkin/Jaeger API, то тогда был не прав — поддержка есть везде во всех языках.

1
23 ...

Информация

В рейтинге
Не участвует
Откуда
Армения
Зарегистрирован
Активность

Специализация

Software Performance Engineer
Lead
PostgreSQL
Java
High-loaded systems
Kubernetes