204 lines
7.4 KiB
Bash
Executable File
204 lines
7.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# game-optimize.sh — оптимизация Debian 12 под игровые серверы / игровой ПК
|
|
# Минимальный пинг, низкий bufferbloat, быстрые прерывания
|
|
|
|
# Запуск: curl -fsSL https://gitea.creative-tg1.ru/CREATIVE_tg1/for-servers/raw/branch/main/server/game-optimize.sh | sudo bash
|
|
|
|
set -e
|
|
|
|
LIMIT_NOFILE=65535
|
|
|
|
echo "============================================"
|
|
echo " Game Server Optimization — Debian 12"
|
|
echo "============================================"
|
|
echo ""
|
|
|
|
# ── 1. Сеть (sysctl) ─────────────────────────────────────
|
|
|
|
echo "[1/5] Сетевые оптимизации (sysctl)..."
|
|
|
|
cat >/etc/sysctl.d/99-game-network.conf <<SYSEOF
|
|
#################################################
|
|
# Queueing + Congestion Control
|
|
# cake активнее борется с bufferbloat, BBR для TCP
|
|
#################################################
|
|
net.core.default_qdisc = cake
|
|
net.ipv4.tcp_congestion_control = bbr
|
|
|
|
#################################################
|
|
# Socket buffers — маленькие, без bufferbloat
|
|
#################################################
|
|
net.core.rmem_default = 212992
|
|
net.core.wmem_default = 212992
|
|
net.core.rmem_max = 16777216
|
|
net.core.wmem_max = 16777216
|
|
|
|
#################################################
|
|
# Network backlog — умеренный
|
|
#################################################
|
|
net.core.netdev_max_backlog = 5000
|
|
net.core.somaxconn = 4096
|
|
|
|
#################################################
|
|
# TCP buffers — сбалансированные
|
|
#################################################
|
|
net.ipv4.tcp_rmem = 4096 87380 16777216
|
|
net.ipv4.tcp_wmem = 4096 65536 16777216
|
|
|
|
#################################################
|
|
# UDP buffers — для игрового трафика
|
|
#################################################
|
|
net.ipv4.udp_rmem_min = 16384
|
|
net.ipv4.udp_wmem_min = 16384
|
|
|
|
#################################################
|
|
# busy_poll — не ждём прерываний, опрашиваем
|
|
# ценой CPU (50 мкс), снижает latency на 20-50%
|
|
#################################################
|
|
net.core.busy_poll = 50
|
|
net.core.busy_read = 50
|
|
|
|
#################################################
|
|
# TCP low latency
|
|
#################################################
|
|
net.ipv4.tcp_low_latency = 1
|
|
net.ipv4.tcp_notsent_lowat = 16384
|
|
|
|
#################################################
|
|
# Security / routing
|
|
#################################################
|
|
net.ipv4.conf.all.accept_redirects = 0
|
|
net.ipv4.conf.default.accept_redirects = 0
|
|
net.ipv4.conf.all.send_redirects = 0
|
|
net.ipv4.conf.default.send_redirects = 0
|
|
|
|
#################################################
|
|
# Keepalive — быстрее обнаруживать разрыв
|
|
#################################################
|
|
net.ipv4.tcp_keepalive_time = 120
|
|
net.ipv4.tcp_keepalive_intvl = 30
|
|
net.ipv4.tcp_keepalive_probes = 5
|
|
|
|
#################################################
|
|
# Ephemeral ports
|
|
#################################################
|
|
net.ipv4.ip_local_port_range = 1024 65535
|
|
|
|
#################################################
|
|
# TCP fastopen — только клиент
|
|
#################################################
|
|
net.ipv4.tcp_fastopen = 1
|
|
|
|
#################################################
|
|
# FIN timeout — быстрее освобождать сокеты
|
|
#################################################
|
|
net.ipv4.tcp_fin_timeout = 10
|
|
|
|
#################################################
|
|
# SYN backlog + retries — меньше ретраев, быстрее фейл
|
|
#################################################
|
|
net.ipv4.tcp_max_syn_backlog = 8192
|
|
net.ipv4.tcp_syn_retries = 2
|
|
net.ipv4.tcp_synack_retries = 2
|
|
SYSEOF
|
|
|
|
sysctl --system >/dev/null 2>&1
|
|
echo " OK"
|
|
|
|
# ── 2. NIC — txqueuelen + coalescing ─────────────────────
|
|
|
|
echo "[2/5] Сетевые интерфейсы (NIC)..."
|
|
|
|
for iface in $(ls /sys/class/net/ | grep -v lo); do
|
|
# Короткая очередь на интерфейсе
|
|
ip link set dev "$iface" txqueuelen 1000 2>/dev/null || true
|
|
|
|
# Выключаем coalescing прерываний (rx-usecs=0) — главный буст для пинга
|
|
ethtool -C "$iface" rx-usecs 0 2>/dev/null || true
|
|
ethtool -C "$iface" tx-usecs 0 2>/dev/null || true
|
|
|
|
# Увеличиваем кольцевой буфер NIC (если поддерживается)
|
|
ethtool -G "$iface" rx 4096 2>/dev/null || true
|
|
ethtool -G "$iface" tx 4096 2>/dev/null || true
|
|
|
|
echo " $iface OK"
|
|
done
|
|
|
|
# ── 3. ulimit ────────────────────────────────────────────
|
|
|
|
echo "[3/5] Лимиты файловых дескрипторов (limits.d)..."
|
|
|
|
cat >/etc/security/limits.d/90-nofile.conf <<LIMEOF
|
|
* soft nofile ${LIMIT_NOFILE}
|
|
* hard nofile ${LIMIT_NOFILE}
|
|
root soft nofile ${LIMIT_NOFILE}
|
|
root hard nofile ${LIMIT_NOFILE}
|
|
LIMEOF
|
|
|
|
echo " OK"
|
|
|
|
# ── 4. systemd DefaultLimitNOFILE ────────────────────────
|
|
|
|
echo "[4/5] Лимиты systemd (DefaultLimitNOFILE)..."
|
|
|
|
for conf in /etc/systemd/system.conf /etc/systemd/user.conf; do
|
|
if grep -q "^#DefaultLimitNOFILE=" "$conf" 2>/dev/null; then
|
|
sed -i "s/^#DefaultLimitNOFILE=.*/DefaultLimitNOFILE=${LIMIT_NOFILE}/" "$conf"
|
|
elif ! grep -q "^DefaultLimitNOFILE=" "$conf" 2>/dev/null; then
|
|
echo "DefaultLimitNOFILE=${LIMIT_NOFILE}" >> "$conf"
|
|
else
|
|
sed -i "s/^DefaultLimitNOFILE=.*/DefaultLimitNOFILE=${LIMIT_NOFILE}/" "$conf"
|
|
fi
|
|
done
|
|
|
|
systemctl daemon-reload
|
|
echo " OK"
|
|
|
|
# ── 5. IRQ affinity (если CPU > 1 ядро) ─────────────────
|
|
|
|
echo "[5/5] IRQ affinity..."
|
|
|
|
CPU_COUNT=$(nproc)
|
|
if [ "$CPU_COUNT" -gt 1 ]; then
|
|
# Распределяем сетевые прерывания по ядрам
|
|
for iface in $(ls /sys/class/net/ | grep -v lo); do
|
|
irqs=$(grep "$iface" /proc/interrupts 2>/dev/null | awk -F: '{print $1}' || true)
|
|
core=0
|
|
for irq in $irqs; do
|
|
irq_num="${irq//[^0-9]/}"
|
|
[ -z "$irq_num" ] && continue
|
|
if [ -f "/proc/irq/$irq_num/smp_affinity_list" ]; then
|
|
echo "$core" > "/proc/irq/$irq_num/smp_affinity_list" 2>/dev/null || true
|
|
core=$(( (core + 1) % CPU_COUNT ))
|
|
fi
|
|
done
|
|
done
|
|
echo " Распределено по $CPU_COUNT ядрам"
|
|
else
|
|
echo " 1 ядро — пропущено"
|
|
fi
|
|
|
|
# ── Итоги ─────────────────────────────────────────────────
|
|
|
|
echo ""
|
|
echo "============================================"
|
|
echo " Итог"
|
|
echo "============================================"
|
|
echo ""
|
|
echo "Очередь:"
|
|
sysctl net.core.default_qdisc
|
|
echo "Контроль перегрузки:"
|
|
sysctl net.ipv4.tcp_congestion_control
|
|
echo "busy_poll:"
|
|
sysctl net.core.busy_poll
|
|
echo "Soft ulimit: $(ulimit -Sn)"
|
|
echo "Hard ulimit: $(ulimit -Hn)"
|
|
echo ""
|
|
echo "NIC:"
|
|
for iface in $(ls /sys/class/net/ | grep -v lo); do
|
|
echo " $iface: txqueuelen=$(cat /sys/class/net/$iface/tx_queue_len 2>/dev/null || echo '?')"
|
|
done
|
|
echo ""
|
|
echo "Готово."
|
|
echo "После перезагрузки сессии / машины — ulimit -n покажет ${LIMIT_NOFILE}"
|