← Назад к вопросам
Как решишь проблему перегрузки сервера Load Average?
2.3 Middle🔥 181 комментариев
#DevOps и инфраструктура#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение проблемы перегрузки сервера (High Load Average)
Высокий Load Average указывает на перегрузку CPU или I/O. Подход должен быть систематичным: диагностика → анализ → оптимизация.
1. Диагностика: Определить причину
# Проверить load average
uptime
# Вывод: load average: 15.23, 12.45, 10.56
# 5 минут: 15.23 | 10 минут: 12.45 | 15 минут: 10.56
# Системный мониторинг
top -b -n 1 | head -15 # Процессы с высокой нагрузкой
ps aux --sort=-%cpu | head -10 # По CPU
ps aux --sort=-%mem | head -10 # По памяти
# I/O нагрузка
iotop -b -n 1
iostat -x 1 5 # Дисковая активность
# Network нагрузка
netstat -an | grep ESTABLISHED | wc -l
ss -s # Сокеты и соединения
# Системные ресурсы
free -h # Память
df -h # Диск
2. Python код: Диагностический скрипт
import psutil
import time
from collections import defaultdict
class SystemDiagnostics:
def __init__(self):
self.cpu_count = psutil.cpu_count()
self.thresholds = {
'load_avg': self.cpu_count * 2, # Warning выше 2x CPU count
'memory': 85, # 85% памяти
'disk': 90, # 90% диска
}
def check_load_average(self):
load_avg = psutil.getloadavg()
cpu_count = psutil.cpu_count()
severity = "OK"
if load_avg[0] > cpu_count * 1.5:
severity = "WARNING"
elif load_avg[0] > cpu_count * 3:
severity = "CRITICAL"
print(f"Load Average: {load_avg}")
print(f"CPU Count: {cpu_count}")
print(f"Status: {severity}")
return load_avg, severity
def check_process_bottleneck(self):
"""Определить какие процессы потребляют ресурсы"""
processes = []
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
try:
processes.append(proc.info)
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
# Сортируем по CPU
top_cpu = sorted(processes, key=lambda x: x['cpu_percent'], reverse=True)[:5]
print("\nTop 5 CPU consumers:")
for proc in top_cpu:
print(f"{proc['name']}: {proc['cpu_percent']}% CPU")
return top_cpu
def check_io_bottleneck(self):
"""Проверить I/O нагрузку"""
disk_io = psutil.disk_io_counters()
print(f"\nDisk I/O:")
print(f"Read: {disk_io.read_bytes / 1024 / 1024:.2f} MB")
print(f"Write: {disk_io.write_bytes / 1024 / 1024:.2f} MB")
net_io = psutil.net_io_counters()
print(f"\nNetwork I/O:")
print(f"Sent: {net_io.bytes_sent / 1024 / 1024:.2f} MB")
print(f"Recv: {net_io.bytes_recv / 1024 / 1024:.2f} MB")
return disk_io, net_io
diag = SystemDiagnostics()
diag.check_load_average()
diag.check_process_bottleneck()
diag.check_io_bottleneck()
3. Решение: Оптимизация на уровне Python приложения
Проблема: Синхронный код блокирует потоки
# ❌ Неправильно — синхронные I/O операции
def handle_request(request):
data = requests.get('https://api.example.com/data') # Блокирует
result = database.query('SELECT * FROM users') # Блокирует
return result
# Если 100 запросов одновременно — нужно 100 потоков/процессов
Решение 1: Асинхронный код
# ✅ Правильно — асинхронные операции
import asyncio
import aiohttp
from sqlalchemy.ext.asyncio import create_async_engine
async def handle_request(request):
async with aiohttp.ClientSession() as session:
async with session.get('https://api.example.com/data') as resp:
data = await resp.json() # Не блокирует
# Асинхронный запрос к БД
async with db_session() as session:
result = await session.execute(select(User))
return result
# 1000 одновременных запросов — один поток, one event loop
Решение 2: Кеширование
from functools import lru_cache
import time
class DataCache:
def __init__(self, ttl_seconds=60):
self.cache = {}
self.ttl = ttl_seconds
def get_data(self, key):
if key in self.cache:
value, timestamp = self.cache[key]
if time.time() - timestamp < self.ttl:
return value # Из кеша
# Если нет в кеше — вычислить
value = self._expensive_operation(key)
self.cache[key] = (value, time.time())
return value
def _expensive_operation(self, key):
# Дорогостоящая операция
return f"data_{key}"
# Redis кеширование (еще лучше)
import redis
redis_client = redis.Redis(host='localhost', port=6379)
def get_user_with_cache(user_id):
cache_key = f"user:{user_id}"
# Попытка получить из Redis
cached = redis_client.get(cache_key)
if cached:
return json.loads(cached)
# Если нет — получить из БД
user = database.get_user(user_id)
# Сохранить в Redis на 10 минут
redis_client.setex(cache_key, 600, json.dumps(user))
return user
Решение 3: Queue & Worker Pool
from celery import Celery
from kombu import Queue
app = Celery('myapp')
# Асинхронная очередь для тяжелых операций
@app.task(queue='background')
def process_heavy_task(data):
# Эта операция выполняется в отдельном worker'е
# Не блокирует основное приложение
return expensive_computation(data)
def handle_request(request):
# Просто добавляем в очередь
task = process_heavy_task.delay(request.data)
return {"status": "processing", "task_id": task.id}
# Worker конфигурация
app.conf.update(
broker_url='redis://localhost:6379',
result_backend='redis://localhost:6379',
worker_max_tasks_per_child=1000, # Перезагружать процесс каждые 1000 задач
worker_prefetch_multiplier=4, # Сколько задач захватить за раз
worker_concurrency=8, # Количество worker процессов
)
Решение 4: Database Query Optimization
from sqlalchemy import select, joinedload
from sqlalchemy.orm import Session
# ❌ N+1 problem — множество запросов
def get_users_bad():
users = session.query(User).all()
for user in users:
print(user.posts) # Отдельный запрос для каждого пользователя!
# ✅ Eager loading
def get_users_good():
users = session.query(User).options(
joinedload(User.posts)
).all()
# Один или два запроса максимум
for user in users:
print(user.posts)
# ✅ Индексы
# ALTER TABLE users ADD INDEX idx_email (email);
# CREATE INDEX idx_created_at ON orders(created_at DESC);
Решение 5: Connection Pooling
from sqlalchemy import create_engine
# Хорошая конфигурация
engine = create_engine(
'postgresql://user:password@localhost/db',
pool_size=20, # Базовый размер пула
max_overflow=40, # Максимум дополнительных соединений
pool_recycle=3600, # Переиспользовать соединение каждый час
pool_pre_ping=True, # Проверить соединение перед использованием
echo_pool=True, # Логировать статистику пула
)
4. Системный уровень: DevOps решения
# Увеличить лимиты файлов
ulimit -n 65536
# TCP оптимизация
sysctl -w net.ipv4.tcp_max_syn_backlog=4096
sysctl -w net.core.somaxconn=4096
sysctl -w net.ipv4.tcp_tw_reuse=1
# Kernel scheduler tuning
sysctl -w kernel.sched_migration_cost_ns=5000000
5. Стратегия скейлинга
# Горизонтальный скейлинг — несколько инстансов
# Load Balancer (nginx, HAProxy) распределяет трафик
# Вертикальный скейлинг — мощнее железо
# Гибридный подход:
# 1. Кеширование (Redis)
# 2. Асинхронность (asyncio, Celery)
# 3. Несколько worker'ов (4-8 процессов)
# 4. Несколько инстансов приложения
# 5. Load balancer (nginx)
Чеклист решения проблемы
- Диагностика: top, iostat, ps aux
- Определить тип нагрузки: CPU-bound vs I/O-bound
- Профилирование: cProfile, PyFlame для CPU
- Оптимизация:
- CPU: Асинхронность, multiprocessing
- I/O: Кеширование, Connection pooling, SQL optimization
- Масштабирование: Горизонтальное или вертикальное
- Мониторинг: Prometheus, Grafana, DataDog
Высокий Load Average редко решается одним решением — обычно нужна комбинация техник и постоянный мониторинг.