Диплом: Разработка асинхронного приложения для передачи информации о подключениях к почтовым серверам на примере ООО "Интермедия"

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам
57
Каждый обработчик имеет при себе все необходимые структуры для
обработки поступившего сообщения и запускается в отдельном легковес-
ном потоке. Модули обработчика представлены на Рисунке 2.3
Рисунок 2.3 – Внутреннее представление обработчика
Используя нативные способы синхронизации между различными
потоками удалось построить систему, где практически отсутствует борьба
за общие ресурсы. А алгоритм обработки сообщения идеально маштабиру-
ется. Полученные лог-сообщения поступают в единую очередь обработки
сообщений, где с другой стороны его ожидает очередь из выстроившихся
обработчиков. Обработчик получив сообщение покидает очередь, а его
место занимает новый, свободный, или освобдившийся обработчик.
Алгоритм обработки сообщения представляет из себя несколько по-
следовательных шагов Рисунок 2.4.
58
Рисунок 2.4 – Алгоритм обработки сообщения
Фильтрация делит лог-сообщения на три группы:
а) Группа Discard - сообщения не содержащие никакой ценной инфор-
мации.
б) Группа TLS - сообщения содержащие информацию о защищённом
соединении.
в) Группа Data - сообщения содержащее необходимы данные.
Сообщение из группы Discard отбрасываются. Сообщения из группы
TLS и Data поступают в Parser-сообщений, где происходит разбор лог-
сообщения с целью выделить первоначально необходимую информацию:
– Дата и время поступления сообщения;
– DNS Имя сервера на котором происходит обработка сообщения;
– Pid - процесс сервера обрабатывающий поступившее сообщение;
Из сообщений группы TLS так же выделяется информация о версии
TLS, после чего все полученные данные передаются в Aggregator.
59
Из сообщений группы Data выделяются все необходимые данные и
формируются в структуру Message, где частью формирования структуры
является запрос в Aggregator с целью получить информацию о версии TLS,
чтобы добавить её к сообщению.
Полученное сообщение передаётся в модуль Validators, где прове-
ряются его поля, например такие как, локальный IP-адрес. Некорректные
данные отбрасываются.
Корректные сообщения передаются в
Constructor
, где преобразуют-
ся в нужный формат для отправки. Полученные данные в формате байтов
передаются в модуль Sender, где происходит их отправка партнёру. В
завершении Worker очищает своё внутреннее состояние и возвращается
обратно в очередь.
60
2.3.2 Структурная система пакета (древо вызова программных мо-
дулей)
Итоговое решение имеет следующую структуру:
project
Feed
conf
inputs
message
app.go
listener.go
output.go
sender.go
validators.go
worker.go
main.go
Более детально структура проекта отображена в приложении 3.2
В модуле main.go считываются аргументы при вызове и пере-
менные окружения. После чего происходит запуск программы и вспомо-
гательных сервисов. Основная инициализация требуемых ресурсов про-
исходит в Feed/app.go. Здесь создаются и контролируются все мо-
дули, так же здесь создаётся пул подготовленных обработчиков. После
того, как ресурсы подготовлены, App запускает Listener из модуля
Feed/listener.go. Поступающие сообщения от Listener парал-
лельно обрабатываются воркерами.
61
При необходимости прекращения работы, главный модуль main.go
перехватывает сигналы ОС (SIGTERM/SIGKILL) и вызывает у App метод
Close. После чего приложение перестаёт принимать новые сообщения,
ждёт пока закончится обработка принятых ранее сообщений и завершает
работу.
Данный паттерн называется graceful shutdown.
2.3.3 Описание программных модулей
Главный модуль программы Feed состоит из подмодулей:
– conf — Содержит структуры конфигурации для App;
– inputs — Содержит структуры и функции для обработки входящих
сообщений. Здесь находится Парсер и Агрегатор;
– message — Структура внутреннего представления сообщения и
функции работы с ним;
– app.go — Сервисный код приложения занимающийся запуском и
завершением работы;
– listener.go — Структура Listener и код для принятия сообщение
по TCP/UPD в зависимости от конфига
– output.go — Структуры и код, занимающиеся преобразованием из
промежуточного представления сообщения в сообщение для отправ-
ки партнёру;
– sender.go — Структуры и код для отправки сообщений. В зависи-
мости от когфига отправка происходить может по UDP, в файл или
/dev/null;
– validators.go — Код для проверки внутреннего представления сооб-
щения на требуемые условия. Например наличие IP адреса. Исполь-
зуется Обработчиками(Worker);
62
– worker.go — Структура и код для обработки входящего сообщения
от получения до отправки.
Для каждого модуля есть свой собственный набор юнит-тестов. Как
сказано в документации Golang[10], для добавления тестов необходимо
рядом с файлом исходного кода поместить файл с префиксом *_test.go.
Как видно в приложении 3.2, практически для каждого файла с исходным
кодом имеется его двойник с тестами. В среднем файлы с тестами на
25-50% больше по размеру, нежели чем файлы с исходным програмным
кодом. А некоторые больше в несколько раз.
Listing 5: Размеры файлов с исходным кодом и тестами
rwrwr−− 1 as as 1,2K app.go
rwrwr−− 1 as as 5,6K app_test.go
Это обосновывается тем, что тестового кода в соотношении к проект-
ному в разы больше. Но при компиляции исходного кода в исполняемый
модуль, тестовый код не включается и не расширяет размер выходного
файла.
Помимо юнит-тестов так же имеется набор интеграционных и на-
грузочных тестов. Для управления всем этим многообразием использует-
ся Docker-контейнер описанный в Dockerfile и скрипт управления в
docker−entrypoint.sh.
Для управления зависимостями искользуется Go Modules [19] позво-
ляющий при помощи файлов go.mod и go.sum зафиксировать все требу-
емые проекту зависимости по версии зависимости и git-hash конкретного
коммита в репозиториях пакетов на github.com.
63
2.4 Контрольный пример реализации проекта и его описание
Одно из ключевых функциональных требований — поддержка ре-
альной нагрузки, которая присутствует в боевой системе. Лучшей де-
монстрацией работы итоговой реализации будут предпусковое нагрузоч-
ное тестирование, как пример работы приложения при разных нагрузках,
включая ожидаемые и сверх нагрузки.
Требование по производительности заключалось в том, что итоговое
решение должно быть способно в реальном времени отравлять инфор-
мацию о всех поступающих электронных письмах на почтовые сервера.
По предварительным данным в пиках достигались значения в 1 миллион
электронных сообщений в час.
Существует два основных типа соединения — это прошедшие со-
единения, по которым электронное письмо в дальнейшем прошло через
инфраструктуру компании, и заблокированные, отфильтрованные чёрны-
ми списками партнёров. Как раньше было установленно, количество за-
блокированных входящих запросов в среднем составляет 60% от обще-
го количества входящих соединений. Соответственно проектная нагрузка
составляла 2.5 миллионов электронных сообщений в час и примерно 700
электронных сообщений в секунду.
Представленные цифры описывают сколько соединений устанавли-
вается на почтовых серверах, но не сколько с почтовых серверов будет
отправлено Log-сообщений. На каждое входящее не отфильтрованное со-
единение генерируется три Log-сообщения, а на каждое заблокированное
— два. Таким образом мы получаем, что в пиках нагрузка в виде Log-
сообщений от почтовых серверов будет составлять:
???? ???????????????????????????????????? ???????????????????????????????? = 3 × ???? ???????????????????????????????????????????????????????????????? + 2 × ????????????????????????????????????????????????????????????????????????????
(2.1)
64
Где колличество прошедших и отфильтрованных электронных
сообщений в секунду представляется в виде (2.2), a общее
количество соединений в час можно выразить из прошедших
соединений (2.3). Тогда подставив в уравнение (2.1) правую часть
???? ???????????????????????????????????????????????????????????????? и ???????????????????????????????????????????????????????????????????????????? из (2.2) и расчитанное
значение ???????????????????????????????????????????????????????????? ???????????????????????? из (2.3) – получим примерное
ожидаемое значение колличества входящих log-сообщений в секунду
(2.4) равное 1667. Для простоты сравнения округлим в большую сторону
до 1700 log-сообщений в секунду.
???? ???????????????????????????????????????????????????????????????? =
(???????????????????????????????????????????????????????????? ???????????????????????? × 0.4)
????????????????????????????????????????????????????
???????????????????????????????????????????????????????????????????????????? =
(???????????????????????????????????????????????????????????? ???????????????????????? × 0.6)
????????????????????????????????????????????????????
(2.2)
???????????????????????????????????????????????????????????? ???????????????????????? =
???? ???????????????????????????????????????????????????????????????? ????????????????????????
40%
× 100%
=
1????6
40
× 100
= 2500000.0 (2.3)
???? ???????????????????????????????????? ???????????????????????????????? = 3 ×
2.5????6 × 0.4
3600
+ 2 ×
2.5????6 × 0.6
3600
= 833.3 + 833.3
= 1667 (2.4)
Нагрузочное тестирование проводилось в условиях приближенных к
тем, что будут в реальной системе. Использовались данные собранные за
последний месяц, порядка 80Gb архивированных лог-данных. И специаль-
но подготовленный тестовый стенд с характеристиками соответствующие
тем, что будут при внедрении.
65
Характеристики тестовой машины:
– 1 * CPU 2.8 GHZ
– 1Gb Mem
Нагрузочное тестирование производилось по следующему алгорит-
му — всего было выбрано 7 шагов по часу на каждый шаг:
– 10ms = 100 msg/s
– 1ms = 1000 msg/s
– 300us = 3000 msg/s
– 50us = 5k msg/s
– 1us = 10k msg/s
– 0 = 100k msg/s
Где первое число означает задержку перед отправка Log-сообщения, а
второе отправленно количество сообщений в секунду. Как видим, на-
ше расчитанное среднее число log-сообщений в секунду 1700 находит-
ся между вторым и третьим шагом. Поэтому минимально приемлимым,
удовлетворительным, будет считаться 100% прохождение второго шага
и 60% прохождение третьего. Что означает бессбойную обработку 1800
сообщений в секунду на 100% времени CPU.
В противном случае результат будет считаться неудовлетворитель-
ным.
После проведения нагрузочного тестирования получены следующие
результаты.
– Для обработки 1000 сообщений в секунду требуется менее 10%
времени работы CPU и 19.2 мега-байт оперативной памяти.
– Для обработки 3000 сообщений в секунду требуется 30% времени
работы CPU и 19.2 мега-байт оперативной памяти Рис.2.5 и Рис.2.6.
– Для обработки 10 тысяч сообщений в секунду требуется менее 80%
времени работы CPU и 19.2 мега-байт оперативной памяти.
66
Максимальная нагрузка, которую может обработать приложение
в описанной конфигурации железа составляет порядка 30 тысяч log-
сообщений в секунду. (Или 12к входящих email в секунду) Для этого
требуется все 100% времени работы CPU и 21.4 мега-байта оперативной
памяти Рис.2.7 и Рис.2.8.
Ниже представлено несколько графиков нагрузочного тестирования.
Рисунок 2.5 – График CPU при трёх тысячах log-сообщений в секунду
Рисунок 2.6 – График ОЗУ при трёх тысячах log-сообщений в секунду
Рисунок 2.7 – График CPU при ста тысячах log-сообщений в секунду

Смотрите также:

"Автоматизация обработки заявок ООО "Проектно-Строительная Компания"
"Автоматизация процесса аттестации персонала для ООО "Нэт Бай Нэт Холдинг"
"Анализ интернет-активности конкурентов ( на примере конкурентов "Газпром нефть")
"Бухгалтерский учёт и аудит расчётов с подотчётними лицами в организации на примере ООО "ЛОЦ 10""
«Психологическое сопровождение персонала в организации на примере ООО «Крокус»
Cовершенствование деловой оценки персонала в организации (на примере ООО "Даймонд кейтеринг развитие")
PR как средство продвижения организации (на примере ПАО "Тамбовский завод "Комсомолец им. Н.С. Артемова")
PR-коммуникации в сфере общественного питания (на примере кафе-кондитерской «Cream Cheese»)
SMM как средство повышения эффективности работы учреждений социокультурной сферы (на примере Малого театра)
Value-based education: ценности в системе образования и способы их реализации на уроке английского языка. Опыт Европейских стран