mirror of
https://github.com/telemt/telemt.git
synced 2026-10-06 17:35:57 +03:00
56e0f000ba
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
182 lines
14 KiB
Markdown
182 lines
14 KiB
Markdown
# Руководство по High-Load конфигурации и тюнингу
|
||
При развертывании Telemt под высокой нагрузкой (десятки и сотни тысяч одновременных подключений), стандартные ограничения сетевого стека ОС могут приводить к потерям пакетов, переключениям контекста CPU и отказам в соединениях. В данном руководстве описана настройка ядра Linux, системных лимитов и аппаратной конфигурации для работы в подобных сценариях.
|
||
|
||
---
|
||
## 1. Системные лимиты и файловые дескрипторы
|
||
Каждое TCP-сосоединение требует файлового дескриптора. При 100 тысячах соединений стандартные лимиты Linux (зачастую 1024 или 65535) будут исчерпаны немедленно.
|
||
### Общесистемные лимиты (`sysctl`)
|
||
Увеличьте глобальный лимит файловых дескрипторов в `/etc/sysctl.conf`:
|
||
```ini
|
||
fs.file-max = 2097152
|
||
fs.nr_open = 2097152
|
||
```
|
||
### На уровне пользователя (`limits.conf`)
|
||
Отредактируйте `/etc/security/limits.conf`, чтобы разрешить пользователю (от которого запущен telemt) резервировать дескрипторы:
|
||
```conf
|
||
* soft nofile 1048576
|
||
* hard nofile 1048576
|
||
root soft nofile 1048576
|
||
root hard nofile 1048576
|
||
```
|
||
### Переопределения для Systemd / Docker
|
||
Если используется **Systemd**, добавьте в ваш `telemt.service`:
|
||
```ini
|
||
[Service]
|
||
LimitNOFILE=1048576
|
||
LimitNPROC=65535
|
||
TasksMax=infinity
|
||
```
|
||
Если используется **Docker**, задайте `ulimits` в `docker-compose.yaml`:
|
||
```yaml
|
||
services:
|
||
telemt:
|
||
ulimits:
|
||
nofile:
|
||
soft: 1048576
|
||
hard: 1048576
|
||
```
|
||
|
||
---
|
||
## 2. Тонкая настройка сетевого стека ядра (`sysctl`)
|
||
Создайте выделенный файл `/etc/sysctl.d/99-telemt-highload.conf` и примените его через `sysctl -p /etc/sysctl.d/99-telemt-highload.conf`.
|
||
### 2.1 Очереди соединений и защита от SYN-флуда
|
||
Увеличьте размеры очередей, чтобы поглощать внезапные всплески соединений и смягчить атаки типа SYN flood:
|
||
```ini
|
||
net.core.somaxconn = 65535
|
||
net.core.netdev_max_backlog = 65535
|
||
net.ipv4.tcp_max_syn_backlog = 65535
|
||
net.ipv4.tcp_syncookies = 1
|
||
```
|
||
### 2.2 Исчерпание портов и TIME-WAIT сокеты
|
||
Высокая текучесть приводит к нехватке временных (ephemeral) портов. Расширьте диапазон портов и позвольте ядру быстро переиспользовать закрытые сокеты:
|
||
```ini
|
||
net.ipv4.ip_local_port_range = 10000 65535
|
||
net.ipv4.tcp_fin_timeout = 15
|
||
net.ipv4.tcp_tw_reuse = 1
|
||
net.ipv4.tcp_max_tw_buckets = 2000000
|
||
```
|
||
### 2.3 TCP Keepalive (Агрессивная очистка мертвых соединений)
|
||
По умолчанию Linux держит "оборванные" TCP-сессии более 2 часов. Значения ниже начинают probes после пяти минут простоя и закрывают не отвечающий peer после последующего probe budget — примерно через 7–8 минут общего простоя:
|
||
```ini
|
||
net.ipv4.tcp_keepalive_time = 300
|
||
net.ipv4.tcp_keepalive_intvl = 30
|
||
net.ipv4.tcp_keepalive_probes = 5
|
||
```
|
||
### 2.4 Буферы TCP и управление перегрузками (Congestion Control)
|
||
Оптимизируйте использование памяти на сокет и переключитесь на алгоритм BBR (Bottleneck Bandwidth and Round-trip propagation time) для улучшения задержки на плохих сетях:
|
||
```ini
|
||
# Core buffer sizes
|
||
net.core.rmem_default = 262144
|
||
net.core.wmem_default = 262144
|
||
net.core.rmem_max = 16777216
|
||
net.core.wmem_max = 16777216
|
||
# TCP-specific buffers (min, default, max)
|
||
net.ipv4.tcp_rmem = 4096 87380 16777216
|
||
net.ipv4.tcp_wmem = 4096 65536 16777216
|
||
# Enable BBR
|
||
net.core.default_qdisc = fq
|
||
net.ipv4.tcp_congestion_control = bbr
|
||
```
|
||
|
||
---
|
||
## 3. Тюнинг Conntrack (Netfilter)
|
||
Если ваш сервер использует `iptables`, `ufw` или `firewalld`, ядро вынуждено отслеживать каждое соединение в таблице состояний (`nf_conntrack`). Когда эта таблица переполняется, Linux отбрасывает новые пакеты без уведомления приложения.
|
||
Проверьте текущие лимиты и использование:
|
||
```bash
|
||
sysctl net.netfilter.nf_conntrack_max
|
||
sysctl net.netfilter.nf_conntrack_count
|
||
```
|
||
Если вы близки к пределу, увеличьте таблицу и заставьте ядро быстрее удалять установленные соединения. Добавьте в `/etc/sysctl.d/99-telemt-highload.conf`:
|
||
```ini
|
||
# In /etc/sysctl.d/99-telemt-highload.conf
|
||
net.netfilter.nf_conntrack_max = 2097152
|
||
# Reduce timeout from default 5 days to 1 hour
|
||
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
|
||
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 12
|
||
```
|
||
*Внимание: в зависимости от ОС, вам может потребоваться выполнить `modprobe nf_conntrack` перед установкой этих параметров.*
|
||
|
||
Когда `server.conntrack_control.inline_conntrack_control = true` и `[server.conntrack_control]` использует `notrack` или `hybrid`, один generation-fenced authority владеет только правилами conntrack control, созданными Telemt. Он применяет изменения IPv4 и IPv6, игнорирует устаревшие или конфликтующие публикации и повторяет неудачный reconcile через 1, 2, 4, 8, 16 и далее не более чем 30 секунд. Частичный многошаговый сбой запускает best-effort восстановление; неудачный rollback оставляет applied firewall state неизвестным до следующего успешного reconcile. `telemt_conntrack_control_state{flag="rule_apply_ok"}` показывает, действует ли требуемый набор правил. При включённой core telemetry попытки используют `telemt_conntrack_rule_reconcile_total{result="success"|"error"}` и `telemt_conntrack_rule_rollback_total{result="success"|"error"}`. При shutdown выполняется ограниченный 30 секундами best-effort cleanup собственных правил. Настройки conntrack control требуют перезапуска.
|
||
|
||
---
|
||
## 4. Архитектура: развёртывание за HAProxy
|
||
|
||
### 4.1 L4-развёртывание native MTProxy и TLS-front
|
||
|
||
Для массового native MTProxy- или TLS-front-трафика L4 HAProxy может поглощать всплески соединений перед передачей TCP streams в Telemt. Следующий пример **не подходит для WEB-listener**.
|
||
|
||
#### Оптимизация `haproxy.cfg` для High-Load
|
||
```haproxy
|
||
global
|
||
# Disable detailed connection logs under load
|
||
log stdout format raw local0 err
|
||
maxconn 250000
|
||
# Tune buffers and socket acceptance
|
||
tune.bufsize 16384
|
||
tune.maxaccept 64
|
||
defaults
|
||
log global
|
||
mode tcp
|
||
option clitcpka
|
||
option srvtcpka
|
||
timeout connect 5s
|
||
timeout client 1h
|
||
timeout server 1h
|
||
# Purge dead peers quickly
|
||
timeout client-fin 10s
|
||
timeout server-fin 10s
|
||
frontend proxy_in
|
||
bind *:443
|
||
maxconn 250000
|
||
option tcp-smart-accept
|
||
default_backend telemt_backend
|
||
backend telemt_backend
|
||
option tcp-smart-connect
|
||
# Preserve the client IP for Telemt through PROXY v2
|
||
server telemt_core 10.10.10.1:443 maxconn 250000 send-proxy-v2 check inter 5s
|
||
```
|
||
**Важно**: Telemt должен быть настроен на обработку протокола `PROXY` на порту `443`, чтобы получать оригинальные IP-адреса клиентов.
|
||
|
||
### 4.2 WEB-развёртывание
|
||
|
||
WEB-режиму требуется L7 TLS-терминатор и приватный plain HTTP/1.1 listener Telemt с `proxy_protocol = false`; не используйте для него L4 backend с `send-proxy-v2` из предыдущего примера. Следуйте полному [руководству по WEB-прокси](../WEB/WEB_PROXY.ru.md), сохраняйте `Host`, точные path и query, WebSocket Upgrade headers и передавайте один перезаписанный `X-Forwarded-For` только от явно доверенных CIDR терминатора. Public ALPN должен предлагать `h2` для `https-lanes` и `http/1.1` для WebSocket Upgrade.
|
||
|
||
Для WEB-listener задайте `web_client_ip_source = "x_forwarded_for"` и укажите в `web_trusted_proxy_cidrs` только адреса непосредственного HAProxy. Не доверяйте доступной клиентам подсети и не включайте PROXY protocol на этом listener.
|
||
|
||
Направляйте весь vhost в один процесс Telemt. При совместном размещении по prefix сохраняйте настроенный `base_path` без rewrite; во время миграции направляйте в Telemt старое и новое поддеревья, пока ранее выпущенные процессом credentials ещё могут использоваться. Multi-process backend требует affinity всего vhost для bridge root, создания и восстановления session, uplink, downlink, DELETE, diagnostics и WebSocket Upgrade.
|
||
|
||
Например, следующий фрагмент HAProxy направляет только точный host и WEB-поддерево с завершающим слешем, не изменяя request target:
|
||
|
||
```haproxy
|
||
frontend https_in
|
||
mode http
|
||
bind *:443 ssl crt /etc/haproxy/certs/proxy.pem alpn h2,http/1.1
|
||
timeout client 65s
|
||
acl telemt_web_host hdr(host) -i proxy.example.com proxy.example.com:443
|
||
acl telemt_web_path path_beg /telegram/web/
|
||
use_backend telemt_web if telemt_web_host telemt_web_path
|
||
|
||
backend telemt_web
|
||
mode http
|
||
retries 0
|
||
timeout connect 5s
|
||
timeout server 65s
|
||
http-request set-header Host proxy.example.com
|
||
http-request set-header X-Forwarded-For %[src]
|
||
server telemt_web_1 127.0.0.1:18080 check
|
||
```
|
||
|
||
Обрабатывайте путь без завершающего слеша `/telegram/web` вне этого backend, чтобы frontend не создавал redirect alias в аутентифицированное поддерево. Не добавляйте `set-path`, `replace-path` или path-компонент к адресу backend server. Значения 65 секунд — пример для defaults; client и server timeouts должны быть больше `web.timeouts.long_poll_secs` и удвоенного effective WebSocket liveness interval.
|
||
|
||
При расчёте capacity учитывайте одновременно публичные TLS sockets и приватные sockets между терминатором и Telemt. Совместно рассчитывайте file descriptors, upstream capacity терминатора, `web.limits.max_http_connections`, handler capacity, параллельные long polls и WebSocket lanes; upstream keepalive pool не является лимитом concurrency.
|
||
|
||
---
|
||
## 5. Диагностика и мониторинг
|
||
|
||
- **Переполнение listen queues**: проверяйте `ListenOverflows` и `ListenDrops` в `/proc/net/netstat` либо через `nstat`.
|
||
- **Conntrack pressure**: проверяйте `nf_conntrack_count`, kernel logs и `telemt_conntrack_control_state{flag="rule_apply_ok"}`; при включённой core telemetry также проверяйте счётчики reconcile/rollback выше.
|
||
- **File descriptors**: `cat /proc/sys/fs/file-nr` и лимиты процесса Telemt в `/proc/<pid>/limits`.
|
||
- **Состояния соединений**: `ss -s`; избегайте полного сканирования через `netstat` на нагруженном сервере.
|
||
- **Rate limiter contention**: при включённой core telemetry настройте alert на положительный прирост или rate counter, например `increase(telemt_rate_limiter_cas_retry_exhausted_total[5m]) > 0`, с группировкой по `scope`, `direction` и `operation`. Reserve exhaustion возвращает нулевой grant без классификации как настроенный throttle; refund exhaustion сохраняет списание. Эта метрика не является ни счётчиком dropped connections, ни счётчиком policy throttling.
|
||
- **WEB**: объединяйте telemetry терминатора и внешний TLS probe с `/v1/runtime/web/status`, `telemt_web_tcp_accept_total{result="accepted"|"error"}` и остальными `telemt_web_*` metrics. Request path и `base_path` намеренно не используются как metric labels.
|