Ранее мы обсудили grid и flex, а также верстку UI.

Для чего вообще создаются разные инструменты?

Очевидно же - делать работу легче и помогать в достижении результата! Молотком проще забивать гвозди, чем камнем, а гвоздодером их быстрее доставать чем чем-либо другим.

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

Наши ожидания подкрепляются рекламными проспектами, убеждающими нас, что... все инструменты лучше всех конкурентов. Во всем!

В результате представляется сказочный путь к счастью: "Без проблем установил, легко запустил и получил отличный результат." Просто. А сложностей и без того достаточно.

Давайте пройдемся по этому пути, пытаясь решить некие задачи нагрузочного тестирования!

Будем сравнивать подходы различных инструментов под микроскопом, разглядывая дьявола, который спрятался в деталях ;)

Несмотря на то, что ниже по тексту популярным решениям нагрузочного тестирования "противопоставляется" проект GeekLoad, это ни в коем случае не означает его преимущество по фичам на данный момент и т.д. Более того, эти и другие инструменты послужили источником вдохновения и идей.

Пожалуйста, воспринимайте повествование с позиции сравнения подходов.

И.. критикуйте! Цель статьи: собрать конструктивную критику, чтобы стать лучше.

Эпизод первый: Установка

Установки не избежать, несмотря на k8s и прочие амазоны. Ибо отладка и исследование проблем иногда случаются с нами.

Один из представителей инструментария для нагрузочного тестирования - k6 с блеском справляется с первым заданием: здесь тебе и инсталляторы под разные ОС, пакеты для различных пакетных менеджеров, docker образ и облачное решение различной степени платности, включая бесплатное. Молодцы.

Теперь посмотрим на популярное решение Apache JMeter: заходим на сайт и скачиваем... архив. 2023 год на дворе. ИИ вот-вот захватит мир и вообще... Вы серьезно?

Ну ладно, может им действительно не нужен инсталлятор в том или ином виде. Пробуем найти, что запускать: apache-jmeter-5.5\bin\jmeter.bat

Not able to find Java executable or version. Please check your Java installation.
errorlevel=2
Для продолжения нажмите любую клавишу . . .

Вот здорово! Это моя любимая тема: чтобы просто запустить, нужно что-то поставить\настроить (Java в данном случае). Установщик продукта (как в k6 например) выполнил бы все необходимые приготовления автоматически.

"Без проблем" скажете вы? Нет!

Какая версия\вендор явы нужна для корректной работы и откуда ее качать?

Почему пользователь должен об этом думать?

Официального образа на docker hub тоже не удалось найти. Грустно.

Ну... ок, скачали и поставили какую то яву. Запускаем:

Консольное окно - аппендикс к основному GUI окну приложения JMeter
Консольное окно - аппендикс к основному GUI окну приложения JMeter

Ох...

  • В чем проблема тестов из GUI? Что бы еще щепоку граблей юзеру подкинуть? На реально слабых машинах Load в принципе запускать грешно.

  • Нам предлагают настроить Java VM, вместо поставки пакетного файла (или аналога) с нужными настройками? Я где то упустил, что JMeter это набор "сделай сам"?

  • Зачем вообще это висящее как пятое колесо окно рядом?!

Gatling (как и многие другие) тоже страдает подобной проблемой: "А давайте, свалим часть работы на юзера!".

Хотя, казалось бы, даже если нет сил\желания на полноценный установщик, кто мешает реализовать готовую к использованию систему, например, на docker-compose, как это сделано в нашем проекте GeekLoad?

Gatling Enterprise, судя по документации и рекламным видео, предлагает интересный функционал, в том числе касающийся установки в виде docker compose.

Но о чем думают его разработчики, если только для того, чтобы прикоснуться к волшебному миру платных фич, нужно обращаться в саппорт, договариваться о звонке и т.д.? Вероятно их устраивают только клиенты, делающие выбор только на основе рекламы.

