goader — консольный бенчмарк с простой конфигурацией и поддержкой различных бэкендов для тестирования. Название происходит от go и loader, а также имеет свое значение на английском, "подгонять копьем, палкой"
На данный момент можно тестировать (аргумент -requests-engine):
- http (GET запросы либо GET+PUT)
- disk
- s3 (С авторизацией по ACCESS/SECRET keys, endpoint необходим, но это дает возможность проверять private s3, signature ver4 на данный момент не поддерживается, но планирую)
- null и sleep для тестирования самого бенчмарка
Уклон сделан на запись и считывание файлов, не страничек
Пример использования
goader -rps=300 -wps=150 -min-body-size=1 -max-body-size=128k --max-requests=1000 -requests-engine=disk -url=tmp/NN/RRRRR
![image](https://habrastorage.org/files/702/be5/4f1/702be54f18ff4bbca17c01895ba993b4.png)
Точки появляются в реальном времени в соответствии с каждым запросом, мне в свое время это позволило визуально выявить проблемы, в том случае, что цифры мало что дали бы. В случае ошибок на их месте будет E
Существует немало утилит для нагрузочного тестирования, но лично у меня к ним ряд претензий, что и сподвигло написать свой...
Проблема номер 1, что мы тестируем?
Упор на “кол-во параллельных тредов”, поиск максимальной нагрузки, максимального кол-ва тредов. Либо фиксированное кол-во тредов. Это конечно здорово, но лично у меня, в реальной жизни, при замене какого либо компонента системы достаточно редко возникал именно этот вопрос, сколько же оно потянет. При замене компонентов куда чаще вопроса два и они другие:
а) Отклик при заранее известной нагрузке. Как например 50 PUT/s, 300 GET/s. Проверяем время отклика на старой и новой системе. От замены компонентов кол-во пользователей не вырастет, цель как правило — улучшить отзывчивость системы.
goader -rps=300 -wps=50 -min-body-size=1 -max-body-size=128k -requests-engine=upload -url=http://localhost/files/user_NNNNN/file_RRRR
б) Мы все таки хотим дать больше, чем было, хотим знать максимум системы. Опять таки, что это такое? Кол-во клиентов которые сервер может выдержать? Кол-во параллельных клиентов которые получают Н-ый процент ошибок? Очень часто ошибок нет, а просто получаем огромное время отклика.
Поэтому для себя максимум системы я определил как “кол-во параллельных клиентов, при котором время отклика не превышает заданное значение".
goader -rpw 2 -max-latency 5ms -requests-engine=disk -url=tmp/RRRRRRR -body-size=4k -max-requests=30000
Нагрузка выравнивается по WRITE-ам (PUT/WriteFile), кол-во READ-ов установлено относительно WRITE-ов, т.е reads-per-write, чтений на запись — в примере 2, может быть дробным числом.
Кол-во тредов будет адаптироваться под задержки и на выходе получим число одновременных клиентов которые мы можем выдержать с данной загрузкой. Опционально максимум можно ограничить-увеличить аргументом -max-channels, по дефолту 32.
Традиционное “кол-во одновременных клиентов” так же существует, -wt=5 -rt=10 (5 тредов на запись, 10 на на чтение).
Это 2 режима, которых мне не хватало. Но была у проверенных мной бенчмарков еще проблема номер 2.
Сложность конфигурации
Дополнительным требованием, выставленным себе, было отсутствие UI и файлов конфигурации. Это конечно очень круто когда настроек миллион и возможности безграничны, но для этого нужна еще одна мощная машина, UI, пол дня на написание конфигурации и потом таскать эти файлы за собой. Безусловно, иногда это все таки плюс, мне было важно иметь возможность подключиться на любой из серверов и иметь возможность запустить, в ручную, по памяти тест системы. Либо послать сотрудникам в слеке короткое сообщение с командой, а дальше они все сделают сами. В крайнем случае подсмотрят в goader --help и опять таки доделают все сами.
Пока что, удается обходиться без файлов конфигурации, и я надеюсь так это и оставить.
Например, зачастую, список путей предоставляется отдельным файлом. Альтернатива: -url=http://127.0.0.1/user/NNNN/images/RRRRRRR.jpg
NNNN — будет заменено случайными числами
RRRRRRR — будет заменено случайными буквами
XXXXX — будет заменено последовательно увеличивающимися числами
Наглядность
Цифры цифрами, а порой глазами можно увидеть аномалии, которые сложно увидеть цифрами, не зная что искать. Каждый запрос отображается в консоли точкой(зеленая — чтение, синяя — запись), ошибка E, смена кол-ва тредов стрелкой вверх либо вниз.
Эта функция позволила найти нам проблемы в системе, так как мы смогли визуально увидеть, как просела производительность в определенный момент.
Помимо этого, конечный результат так же стремится быть лаконичным и информативным. Есть возможность заменить его на json, -output=json/human
Порой точки мешают, их можно отключить -show-progress=false
При большом кол-ве запросов, либо при удаленном исполнении, глазами бывает трудно увидеть прогресс, для этого есть экспериментальная функция создания html файла с визуальным отображением (-timeline-file=timeline.html
), когда запрос вышел и сколько времени он занял. Есть планы по улучшению, сменить отображение времени жизни запроса на вертикальное и тогда будет куда более наглядно, в какое время сколько запросов существовало. Но пока что это не приоритет.
Поддержка простых http запросов
Под простыми я подразумеваю только GET-запросы к страничками, без PUT-ов используя все вышеописанное. Это не было приоритетом, но использовать можно.
Запросов в секунду:
goader -rps=300 --max-requests=1000 -url=http://localhost/user/NN/product/RRRR
Кол-во одновременных клиентов:
goader -rt=32 --max-requests=1000 -url=http://localhost/user/NN/product/RRRR
Поиск максимального кол-ва одновременных клиентов с заданной максимальной задержкой:
goader -wt=0 -max-latency=300ms --max-requests=1000 -url=http://localhost/user/NN/product/RRRR
Лучше делать большее кол-во запросов в этом режиме, для более точных результатов.
К слову, это был мой первый опыт с go, хотелось на практике проверить восторженные отзывы, не могу сказать, что я их не поддерживаю. Да, есть свои недостатки, но в целом, быстрая компиляция, быстрая проверка ошибок, единая экосистема, простая система типов — все это позволяет как модно утверждать, сконцентрироваться на коде, а не особенностях экосистемы.
А то, что, без лишней магии на выходе получаются бинарники под все системы — вообще прелесть.
На гитхаб заливаю только linux/386 linux/amd64 windows/amd64 darwin/386 darwin/amd64, но если кому то необходимо расширить этот список — то без проблема. В рамках поддерживаемого самим golang-ом. Комментарии по поводу самого кода тоже приветствуются.
Скачать можно с Github либо собрать самим, лицензия MIT. Для удобства использования лучше положить в $PATH.
Комментарии (5)
Optik
05.11.2016 13:51+11) Чем не устроил ворох существующих инструментов?
2) Как у любого измерительного прибора нужны какие то гарантии по точности измерений.
3) Большие сомнения, что в комбайне учтены нюансы такого сложного мира как «диски».TigraSan
06.11.2016 14:59-11) Повторюсь о том что писал в посте, сложная конфигурация, UI конфигурация, зависимости итд. Мне было важно притащить один бинарник, который будет бежать на любой системе с параметрами которые легко запомнить, которые делают то что собственно и нужно.
2) Частично в следующем ответе…
3) requests-engine disk немного обманчиво. Правильней было бы назвать «path», но не вдаваясь в подробности disk все таки лаконичней. Это не specsfs либо fio, тут фиксированный сет операций необходимых для записи-чтения файла. А уж как, какая файловая система + ее бэкенд с этим справляется — это цифры и покажут. И сравнивая одним и тем же бенчмарком различные системы — цифры вполне можно сравнивать. Цель была проверять систему со стороны юзера, а не синтетический набор операций, который может быть одинаковым, но в разном порядке, на разных inode-ах, приводя к разным результатом, в зависимости от порядка. Так каждый раз яблоки сравниваются с яблоками. Единственное что раздумываю — добавить O_DIRECT. Все остальное — это уже не цель бенчмарка
A-Stahl
Go? Хм…