Dostrajanie jądra w hostingu Linux przynosi wymierny wzrost wydajności, ponieważ specjalnie dostosowuję parametry sysctl dla sieci, pamięci, procesora i bezpieczeństwa. Ładuję profile bez ponownego uruchamiania i dostosowuję wartości dla obciążeń, współbieżności i zachowania we/wy, tak aby Serwer szybko reaguje pod obciążeniem i działa niezawodnie.
Punkty centralne
- sysctl Kontroluje zachowanie jądra w czasie wykonywania
- Sieć optymalizacja: Backlogs, sockets, TCP
- Pamięć wykończenie: Zamiana, Brudne strony
- CPU Dostrajanie: Harmonogram, PIDy
- Bezpieczeństwo hartowanie bez kosztów ogólnych
Czym jest sysctl w hostingu Linux?
Z sysctl Odczytuję i zmieniam parametry jądra w czasie wykonywania bez jego kompilacji. Wartości są przechowywane jako pliki w katalogu /proc/sys, takie jak net/ipv4/tcp_max_syn_backlog, i kontrolują sieć, pamięć i bezpieczeństwo. W przypadku hostowania obciążeń z wieloma połączeniami, bezpośrednie dostrajanie zmniejsza szczyty opóźnień i limity czasu. Wprowadzam tymczasowe zmiany za pomocą sysctl -w i zapisuję stałe profile w /etc/sysctl.d/*.conf. Następnie ładuję wszystko za pomocą sysctl -system i sprawdzam dmesg i dzienniki, dzięki czemu mogę szybko rozpoznać błędne konfiguracje.
Jak bezpiecznie używać sysctl
Przed wprowadzeniem zmian Profile i dokumentuję rzeczywiste wartości za pomocą sysctl -a, dzięki czemu mogę je w każdej chwili przywrócić. Najpierw testuję nowe wartości na maszynach wirtualnych z porównywalnym obciążeniem. Następnie zwiększam parametry krok po kroku, monitoruję metryki i ponownie dostosowuję. W ten sposób zapobiegam zabójstwom OOM, spadkom gniazd i sporadycznym retransmisjom. Aby uzyskać powtarzalne konfiguracje, tworzę osobny plik, taki jak /etc/sysctl.d/99-hosting.conf i ładuję go w kontrolowany sposób.
Tymczasowe testowanie #
sudo sysctl -w net.core.somaxconn=65535
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=4096
Ustaw # na stałe
sudo tee /etc/sysctl.d/99-hosting.conf >/dev/null <<'EOF'
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
vm.swappiness = 10
vm.dirty_ratio = 20
EOF
sudo sysctl --system
Parametry sieci przenoszące serwery internetowe
Dla wielu jednoczesnych połączeń zwiększam somaxconn, aby nie przepełnić listy połączeń Nginx lub Apache. Używam net.ipv4.tcp_max_syn_backlog, aby zwiększyć kolejkę półotwartych połączeń, co pomaga podczas szczytów ruchu. W konfiguracjach tylko webowych zwykle zostawiam net.ipv4.ip_forward wyłączony, z reverse proxy lub bramami włączam go. Sprawdzam spadki zaległości za pomocą ss -s i netstat -s i sprawdzam, czy kolejki akceptacji są puste. Jeśli chcesz zagłębić się w kontrolę przeciążenia, możesz również ocenić algorytmy takie jak CUBIC lub BBR; moje odniesienie do Kontrola przeciążenia TCP.
# Przykładowe wartości dla często używanych serwerów internetowych
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.ip_forward = 0
Dostrajanie pamięci masowej i maszyn wirtualnych na potrzeby hostingu obciążeń
I niżej szczęśliwość do 10, dzięki czemu jądro dłużej korzysta z pamięci RAM i rzadziej ją wymienia. Przy vm.dirty_ratio wynoszącym od 15 do 20 procent, ograniczam brudne strony, aby obciążenie zapisem nie prowadziło do długich serii spłukiwania. Dla wielu procesów ustawiam vm.overcommit_memory na 1, jeśli znam aplikacje i rozumiem ich rezerwy. Monitoruję również trafienia w pamięci podręcznej stron i oczekiwanie na operacje wejścia-wyjścia, aby móc poprawnie interpretować efekty buforowania. Głębsze spojrzenie na zachowanie pamięci podręcznej zapewnia ten przewodnik po Pamięć podręczna stron.
# Profile pamięci masowej i maszyn wirtualnych
vm.swappiness = 10
vm.dirty_ratio = 20
vm.overcommit_memory = 1
Dostrajanie procesora i harmonogramu
Przy wysokiej współbieżności podnoszę kernel.pid_max dzięki czemu wiele procesów roboczych otrzymuje identyfikatory. W przypadku kwot CFS dostosowuję kernel.sched_cfs_bandwidth_slice_us, aby uniknąć zbyt krótkich plasterków dla usług typu bursty. Sprawdzam długości kolejek uruchamiania, przełączniki kontekstu i czasy kradzieży, zwłaszcza na współdzielonych hostach. Jeśli potrzebuję izolacji CPU, wiążę usługi z rdzeniami poprzez taskset lub cgroups. Wprowadzenie do głębszej optymalizacji jądra zapewnia ten kompaktowy dokument Wydajność jądra-Przewodnik.
# Parametry procesu i harmonogramu
kernel.pid_max = 4194304
# Przykład dla drobniejszych plasterków CFS
kernel.sched_cfs_bandwidth_slice_us = 5000
Parametry bezpieczeństwa bez utraty wydajności
Aktywuję dmesg_restrict, aby uniemożliwić nieuprzywilejowanym użytkownikom czytanie logów jądra. Używam kernel.kptr_restrict do ukrywania adresów, które mogłyby pomóc atakującym w exploitach. Na poziomie sieci domyślnie włączam rp_filter, aby zapobiec spoofingowi IP. Ustawienia te prawie nie wpływają na wydajność i znacząco wzmacniają zabezpieczenia hosta. Ładuję je do tego samego pliku sysctl w kontrolowany sposób, aby pozostać identyfikowalnym.
Wzmocnienie # poprzez sysctl
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
Rozszerzony bufor sieciowy dla wysokiej przepustowości
Dla hostów o dużym natężeniu ruchu pasuję Bufor TCP aby szybkie połączenia nie zawieszały się w limicie okna. Używam net.ipv4.tcp_rmem i tcp_wmem do definiowania minimalnych, standardowych i maksymalnych rozmiarów. net.core.optmem_max i net.core.netdev_max_backlog pomagają w czystym absorbowaniu krótkich serii. Monitorowałem retransmisje, rozwój cwnd i poziomy zapełnienia bufora przed dalszym zwiększaniem wartości. Kroki te zwiększają przepustowość i zauważalnie zmniejszają wahania opóźnień na nowoczesnych łączach 10G.
Rozszerzony bufor sieciowy #
net.core.optmem_max = 81920
net.core.netdev_max_backlog = 3000
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
Praktyka: Od wartości bazowej do wymiernego zysku
Każde strojenie rozpoczynam od Linia bazowa i dokumentuję kluczowe dane, takie jak opóźnienie P95, przepustowość i stopa błędów. Następnie zmieniam kilka parametrów, ładuję profil i ponownie mierzę za pomocą ab, wrk lub sysbench. Jeśli opóźnienie spada, rejestruję zmianę; jeśli wzrasta, cofam ją. W ten sposób buduję profil hostingu, który odpowiada mojej aplikacji. Na koniec ponownie weryfikuję pod obciążeniem produkcyjnym przed pozostawieniem wartości na stałe.
# Zapis aktualnego stanu
sysctl -a > /root/sysctl-baseline.txt
# Wyświetlanie parametrów sieci
sysctl -a | grep -E 'net\.core|net\.ipv4'
# Przeładuj profile
sysctl --system
Tabela porównawcza: profil standardowy vs. hostingowy
Poniżej Tabela pokazuje praktyczne wartości początkowe, których często używam. Wartości zależą od obciążenia, sieci i sprzętu. Zaczynam od tego, sprawdzam metryki i dostosowuję krok po kroku. W razie problemów wracam do wartości domyślnych i zwiększam je małymi krokami. W ten sposób minimalizuję ryzyko i osiągam spójne wyniki.
| Parametry | Standard | Profil hostingu | Korzyści |
|---|---|---|---|
| net.core.somaxconn | 128 | 65535 | Więcej akceptowanych połączeń |
| net.ipv4.tcp_max_syn_backlog | 1024 | 4096 | Mniej spadków ze szczytami |
| vm.swappiness | 60 | 10 | Mniej wymian pod obciążeniem |
| kernel.pid_max | 32768 | 4194304 | Więcej możliwych procesów/pracowników |
| vm.dirty_ratio | 30 | 20 | Bardziej równomierne pisanie |
Unikanie typowych błędów i monitorowanie
Nie używam Wartości ekstremalne, ponieważ mogą one prowadzić do przekroczenia limitu czasu, zabójstw OOM lub utraty pakietów. Testuję zmiany etapami, każdy z wyraźną metryką i krótką fazą obserwacji. Krytycznymi wskaźnikami są: długość kolejki akceptacji, retransmisje TCP, opóźnienie P95, oczekiwanie IO i swap in/out. Do monitorowania używam lekkich agentów i pulpitów nawigacyjnych, dzięki czemu mogę szybko rozpoznać trendy. Po aktualizacjach jądra sprawdzam, czy profile sysctl są nadal ważne i w razie potrzeby ponownie je ładuję.
Trwałość, sekwencja i dystrybucja
Aby zapewnić powtarzalność profili, obserwuję sekwencję ładowania w pliku /etc/sysctl.d: Pliki są przetwarzane leksykograficznie. Celowo przypisuję prefiksy, takie jak 60-... lub 99-..., aby upewnić się, że mój profil hostingu zastępuje inne ustawienia domyślne. Różnice między dystrybucjami (Debian/Ubuntu vs. RHEL/Alma) zwykle wpływają tylko na ścieżki i wartości domyślne; sysctl -system zawsze ładuje /etc/sysctl.conf, /etc/sysctl.d/*.conf i pliki dostawców, jeśli ma to zastosowanie. Po większych aktualizacjach systemu sprawdzam za pomocą sysctl -system -o (suchy przebieg w zależności od wersji) lub porównuję załadowaną efektywną konfigurację z moim szablonem, aby uniknąć niespodzianek.
Przykład #: zapewnienie czystej sekwencji
sudo ls -1 /etc/sysctl.d
10-vendor.conf
50-defaults.conf
99-hosting.conf # nadpisuje wszystko przed nim
# skutecznie różnicuje załadowane wartości
sysctl -a > /root/sysctl-after.txt
diff -u /root/sysctl-baseline.txt /root/sysctl-after.txt | less
Cykl życia TCP i zarządzanie portami
Przy dużym obciążeniu tworzonych jest wiele krótkotrwałych połączeń. Umieszczam ip_local_port_range aby połączenia wychodzące (np. z serwerów proxy) nie utknęły w limicie portu efemerycznego. tcp_fin_timeout kontroluje, jak długo gniazda pozostają w FIN-WAIT-2. Z sensownym Keepalive-parametry, szybciej zamykam martwe sesje bez agresywnego zrywania połączeń. TIME_WAIT jest normalny i chroni przed opóźnionymi pakietami; nie zmniejszam go na ślepo. tcp_tw_reuse Pomaga głównie na hostach klienckich, na czystych serwerach zwykle pozostaje wyłączony. Pozostawiam włączone znaczniki czasu i SACK, ponieważ poprawiają one wydajność i niezawodność.
# Zakres portów i cykl życia TCP
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
# Ostrożnie z tcp_tw_reuse: przydatne tylko dla wychodzącego obciążenia klienta
# net.ipv4.tcp_tw_reuse = 1
Utrzymywanie stabilności IPv6 i tabel sąsiadów
Wiele hostów przenosi dziś ruch dwusieciowy. Zoptymalizowałem tabele ARP/ND tak, aby nie było komunikatów o przepełnieniu tabeli sąsiadów, szczególnie w przypadku serwerów proxy lub węzłów z wieloma elementami równorzędnymi. The gc_thresh-Definiuję progi, aby dopasować je do macierzy połączeń. Pozostawiam opcje ICMPv6 i router add restrykcyjne dla serwerów, aby żadne niechciane trasy nie zostały uwzględnione. W przypadku IPv4 zwracam również uwagę na zbieranie śmieci ARP, aby wpisy starzały się w odpowiednim czasie, ale nie znikały zbyt wcześnie.
Tabele sąsiedztwa #: bardziej hojne progi
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
Konserwatywne starzenie ARP/ND #
net.ipv4.neigh.default.gc_stale_time = 60
Wspólne myślenie o deskryptorach plików i backlogach
Częstym wąskim gardłem są Deskryptory plików. Jeśli aplikacje utrzymują tysiące gniazd, fs.file-max (ogólnosystemowy) i ulimit/nofile (na usługę) pasują do siebie. somaxconn zwiększa kolejkę listy, ale pomaga tylko wtedy, gdy sam serwer WWW może otwierać więcej FD, a współczynnik akceptacji jest wystarczająco wysoki. Upewniam się, że limity systemowe i usługowe są zsynchronizowane, w przeciwnym razie pojawiają się sztuczne wąskie gardła pomimo „dużych“ zaległości jądra.
# Zezwól na więcej FD w całym systemie
fs.file-max = 2097152
# Strona usługi (przykładowa jednostka systemd)
# [Service]
# LimitNOFILE=1048576
Amortyzacja obciążeń UDP/QUIC
Korzystanie z DNS, syslog, telemetrii i QUIC (HTTP/3) UDP. Tutaj skaluję globalne bufory gniazd i limity pamięci specyficzne dla UDP. W przypadku dużych, gwałtownych obciążeń UDP (takich jak bramki telemetryczne) zapobiega to spadkom na ścieżce odbiorczej. Monitoruję liczniki błędów za pomocą ss -u -a i netstat -su i stopniowo dostosowuję maksima. Dla QUIC, net.core.rmem_max/wmem_max jest również istotne, ponieważ stosy przestrzeni użytkownika często osiągają te limity poprzez setsockopt.
# Bufor UDP i limity
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.udp_mem = 98304 131072 262144
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
Określa brudny zapis zwrotny: Bajty zamiast procentów
W systemach z dużą ilością pamięci RAM wartości procentowe mogą prowadzić do dużych, nagłych wyczyszczeń. Dlatego wolę używać vm.dirty_background_bytes oraz vm.dirty_bytes, aby zdefiniować bezwzględne górne limity. Stabilizuje to szybkość zapisu i wygładza opóźnienia, zwłaszcza w przypadku dysków twardych lub mieszanych obciążeń. Rozważam również vm.min_free_kbytes umiarkowanie, aby jądro miało wystarczająco dużo wolnej pamięci na alokacje typu burst.
Przykład #: bezwzględne limity brudne (ok. 1G tła, 4G twarde)
vm.dirty_background_bytes = 1073741824
vm.dirty_bytes = 4294967296
vm.min_free_kbytes = 65536
Rozkład obciążenia RPS/RFS i sieciowych IRQ
Przy wysokich prędkościach PPS, pojedynczy rdzeń CPU może zawiesić się na NIC-IRQ. Używam Receive Packet Steering (RPS) i, jeśli to konieczne, Receive Flow Steering (RFS), aby rozdzielić przetwarzanie pakietów na kilka rdzeni. Globalnie ustawiam net.core.rps_sock_flow_entries, Rzeczywista alokacja odbywa się dla każdej kolejki za pośrednictwem sysfs. Redukuje to hotspoty procesora, poprawia lokalizację pamięci podręcznej i zmniejsza szczyty opóźnień. W połączeniu z net.core.netdev_max_backlog daje to bardziej niezawodny potok.
# Globalne wpisy przepływu dla RPS
net.core.rps_sock_flow_entries = 32768
# Uwaga: Strojenie na kolejkę poprzez /sys/class/net//queues/rx-*/rps_cpus
# i rps_flow_cnt, w zależności od karty sieciowej i liczby kolejek.
Kontenery, przestrzenie nazw i maszyny wirtualne
Pojemniki mieszczą wiele net.*-Wartości przestrzeń nazw i może mieć zastosowanie do każdej sieciowej przestrzeni nazw. Dlatego dokumentuję, czy dostosowuję sieć hosta, czy pod/kontenera. Orkiestratorzy często zezwalają tylko na bezpieczną listę sysctls; wartości takie jak kernel.pid_max pozostają po stronie hosta. Na maszynach wirtualnych sprawdzam, które wirtualne karty sieciowe i odciążenia są aktywne (virtio, ENA), ponieważ odciążenia i MTU mają duży wpływ na wymagania buforowe i rozwój cwnd. Hosty bare-metal o dużym obciążeniu NUMA korzystają z dezaktywacji vm.zone_reclaim_mode i celowy układ powinowactwa CPU/IRQ.
# Uniknięcie efektu ubocznego NUMA
vm.zone_reclaim_mode = 0
Conntrack i stateful firewall w skrócie
Jeśli host działa jako NAT/firewall lub hostuje wiele kontenerów z egress NAT, to skalowanie nf_conntrack-table. Zbyt małe tabele haszujące generują spadki i duże opóźnienia podczas skanowania tabel. Mierzę wykorzystanie za pomocą nstat i patrzę na „oczekiwane“ vs. „w użyciu“. W przypadku czystych serwerów internetowych bez NAT, conntrack jest często bezkrytyczny lub nawet dezaktywowany; na bramach musi być włączony do pakietu tuningowego.
# Conntrack size (tylko jeśli jest aktywnie używany!)
net.netfilter.nf_conntrack_max = 1048576
Odporność na ataki i anomalie
Pomoc w zakresie ruchu botów i skanowania tcp_syncookies i konserwatywne opcje ICMP/redirect. Syncookies zapisują uścisk dłoni w przypadku przepełnienia kolejek SYN bez nadmiernego ograniczania legalnego ruchu. Wyłączam przekierowania i trasy źródłowe na serwerach, które nie powinny być przekierowywane. Te środki zabezpieczające są lekkie i uzupełniają mechanizmy ochrony wymienione powyżej.
# SYN flood defence i konserwatywne zachowanie routingu
net.ipv4.tcp_syncookies = 1
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
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
Pogłębić praktykę pomiarową: Co sprawdzam regularnie
Aby uzyskać powtarzalne wyniki, mierzę konsekwentnie przed i po zmianach. Po stronie sieci używam ss -s, ss -ti, nstat i netstat -s, aby zobaczyć długości kolejek, retransmisje i statystyki worków. Po stronie pamięci I/O, vmstat, iostat i pidstat pomagają kategoryzować brudne płuczki, przełączniki kontekstowe i czasy oczekiwania procesora. Sprawdzam również testy obciążenia:
- Kolejka akceptacji (LISTEN) i kolejka SYN: odrzucone vs. przepełnione
- Pacing/przepustowość na połączenie i rozwój cwnd
- Opóźnienia P95/99 w porównaniu A/B, zamiast tylko średniej
- Współczynnik wejścia/wyjścia zamiany i współczynnik trafień pamięci podręcznej stron
- Rozkład obciążenia IRQ i długości kolejek uruchamiania na CPU
Szybkie sprawdzanie stanu #
ss -s
netstat -s | egrep 'listen|SYN|retran|dropped'
vmstat 1 10
pidstat -w -u -r 1 5
Przykład: skonsolidowany profil hostingu
Na początek łączę wartości podstawowe i rozszerzone w jednym pliku. Następnie zwiększam je małymi krokami, każdy z wyraźnymi punktami pomiarowymi. Poniższe wartości są konserwatywnym, ale wysokowydajnym punktem wyjścia dla obciążonych serwerów WWW i serwerów proxy.
sudo tee /etc/sysctl.d/99-hosting.conf >/dev/null <<'EOF'
Podstawy sieci #
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
net.core.netdev_max_backlog = 3000
net.core.optmem_max = 81920
Bufory i porty TCP #
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
# UDP/QUIC
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.udp_mem = 98304 131072 262144
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
Tabele sąsiadów #
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
net.ipv4.neigh.default.gc_stale_time = 60
Bezpieczeństwo #
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
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
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Memory/VM
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_bytes = 1073741824
vm.dirty_bytes = 4294967296
vm.min_free_kbytes = 65536
vm.overcommit_memory = 1
vm.zone_reclaim_mode = 0
Procesor/procesy #
kernel.pid_max = 4194304
kernel.sched_cfs_bandwidth_slice_us = 5000
# RPS
net.core.rps_sock_flow_entries = 32768
# FDs
fs.file-max = 2097152
EOF
sudo sysctl --system
Podsumowanie: Strojenie jako powtarzający się proces
Ukierunkowane Dostrajanie jądra z sysctl przynosi wyraźne efekty w hostingu: krótsze czasy odpowiedzi, wyższe wartości przepustowości i stałe usługi. Zaczynam od podstaw sieciowych, takich jak somaxconn i tcp_max_syn_backlog, a następnie dbam o pamięć za pomocą swappiness i dirty_ratio. Następnie optymalizuję PIDy i schedulery oraz zabezpieczam hosta za pomocą dmesg_restrict, kptr_restrict i rp_filter. Mierzę każdą zmianę, dokumentuję ją i obserwuję metryki. Krok po kroku tworzę profil, który wydajnie obsługuje moje obciążenia i ma rezerwy na szczyty ruchu.