Уверен, множество людей, кто бы полюбил и купил платную версию, не сделают этого, ввиду других альтернатив, которые проще попробовать, просто скачав триал без вопросов.

Продолжая тему заботливого рассовывания палок в колеса, CLI gatling'а не предлагает способа простого запуска скрипта сохраненного в файле из командной строки без запросов к пользователю в разделе Quickstart | Running Gatling:

Пруф
Только с участием юзера. Взято здесь.
Только с участием юзера. Взято здесь.

Это было бы слишком просто. Но, все же способ решения этого крайне простого кейса, нашелся после детального изучения документации, в разделе Zip Bundle Command Line Options:

gatling.bat -s MySimulation -rm local -bf d:\Test\gatling -sf d:\Test\gatling

Когда ожидалось подобное этому (как в k6 или GeekLoad) :

gatling.bat -s d:\Test\gatling\MySimulation.scala

Эпизод второй: Hello world!

С чего начинается освоение продукта? С простых кейсов, которые чаще всего и бывают в нашей практике. Да, знаю - почти всегда они вырастают до небес, но позже.

Попробуем "скормить" финалисту предыдущего эпизода k6, скрипт с единственным запросом:

import http from 'k6/http';

export default function () {
  http.get('https://www.google.ru');
}

Не заметили "криминала"? Да, для систем разработки общего назначения, все нормально. Но учитывая то, что мы используем специализированную утилиту, первая строка является избыточной.

Уверен, что встроенный функционал может и должен быть инжектирован в пространство скрипта прозрачно.

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

Ничего не смущает?
Ничего не смущает?

Обилие одинаковых метрик в частности и значений в общем, наверное, должно внушить уважение к мощи продукта. Но, учитывая простую задачу, это только усложняет анализ результатов.

Ошибки, итерации и тайминги слились в кучу, что явно не способствует простоте анализа.

Iteration_duration меньше суммы компонентов, отображенных выше. Попробуйте с ходу разобраться что есть что.

Http_req_duration наоборот, отображает сумму элементов расположенных ниже. Больше разных подходов в одном отчете! Чтобы жизнь медом простой не казалась!


Вот реализация аналогичного скрипта для GeekLoad:

function main() {
  http('https://www.google.ru').get().sync();
}

Без шаблонного кода. Но import никто не запрещал, если нужно (еще бы, после этой статьи).

Здесь метод sync() в конце вызова, осуществляет синхронный вызов запроса. Его антипод - async() - асинхронный вызов, которого в k6 и многих других аналогах просто нет.

Попробуем запустить скрипт:

Просто
Просто

Простой скрипт = простое summary, а для вдумчивого анализа, существуют специальные отчеты. Они есть у всех описанных утилит в том или ином виде.

Хотя нет, пожалуй не хватает чего то.... поделитесь в комментах, чего именно на ваш взгляд?


JMeter - предлагает визуальный редактор теста:

Здесь максимально полный эквивалент скриптов для k6 и GeekLoad
Здесь максимально полный эквивалент скриптов для k6 и GeekLoad

Догадайтесь, что покажет JMeter после выполнения теста? Ничего! Абсолютно.

При этом, summary все же есть, но JMeter не утруждает себя помощью человеку, начинающему освоение инструмента. А остальных заставляет добавлять в каждый тест элемент Listener|Summary report:

Добавляли summary теста, а получили summary проекта по всем его запускам...
Добавляли summary теста, а получили summary проекта по всем его запускам...

Чтобы увидеть после выполнения теста картинку, показанную выше, нужно обязательно выбрать элемент "Summary report". JMeter по-прежнему отказывается показывать какой-либо отчет автоматически. Не царское это дело, вероятно...

Заметили цифру 2 в колонке Samples и разные значения Min и Max? Напомню: тест с 1 запросом, без виртуальных пользователей и прочих мультипликаторов. А судя по summary - операций было 2. Оказалось, виной тому две мои попытки запустить тест.

