Initial commit
This commit is contained in:
@@ -1,12 +1,110 @@
|
||||
# Установка Go
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
wget https://go.dev/dl/go1.27.1.linux-amd64.tar.gz
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf go1.27.1.linux-amd64.tar.gz
|
||||
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
|
||||
source ~/.profile
|
||||
rm go1.27.1.linux-amd64.tar.gz
|
||||
go version
|
||||
```
|
||||
## Итоговое техническое описание проекта: Высоконагруженный STUN-сервер на Go
|
||||
Данный проект представляет собой сверхбыстрый, отказоустойчивый и оптимизированный
|
||||
под экстремальные нагрузки STUN-сервер (Session Traversal Utilities for NAT),
|
||||
написанный на языке Go (Golang). Сервер разработан в соответствии со стандартами
|
||||
RFC 5389 и RFC 8489 и предназначен для использования в инфраструктурах реального
|
||||
времени (WebRTC, VoIP, SIP, онлайн-игры) с целью определения внешних IP-адресов
|
||||
и портов клиентов, находящихся за NAT.
|
||||
Проект полностью контейнеризирован с помощью Docker и Docker Compose, а также
|
||||
защищен на уровне ядра ОС Linux, что позволяет ему обрабатывать тысячи запросов
|
||||
в секунду (RPS) на минимальных серверных мощностях.
|
||||
------------------------------
|
||||
## 🚀 Архитектурные особенности и ключевые фишки
|
||||
Архитектура проекта сфокусирована на достижении максимальной пропускной способности
|
||||
и минимального времени отклика (в тестах задержка составляет всего 20–30 мс):
|
||||
|
||||
1. Концепция True Zero-Alloc (Нулевое выделение памяти в куче):
|
||||
* Вместо аллокации нового буфера под каждый входящий UDP-пакет, каждый независимый
|
||||
* воркер создает фиксированный срез байт (buf := make([]byte, 1500)) единожды
|
||||
* перед запуском бесконечного цикла.
|
||||
* Ответ клиенту формируется в том же самом массиве данных поверх исходного
|
||||
запроса (buf = buf[:cap(buf)]).
|
||||
* Сборщик мусора Go (Garbage Collector) вообще не нагружается во время
|
||||
обработки сетевого флуда. Это исключает микропаузы (STW) сервера под нагрузкой.
|
||||
2. Использование современного пакета net/netip:
|
||||
* Взамен старого типа net.IP (который является срезом и всегда аллоцируется в куче),
|
||||
в коде применен пакет net/netip.
|
||||
* Объект netip.AddrPort хранит данные в виде легковесной структуры фиксированного
|
||||
размера, которая обрабатывается исключительно на уровне быстрого стека процессора.
|
||||
3. Многопоточный пул воркеров (Worker Pool):
|
||||
* Сервер автоматически определяет количество доступных логических ядер процессора
|
||||
(runtime.NumCPU()) и запускает строго эквивалентное количество горутин-воркеров.
|
||||
* Ядро Linux равномерно распределяет сетевые прерывания от UDP-сокета,
|
||||
утилизируя процессор на все 100%.
|
||||
4. Мягкое завершение работы (Graceful Shutdown):
|
||||
* Сервер перехватывает системные сигналы остановки от операционной системы
|
||||
или Docker-демона (SIGINT, SIGTERM).
|
||||
* При получении команды на выключение сокет закрывается, воркеры корректно
|
||||
дорабатывают текущую итерацию, а sync.WaitGroup гарантирует завершение процессов
|
||||
без потери обрабатываемых пакетов.
|
||||
|
||||
------------------------------
|
||||
## 🐳 Контейнеризация и Безопасность в Docker
|
||||
Проект поставляется со специализированной конфигурацией развертывания,
|
||||
обеспечивающей максимальную производительность и изоляцию:
|
||||
|
||||
* Многоэтапная сборка (Multi-stage Build): Образ собирается в официальном
|
||||
контейнере golang:alpine, где происходит компиляция бинарника со флагами
|
||||
-ldflags="-s -w" (вырезаются отладочные символы, что уменьшает размер файла
|
||||
в 2 раза).
|
||||
* Супер-легковесный и безопасный финальный слой (scratch): Финальный образ
|
||||
собирается на базе абсолютно пустого слоя FROM scratch. Внутри контейнера
|
||||
нет Linux-дистрибутива, нет пакетных менеджеров, утилит (sh, bash, ls)
|
||||
и зависимостей. Вес готового Docker-образа составляет всего ~15-20 МБ.
|
||||
* Принцип Non-Root: Внутри контейнера процесс STUN-сервера запускается
|
||||
от имени непривилегированного системного пользователя stunuser.
|
||||
В случае гипотетической уязвимости в коде, злоумышленник не сможет выйти на
|
||||
хост-систему или получить права суперпользователя.
|
||||
* Сетевой режим network_mode: "host": Контейнер подключен к сетевой карте
|
||||
VPS напрямую. Это исключает прослойку docker-proxy и встроенную маршрутизацию
|
||||
Docker, которая является главным «узким горлышком» для UDP-трафика и приводит
|
||||
к потере пакетов под нагрузкой.
|
||||
|
||||
------------------------------
|
||||
## 🛠️ Системный тюнинг ОС Linux под Highload UDP
|
||||
По умолчанию буферы сетевых сокетов в Linux настроены на низкую нагрузку.
|
||||
При шторме UDP-запросов буфер быстро переполняется, и ядро ОС начинает молча
|
||||
дропать (терять) пакеты еще до того, как Go-приложение успеет их прочитать.
|
||||
Для решения этой проблемы в проекте применяется сетевой тюнинг ядра через
|
||||
конфигурацию sysctl. Максимальные и дефолтные буферы приема (rmem) и отправки
|
||||
(wmem) сетевых сокетов расширяются до 25 Мегабайт (26214400 байт):
|
||||
|
||||
* net.core.rmem_max=26214400
|
||||
* net.core.wmem_max=26214400
|
||||
|
||||
Эти настройки жестко фиксируются в системном файле /etc/sysctl.conf хост-машины,
|
||||
благодаря чему сервер гарантированно выдерживает кратковременные всплески трафика
|
||||
(микро-штормы), удерживая пакеты в памяти ОС до момента их вычитки воркерами.
|
||||
|
||||
------------------------------
|
||||
## 📋 Структура конфигурационных файлов проекта
|
||||
Проект имеет модульную и простую структуру, состоящую из следующих компонентов:
|
||||
|
||||
1. main.go — Весь исходный код сервера. Содержит логику инициализации,
|
||||
пул воркеров, парсинг сырых байт STUN-заголовка, генерацию XOR-маппинга для
|
||||
обхода NAT и отправку ответов.
|
||||
2. go.mod — Файл описания Go-модуля (проект STUN на базе Go 1.27.1) с
|
||||
автоматической фиксацией низкоуровневых системных зависимостей (golang.org/x/sys).
|
||||
3. Dockerfile — Инструкция сборки безопасного микро-контейнера на базе
|
||||
scratch от лица non-root пользователя.
|
||||
4. docker-compose.yml — Манифест для оркестрации: настраивает запуск в
|
||||
режиме host, прокидывает переменные окружения, ограничивает ресурсы
|
||||
(Limits: 2 CPU, 128MB RAM) и защищает диск от переполнения логами
|
||||
(ротация логов ограничена 3 файлами по 10МБ).
|
||||
5. .env — Файл конфигурации переменных среды, где хранится внешний публичный
|
||||
IPv4-адрес сервера (PUBLIC_IP), необходимый для корректного заполнения
|
||||
STUN-аттрибутов ответа.
|
||||
|
||||
------------------------------
|
||||
## 📈 Результаты тестирования пропускной способности
|
||||
В ходе стресс-тестирования методом асинхронного UDP-флуда
|
||||
(параллельный запуск тысячи клиентов turnutils_stunclient), сервер показал
|
||||
следующие результаты:
|
||||
|
||||
* Линейная масштабируемость: Обработка пакета из 2000 одновременных
|
||||
запросов выполняется за ~1.19 сек, демонстрируя чистую скорость ~1550-1700 RPS
|
||||
(запросов в секунду) на один клиентский поток тестирования.
|
||||
* Параллельная утилизация ядер: Время работы в пользовательском пространстве
|
||||
(user) и пространстве ядра (sys) превышает реальное время теста (real),
|
||||
что доказывает идеальную параллельную работу пула воркеров на всех доступных
|
||||
ядрах процессора хоста.
|
||||
|
||||
Reference in New Issue
Block a user