Это мой первый проект на Go, его смысл в том, чтобы потренироваться:
- Организовывать код проекта согласно чистой архитектуре
- Использовать каналы для синхронизации доступа к общим данным
- Использовать инъекцию зависимостей для обеспечения низкой связанности слоев
- Использовать модуль BurntSushi/toml для конфигурирования приложения из
.toml
файла- Путь к файлу можно передать с флагом
-config-path
при запуске исполняемого файла приложения
- Путь к файлу можно передать с флагом
- Использовать модуль stretchr/testify для модульного тестирования (unit-tests) функций-обработчиков HTTP сервера
- Проводить нагрузочное тестирование с помощью утилиты Apache JMeter
Проект представляет из себя REST API сервер, который реализует хранилище счетчиков. В терминологии Go, это map
'а, то есть набор из ключей (названий счетчиков) и их текущих значений.
Пользователям доступны следующие функции:
- Создание счетчика по запросу:
/set?name=<имя>&val=<число>
- Просмотр текущего состояния счетчика по запросу:
/get?name=<имя>
- Увеличение счетчика на 1 по запросу:
/inc?name=<имя>
- Уменьшение счетчика на 1 по запросу:
/dec?name=<имя>
Для обеспечения безопасного одновременного доступа обработчиков к данным можно использовать каналы или мьютексы. В данном проекте использовались каналы.
Обработчики запросов формируют команды и отправляют их в канал cmds
.
Горутина, работающая в фоновом режиме, считывает команды из канала cmds
и вызывает соответствующий UseCase
, который в свою очередь вызывает соответствующий метод хранилища счетчиков CounterStore
.
Метод хранилища счетчиков CounterStore
возвращает ответ, который проходит через UseCase
и попадает в горутину, которая отправляет его по каналу replyChan
, которым обладает каждая команда.
Обработчики считывают информацию из replyChan
и формируют ответ на запрос пользователя.
Данный алгоритм взаимодействия слоев соответствует идеологии чистой архитектуры:
HTTP > usecase
usecase > repository
usecase < repository
HTTP < usecase
$ curl "localhost:8080/set?name=a&val=19"
counter 'a' with val '19' was set
$ curl "localhost:8080/get?name=a"
'a': 19
$ curl "localhost:8080/inc?name=a"
ok, 'a': 20
$ curl "localhost:8080/get?name=a"
'a': 20
$ curl "localhost:8080/dec?name=a"
ok, 'a': 19
Для имитации множества одновременных подключений можно использовать JMeter (аналог ApacheBench) - программу для тестирования веб-сервера.
С помощью утилиты jmeter
создается файл load_test.jmx
, который содержит описание нагрузочного теста (Test Plan).
2000
- общее число запросов (по500
на каждый endpoint)50
- число запросов, отправляемых одновременно
При проведении тестирования утилита запускается в режиме non-gui:
jmeter -n -t test-file -l results-file -j log_file
-n
- запустить программу без графического интерфейса-t
-.jmx
файл с описанием теста (Test Plan)-l
-.jtl
файл, в который будут записаны результаты отправки каждого запроса-j
-.log
файл, в который будут записаны логи
Из файла с логами можно сгенерировать полный отчет (dashboard) результатов нагрузочного теста:
jmeter -g result.jtl -f -o report_dir
-o
- директория, в которую будет сводный отчет с графиками и таблицами- директория не должна существовать или должна быть пустой
-f
- удалить существующий отчет
Итого, используются следующие команды:
jmeter -n -t tests/jmeter/load_test.jmx -f -l tests/jmeter/result.jtl -j tests/jmeter/result.log
jmeter -g tests/jmeter/result.jtl -f -o tests/jmeter/report
Тест успешно пройден, сгенерированный отчет появится в директории tests/jmeter/report
в виде html-страницы:
Все команды, используемые в процессе разработки и тестирования, фиксировались в Makefile.