В Apache своя логика: они решили, что summary нам нужен накопительный - по всем запускам теста. Либо очищать лог ручками после каждого запуска, теряя предыдущие результаты... Ну а что, удобно!


От рафинированного Hello World, перейдем к чуть более полезному примеру с двумя последовательными запросами к одному серверу:

Gatling:

import io.gatling.core.Predef._
import io.gatling.http.Predef._

class MySimulation extends Simulation {
  val scn = scenario("My Scenario")
    .exec(http("Request 1")
      .get("/"))
    .exec(http("Request 2")
      .get("/search?q=test"))

  setUp(
    scn.inject(atOnceUsers(1))
  ).protocols(http.baseUrl("https://www.google.ru"))
}

"Простой и выразительный DSL!" - говорили они.

"Простое должно быть сложным!" - вторило эхо.

800&1200
800&1200

Итак, мы выполнили сценарий с двумя запросами. Помог ли нам Gatling выяснить какой из них самый медленный? Зато мы знаем, среднюю длительность и процентили от всех запросов!

Да, есть другие варианты анализа (html отчет с графиками), но задача простая, хватило бы адекватного summary!

При первом знакомстве, особенно понравилось про 800 и 1200. Повеяло загадкой и магией. Но оказалось, это некие граничные значения длительности запросов, заданные в файле конфигурации Gatling.conf.


K6:

import http from 'k6/http';

export default function () {
  const server = 'https://www.google.ru';
  
  http.get(server);
  http.get(`${server}/search?q=test`);
}

Не плохо. Но чего-то не хватает. Может chained calls?

Больше магии!
Больше магии!

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


JMeter:

Хотя и визуально, но в целом как в k6, т.к. нужно указывать адрес сервера в каждом запросе.
Хотя и визуально, но в целом как в k6, т.к. нужно указывать адрес сервера в каждом запросе.
Средняя температура по больнице всем запросам
Средняя температура по больнице всем запросам

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

Издеваются.


GeekLoad:

function main() {
    http('https://www.google.ru')
        .get()
        .get('search?q=test')
        .sync();
}

На ум приходит только слоган Nike: Just Do It!

Два запроса - два результата. Поведение по умолчанию.
Два запроса - два результата. Поведение по умолчанию.

Имена операций (запросов) по умолчанию разные. Можно изменить, в т.ч. сделать одинаковыми.

Эпизод основной: Load это про нагрузку

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

В качестве задачи возьмем 3 группы виртуальных пользователей работающих параллельно, две из которых параметризованы уникальными для каждого пользователя (не итерации!) авторизационными данными. Каждая группа выполняет свой сценарий. Профиль нагрузки константный. Агент только один - встроенный локальный.

Не особо замороченный тест. Мы же про простые кейсы?

Ниже приведены скрипты и summary для четырех испытуемых. Оцените сами, насколько каждый из них упрощает понимание созданного теста, и как следствие, эффективность его контроля и модификации.

Gatling:

К сожалению, не удалось найти штатного способа (feed) гарантирующего получение уникального значения для каждого виртуального пользователя.

Не удалась также попытка создания велосипеда на основе session.userId, т.к. по логике Gatling, id юзера на самом деле является номером итерации юзера. Т.е. если юзеров 10 и все они повторились 50 раз, то userId принимает значения 1..500, вместо 1..10. А главное, не то как называется это значение, а то, что нет альтернативы с диапазоном 1..10.

Вследствие этого, была произведена неполноценная замена на feed с последовательным закольцованным получением элементов.

Скрипт
import io.gatling.core.Predef._
import io.gatling.http.Predef._

class MySimulation extends Simulation {
  val users = Array("Anna", "Peter", "Bill", "Sonya", "Katrin", "Jon")

  val login = users.map(name => Map("login" -> name)).circular
  val password = users.map(name => Map("password" -> name)).circular
  
  val basic = scenario("basic")
    .feed(login)
	.feed(password)
    .exec(http("Basic Auth")
          .get("/auth/basic")
	      .basicAuth("#{login}", "#{password}")
	)
  
  val bearer = scenario("bearer")
    .feed(login)
	.feed(password)
    .exec(http("JWT Login")
          .post("/auth/jwt/login")
          .body(StringBody("""{ "name": "#{login}", "password": "#{password}" }"""))
		  .asJson
	      .check(jsonPath("$.token").saveAs("tokenValue"))
		)
    .exec(http("JWT Auth")
        .get("/auth/jwt")
        .header("Authorization", "Bearer #{tokenValue}"))
  
  val unAuthorize = scenario("unAuthorize")    
    .exec(http("Unauthorize")
          .get("/auth/unauthorized"))

  val profile = constantConcurrentUsers(3).during(5)
  
  setUp(
    basic.inject(profile),
    bearer.inject(profile),
    unAuthorize.inject(profile)
  ).protocols(http.baseUrl("http://localhost"))
}

Пример отображения сообщения о синтаксической ошибке
Не хватает только полного текста библии
Не хватает только полного текста библии

Summary
Отдельные тайминги по реквестам и сценариям? Нет, не слышали.
Отдельные тайминги по реквестам и сценариям? Нет, не слышали.

Несмотря на то, что это не функциональное тестирование, основное внимание уделено количественным метрикам успешно\не успешно вместо таймингов.

В процессе наткнулся на фичу, которая выглядит как баг: каждые 5 секунд выводится summary от этих 5 секунд, но не поверх предыдущего текста, а снизу. В результате для короткого теста просто кажется, что часть отчета продублирована:

Так действительно удобнее и проще?
Так действительно удобнее и проще?

Что интересно, в финальном Summary детализация по сценариям совсем отсутствует, хотя в "прогрессе" есть.

K6:

Скрипт
import http from 'k6/http';

export let options = {
  scenarios: {
    basic: {
      executor: 'constant-vus',
      exec: 'basic',
      vus: 3,
      duration: '5s'
    },
    bearer: {
      executor: 'constant-vus',
      exec: 'bearer',
      vus: 3,
      duration: '5s'
    },
    unAuthorize: {
      executor: 'constant-vus',
      exec: 'unAuthorize',
      vus: 3,
      duration: '5s'
    }
  }
};

const demoServer = 'http://localhost';
const users = ['Anna', 'Peter', 'Bill', 'Sonya', 'Katrin', 'Jon'];

export function basic() {
  const login = users[__VU - 1];
  const password = users[__VU - 1];
  
  http.get(`${demoServer}/auth/basic`, {
    auth: {
      username: login,
      password: password
    }
  });
}

export function bearer() {
  const login = users[__VU - 1];
  const password = users[__VU - 1];
  
  let response = http.post(`${demoServer}/auth/jwt/login`, {
    name: login,
    password: password,
  });

  http.get(`${demoServer}/auth/jwt`, {
    headers: {
      Authorization: `Bearer ${response.json('token')}`
    }
  });
}

export function unAuthorize() {
  http.get(`${demoServer}/auth/unauthorized`);
}

Пример отображения сообщения о синтаксической ошибке
Больше, еще больше текста!
Больше, еще больше текста!

То, что при нагрузочном тестировании может быть большое количество однотипных сообщений или прочих элементов не сюрприз. Но так "в лоб" подходить к логированию, когда даже синтаксические ошибки отображаются на каждой итерации vu, это печаль. Про ревью сгруппированного списка ошибок в summary речи даже не идет.

Summary
Дальше робкого упоминания сценариев дело не пошло...
Дальше робкого упоминания сценариев дело не пошло...

JMeter:

Визуальное дерево проекта
Визуальное дерево сценария
Визуальное дерево сценария

Визуальное дерево в реальности не всегда достаточно наглядно описывает сценарий. Отображаются свойства только выбранного элемента, в отличие от скрипта. Как минимум, для формата статьи - минус. Просто факт.

Идеальным представляется дуализм представления проекта скрипт + визуальное дерево. Хотябы с частично двунаправленным редактированием. Но, к сожалению, во всех описываемых инструментах такой подход не реализован. Возможно что то изменится в будущем.

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

JMeter по какой то причине огранивает юзера в выборе способа хранения тестовых значений только CSV файлом. Сохранить значения в самом проекте не удалось. Для простых кейсов это было бы проще.

Summary
Возможность раздельных результатов по реквестам существует!
Возможность раздельных результатов по реквестам существует!

Метрик по группам здесь тоже нет, но есть по реквестам. Если переименовать элементы проекта имеющие по умолчанию одинаковые стандартные имена.

GeekLoad:

Скрипт
function main() {
    DataSource.from(['Anna', 'Peter', 'Bill', 'Sonya', 'Katrin', 'Jon'])
        .byUser('login')
        .byUser('password');

    Stage.run({
        title: 'Auth test',
        users: 9,
        profile: '5s',
        groups: [basic, bearer, unAuthorize]
    });
}

function basic() {
    http(demoServer)
        .get('auth/basic')
        .auth(Auth.basic(), login(), password())
        .sync();
}

function bearer() {
    http(demoServer)
        .post('auth/jwt/login')
        .body({name: login(), password: password()})
        .then(xPath('token').store('tokenValue'))
        .get('auth/jwt')
        .auth(Auth.bearer(), Session.tokenValue)
        .sync();
}

function unAuthorize() {
    http(demoServer)
        .get('auth/unauthorized')
        .sync();
}

Пример отображения сообщения о синтаксической ошибке
Просто ошибка. Синтаксическая.
Просто ошибка. Синтаксическая.

Summary
Результаты выполнения одного Stage. Но бывает более одного.
Результаты выполнения одного Stage. Но бывает более одного.

Группировка по сценариям, раздельные тайминги, ошибки, сгруппированные сообщения. Чтобы было просто понять, что есть что.

Эпизод не простой: Сложное должно быть возможным

Удобный инструмент простые задачи должен делать максимально простыми. Но это не значит, что сложные ему должны быть противопоказаны.

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

Рассмотрим комплексный пример:

  • Тест из двух последовательных этапов.

  • Каждый этап из двух параллельных групп.

  • Каждая группа имеет некий неконстантный профиль нагрузки.

  • Каждая группа симулируется на автоматически разворачиваемых агентах, расположенных в разных локациях с указанием процента распределения VU.

  • Так как тест большой, сценарии сохранены в отдельном файле.

  • В тесте указано общее целевое количество VU от которого через процент задаются значения для всех групп, что позволит крайне просто масштабировать тест изменяя только одно значение.

k6 и JMeter посчитали функционал этапов избыточным. Просто создайте нужное количество тестов, запустите их последовательно чем либо, а затем результаты объедините в один отчет. Элементарно же.

Gatling здесь выступил гораздо лучше: есть функционал метода andThen, который очень гибко позволяет комбинировать выполнение сценариев.

Gatling, k6 и JMeter предлагают функционал распределенного тестирования. В облачной версии или с ручным запуском агентов, и т.д.

Но нет прозрачного интегрированного подхода, когда агенты изначально являются такими же сущностями проекта, как группы и ими также можно управлять, а не просто запускать на них часть теста.

Gatling, k6 и JMeter так или иначе отлично умеют в профиль нагрузки, но в силу отсутствующего функционала агентов, распределением юзеров по локациям управляйте как нибудь сами. Так как это нужно не всем, значит не нужно никому.

Итого, с учетом встреченных ограничений, в Gatling получился следующий скрипт:

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import MyScenarios._

class Stages extends Simulation {
  // Здесь могла бы быть настройка агентов (инжекторов), но даже в Gatling Ent, 
  // это конфигурируется вне скрипта - только в WebUI.
  
  val setup = scenario("setup") // Сценарий - заглушка, лучшего решения не нашлось.
    .feed(login)

  setUp(
    setup.inject(atOnceUsers(0)) // Сценарий с нулевой нагрузкой, нужен для andThen.
      // andThen - только логическая конструкция, именования группы сценариев 
      // она не дает. Придется добавлять группу в тело каждого сценария.
      .andThen(firstScenario.inject(constantConcurrentUsers(150).during(60)),
               secondScenario.inject(
                 rampConcurrentUsers(0).to(150).during(25),
                 atOnceUsers(150).during(10),
                 rampConcurrentUsers(150).to(0).during(25)
                 // Здесь могла быть настройка распределение юзеров по локациям
                 // Но, похоже, это не реализуемо в скрипте, только в облаке.
               ))

      .andThen(
	           // Здесь могут быть любые ценарии, кроме тех, что уже описаны выше.
               // Gatling запрещает повторы в рамках одного теста. 
              )
  ).protocols(http.baseUrl("http://localhost"))
}

В GeekLoad, есть возможность произвольной последовательной комбинации Stages, Group и одиночных реквестов в одном проекте. Но в данном случае просто два этапа:

import {firstScenario, secondScenario} from './Scearios.gl-js';

function main() {
  config = {
    test : {
      // Целевое количество VU, от которого могут вычисляться проценты для профилей
      users: 1000
    }
  };

  // Два облака, в которых на время тестов, поднимется нужно количество агентов
  let usa = Cloud.amazon({
    name: 'Usa',
    key : AmazonKey,
    secret : AmazonSecret,
    image : 'geekload-agent',
    region: 'us-west-1',
    limit: 1,
    capacity: 500
  });

  let europe = Cloud.amazon({
    name: 'Europe',
    key : AmazonKey,
    secret : AmazonSecret,
    image : 'geekload-agent',
    region: 'eu-west-3',
    limit: 2,
    capacity: 500
  });

  // Все конструкции выполняются последовательно, кроме групп внутри этапов (Stages)
  Stage.run({
    title : 'Usual activity',
    users : '30%',
    groups: [{
              scenario : firstScenario,
              profile : '1m',
              // Распределяем всех пользователей по локациям
              distribution : [
                              {location: usa, target : '20%'},
                              {location: europe, target : '30%'}
                             ]
             }, 
             {
              scenario : secondScenario,
              // Нагрузка растет по S-образной кривой от 0 до 500 vu за 25 сек.,
              // затем фиксированна на 10 сек
              // затем линейно убывает до 0 за 25 сек.
              profile : [
                {target: '50%', duration: '25s', shape: Shape.smooth},
                '10s',
                {target: '0', duration: '25s'}
              ],

              distribution : [
                {location: usa, target : '10%'},
                {location: europe, target : '40%'}
              ]
             }]
  });
  
  Stage.run({
    title : 'Black Friday',
    users : '100%',
    ...
  });
}

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

Вообще есть еще проверки, SLA и т.д. а также тот факт, что GeekLoad не имеет пока такого багажа фич, как у уважаемых конкурентов. Но суть статьи не в этом.

Разумеется, все описанные выше проблемы так или иначе решаются. Подходящую JDK можно найти и поставить, данные экспортировать и проанализировать в той же Grafana, к любому синтаксису загуглив, привыкнуть и т.д.

А еще можно сходить на форумы за "костылями".

Но простое должно быть простым, а не просто возможным. Уверен, это удел сложного.

Итак, в чем видится проблема?

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

Когда проблема с которой разобрался, не считается проблемой.

Когда лишние повторяющиеся действия или фрагменты кода считаются нормой.

Когда отсутствие нужной функциональности или сумбурная куча информации вместо summary, оправдывается происхождением продукта.

Когда, трудности поиска простой фичи в дебрях документации, обосновываются низкими когнитивными способностями пользователя.

Привычка? Попробуем докопаться до сути в следующей статье цикла ;)

Не переключайтесь!

Комментарии (10)


  1. artschedrov
    15.07.2023 09:07
    +2

    Теперь посмотрим на популярное решение Apache JMeter: заходим на сайт и скачиваем... архив. 2023 год на дворе. 

    Вот здорово! Это моя любимая тема: чтобы просто запустить, нужно что-то поставить\настроить (Java в данном случае).

    Какая версия\вендор явы нужна для корректной работы и откуда ее качать?

    Уж полно вам высасывать из пальца, господа)


    1. old-school-geek Автор
      15.07.2023 09:07
      -1

      Отчасти с вами согласен.

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

      А теперь оценим ситуацию: на одной чаше весов - несколько физических разработчиков поленившихся умеренными усилиями что-то допилить, а на другой - множество пользователей, испытавших маленькое неудобство от этого.

      Думаю, что перевес однозначно на стороне пользователей.


  1. glebovgin
    15.07.2023 09:07

    Не рассматривали Locust?


    1. old-school-geek Автор
      15.07.2023 09:07

      Подробно его не рассматривал, но после беглого знакомства, он показался немного похожим на k6. Рискую ошибиться, но похоже синтаксис несколько избыточен.

      Похоже, есть докер образ, значит можно просто взять и запустить. Вопросов нет, молодцы. Но почему в топике про инсталляцию этого варианта нет - загадка. Чтобы не было слишком просто? Хотя это опять про пальцы :)

      Они рекламируют "Миллионы юзеров" на главной странице. Но в справке тут же сокрушаются про ограничения питона на использование ядер. Что заставляет вас запускать несколько процессов и т.д. Лукавство детектед.

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

      Остальное нужно изучать подробнее. К сожалению, пока нет возможности этим заняться.


      1. gigimon
        15.07.2023 09:07

        Locust сильно проще k6, но сценарии пишутся на чистом Python, что очень хорошо, когда вам надо нагрузить чуть сложнее, чем десяток GET запросов на сайте.

        У locust неплохой real time интерфейс (ui), графики реалтаймные и т.п. По поводу миллиона запросов, он отлично скейлится по серверам, просто запускаете воркеры 1 командой и все. Я запускал его на 64 ядрах (8 серверов по 8 ядер)

        Запихнуть в k6 дополнительные либы, то еще приключение


        1. old-school-geek Автор
          15.07.2023 09:07

          Если не затруднит, приведите пример раскрывающий простоту locust: скрипт на locust vs скрипт на k6.


          1. gigimon
            15.07.2023 09:07

            в k6 скрипт пишется почти на javascript, но нет уверенности что любая библиотека заведется (там свой движок js) + подключение ее не простое дело.

            locust - обычная python библиотека, куда просто поставил любой пакет и используешь.

            Шире не раскрою, с k6 мало опыта


            1. old-school-geek Автор
              15.07.2023 09:07

              Не уверен, что подключение чего-то со стороны всегда хорошо для LT.

              То что входит в сам инструмент - хоть как то проверяется на адекватность сгенерированных метрик\отчетов и т.д. Чего нельзя сказать о произвольных либах со стороны, как бы удобны они не были. Взять как минимум пулы коннекшенов в подключаемых либах. Что о них знает локуст или любой другой инструмент? И, как результат, как можно корректно учитывать неизвестное поведение библиотек в отчетах?

              Все же LT это не "обычная библиотека". Это измерительный инструмент.

              Чего не хватает из штатного, что понадобилось подключать?


              1. gigimon
                15.07.2023 09:07

                Нагрузочное тестирование бывает не только для http :)

                Мне из практики надо было:

                1. нагружать amqp

                2. нагружать базы данных

                3. библиотека криптографические, для тестирования блокчейнов

                В locust для выведения отчетов можно передавать данные и руками, как хотите, у него для этого эвенты есть.


                1. old-school-geek Автор
                  15.07.2023 09:07

                  Понятно, спасибо, что поделились опытом!