БЕСПЛАТНАЯ ПОДГОТОВКА К ЕГЭ ПО ПРОФИЛЬНОЙ МАТЕМАТИКЕ
Подготовься к ЕГЭ-2026 по профильной математике самостоятельно с помощью сервиса "1С:Репетитор"!
Понятная теория и эффективные тренажеры с объяснением! Вы успеете подготовиться к экзамену! Начните занятия прямо сейчас!
design_arrow
Серверное программирование

Серверное программирование

Сервер – это длительно работающий процесс, который принимает запросы от клиентов по сети, обрабатывает их согласно протоколу и возвращает ответы, поддерживая инварианты корректности (безопасность, согласованность состояния) и целевые показатели качества (пропускная способность, задержка, доступность).

Ключевая интуиция: сервер – это детерминированный автомат с внешними входами (пакеты/сокеты), очередями, исполнительными стадиями (CPU/IO) и выходами (ответы). На практике он разложим на слои: транспорт (TCP/UDP), мультиплексирование соединений, разбор протокола, бизнес-логика, доступ к данным, кэширование и логирование.

Связь с ЕГЭ: тема развивает навыки формализации алгоритмов, понимание протоколов, работы с очередями, оценок сложности и проектирования корректных реактивных систем – компетенции, регулярно встречающиеся в задачах по алгоритмам, теории информации и моделированию вычислений.

Формальная модель сервера и инварианты

Пусть множество клиентов C = {c1, …, cm} генерирует запросы req. Сервер – это машина состояний с очередью Q и обработчиком H.

  1. Абстракция очереди и обработчика

    • Очередь запросов: Q = (req_1, …, req_k).

    • Обработчик: функция H: req → resp error.

    • Политика обслуживания: обычно FIFO; допускаются приоритеты.

    Инварианты корректности:

    • I1 (безопасность): для любого req обработчик выполняет предусловия протокола (аутентификация, формат).

    • I2 (прогресс): корректный req со временем покидает очередь (отсутствует «вечное голодание»).

    • I3 (изоляция): конкурентная обработка не нарушает целостность общих ресурсов (блокировки/транзакции).

  2. Оценки производительности (элементы теории очередей)

    Пусть интенсивность входа λ (запросов/сек), среднее время обслуживания E[S]. Для одноканального сервера со стабильностью ρ = λ·E[S] < 1:

    Пропускная способность ≈ λ

    Среднее число в системе L ≈ ρ / (1 − ρ)      (приближённо для M/M/1)

    Средняя задержка W ≈ L / λ                   (закон Литтла)

    Вывод: уменьшение E[S] и параллельная обработка снижают задержку и повышают пропускную способность.

Сетевой стек и сокеты: IP, TCP, UDP

  1.  Слои взаимодействия

    • IP – доставка дейтаграмм без гарантии.

    • TCP – потоковый надёжный транспорт: порядок, контроль перегрузки, повторные передачи.

    • UDP – дейтаграммный, без установления соединения: минимальные накладные расходы, нет гарантии доставки.

    Правило TNET

    T1  Для транзакционных протоколов, требующих порядок и надёжность, используйте TCP.

    T2  Для телеметрии/стриминга с допуском потерь и жёсткой задержкой допустим UDP + свой контроль.

    T3  Всегда указывайте таймауты, размеры буферов и политику повторов.

  2. Сокетная модель

    Серверный TCP-сокет: socket() → bind() → listen() → цикл accept() → обработка соединений.
    UDP-сокет: socket() → bind() → цикл recvfrom()/sendto() без состояния соединения.

Протоколы прикладного уровня: HTTP, RPC и сериализация

  1. HTTP (упрощённо)

    • Запрос: старт-строка METHOD URI VERSION, заголовки, опциональное тело.

    • Ответ: статус-строка VERSION CODE REASON, заголовки, тело.

    • Статусы: 2xx (успех), 3xx (перенаправление), 4xx (ошибка клиента), 5xx (ошибка сервера).

    Инвариант H-HTTP: ответы кодируют чёткий результат и не раскрывают лишние сведения (минимизируйте детали ошибок).

  2. RPC и сериализация

    • RPC: удалённый вызов процедур (JSON-RPC, gRPC).

    • Сериализация: JSON (текстовый, гибкий), Protobuf/Avro (бинарные, компактные, схемы).
      Правило SER

    S1  Фиксируйте схему и версионирование сообщений.

    S2  Разделяйте поля «обязательные»/«опциональные».

    S3  Валидируйте вход до бизнес-логики.

Конкурентность: процессы, потоки, событийные циклы, async

  1. Модели

    • Process-per-connection: просто, дорого по ресурсам.

    • Thread-per-connection: легче, но риски блокировок; нужен пул потоков.

    • Событийный цикл + неблокирующие сокеты (epoll/kqueue/IOCP): высокая масштабируемость, сложнее логика.

    • Async/await: синтаксическая поддержка событийной модели.

    Правило CONC

    C1  Если обработка I/O-интенсивна и кратка – событийная модель или async.

    C2  Если много CPU-логики – пул потоков + чёткие критические секции.

    C3  Не блокируйте event-loop (никаких длинных CPU/блокирующих вызовов).

  2.  Синхронизация и состояние

    • Разделяемое состояние → мьютексы/чтение-запись/атомики.

    • Безопасная очередь для передачи задач между потоками.

    • Copy-on-write и иммутабельные структуры для уменьшения блокировок.

Доступ к данным: кэш, БД, транзакции

  1. Кэширование

    Политики: write-through, write-back, write-around. Инвалидация по времени (TTL), по событиям, по версиям.

  2. Транзакционная целостность

    ACID для реляционных БД; eventual consistency для распределённых хранилищ.
    Правило DATA

    D1  Определите инварианты предметной области (балансы, лимиты).

    D2  Выберите уровень изоляции (Read Committed/Repeatable Read/Serializable) или компенсирующие транзакции (Saga).

    D3  Логируйте критические операции с idempotency-key.

Производительность и масштабирование

  1. Временная модель ответа

    T_resq ≈ T_net_in + T_parse + T_app + T_db + T_cache + T_net_out

    Оптимизация – уменьшать доминирующие слагаемые (профилирование).

  2. Масштабирование

    • Вертикальное: больше CPU/ОЗУ.

    • Горизонтальное: балансировщики (L4/L7), несколько экземпляров сервера.

    • Back-pressure: ограничение параллелизма, очереди, «честные» таймауты.

    Правило SCALE

    SC1  Ограничьте #одновременных запросов (семофоры/пулы).

    SC2  Включите таймауты и отмену (cancellation) на всех вызовах.

    SC3  Внедрите circuit breaker и retry с экспоненциальной паузой + джиттер.

Информатика–схема серверного программирования

Надёжность, ошибки и наблюдаемость

  1. Идиомы обработки ошибок

    • Исключения → коды на границе протокола (не отдавайте stacktrace).

    • Idempotency: повтор запроса не меняет состояние (для безопасных методов).

    • Компенсации: обратные действия при частичной неудаче.

  2. Наблюдаемость

    • Логи (структурированные): корреляционные идентификаторы, уровни.

    • Метрики: RPS, P50/P95/P99 задержек, ошибки по классам.

    • Трейсинг: распределённые трассы запросов (span, trace-id).

Безопасность серверов: от границы до ядра

Правило SECURE

B1  Валидация входа (длины, типы, формат); лимит размера тела.

B2  Аутентификация и авторизация; принцип наименьших привилегий.

B3  Шифрование транспорта (TLS); обновляйте сертификаты.

B4  Защита от DoS: rate-limit, quotas, защита очередей.

B5  Защита от инъекций: параметризованные запросы, экранирование.

B6  Безопасное хранение секретов (не в коде).

B7  Обновления/патчи и минимизация attack surface.

Мини-шпаргалка 

TCP-сервер (псевдокод):

sock = socket()

bind(sock, addr)

listen(sock, backlog)

while True:

    conn = accept(sock)       # неблокирующее + epoll предпочтительно

    schedule(handle(conn))    # пул потоков или event-loop

Идиома «два таймаута»:

client_timeout = read_timeout + write_timeout 

Экспоненциальный retry с джиттером:

delay = base * 2^k + U(0, jitter)

Бюджет задержки (SLO):

T_net_in + T_parse + T_app + T_db + T_net_out ≤ T_budget

Типичные ошибки и анти-паттерны

  1. Блокировка event-loop долгими синхронными операциями.

  2. Отсутствие таймаутов/отмены → зависания.

  3. Безразмерные очереди → всплеск памяти и лавинообразные таймауты.

  4. Логи без корреляционных id → неразборчивые инциденты.

  5. Неверная обработка частичных ошибок (часть батча записалась, часть нет).

  6. Выдача внутренних деталей (стектрейсы, версии БД) клиенту.

  7. Отсутствие лимитов на вход (размер JSON, число полей).

Связь с ЕГЭ по информатике

  • Алгоритмизация и структуры данных: очереди, стек вызовов, конкурентный доступ.

  • Теория информации и кодирование: протоколы, сериализация, валидация.

  • Моделирование систем: оценка пропускной способности, законы очередей.

  • Безопасность: базовые принципы защитного программирования и верификация входных данных.

Пять упражнений

Упражнение 1. Однопоточный TCP-эха-сервер (модель и корректность)

a) Опишите конечный автомат сервера: состояния Listening, Connected, Closing.
b) Докажите инвариант: сервер возвращает ровно те байты, которые принял (без добавлений/потерь).
c) Оцените верхнюю границу пропускной способности, если среднее время обработки одного пакета S=0.5 ms, а приход λ=1200 req/s. Выполнимо ли ρ<1?
Подсказка: ρ = λ·S. Переведите S в секунды.

Упражнение 2. Событийный сервер и неблокирующий ввод-вывод

Дан набор одновременно открытых 10 000 соединений с редкими сообщениями.
a) Обоснуйте выбор событийной модели (epoll) против «поток на соединение».
b) Сформулируйте инвариант event-loop: «ни один обработчик не держит цикл дольше Δ миллисекунд».
c) Предложите схему разделения: парсинг в event-loop, бизнес-логика в пуле.

Упражнение 3. Идемпотентность и повторные запросы

Сервер принимает POST /transfer (денежный перевод).
a) Покажите, как введение Idempotency-Key гарантирует отсутствие двойного списания при повторах.
b) Напишите псевдокод проверки ключа и записи результата в таблицу операций.
c) Докажите, что при политике «первый успешный результат закрепляется» сервер сохраняет инвариант баланса.

Упражнение 4. Бюджет задержки и ретраи

Клиент ожидает ответ не более T_budget = 200 ms. Средние задержки: T_net_in=15 ms, T_parse=5 ms, T_app=60 ms, T_db=80 ms, T_net_out=10 ms.
a) Выполнится ли SLO?
b) Какую часть архитектуры оптимизировать в первую очередь? Обоснуйте (правило узкого места).
c) Предложите политику retry (число попыток, пауза, джиттер), не превышающую бюджет.

Упражнение 5. Ограничение нагрузки (rate-limit)

Требуется ограничить клиента до R = 100 запросов в 60 секунд.
a) Опишите алгоритм «скользящее окно» или «ведро с токенами».
b) Приведите формулы пополнения токенов: 
tokens(t) = min(B, tokens(t0) + (t − t0) * R / 60)
где B – размер ведра.
c) Докажите, что при корректной реализации число принятых запросов за любой интервал 60 секунд не превысит R.

Развёрнутые правила проектирования (чек-лист)

ARCH  Разделяйте приёмо-передачу, парсинг, бизнес-логику, доступ к данным.

TIME  Ставьте таймауты и дедлайны на каждом слое; поддерживайте отмену.

POOL  Ограничивайте параллелизм пулами; планируйте CPU-профильные задачи отдельно.

IO    Предпочитайте неблокирующий I/O для большого числа соединений.

STATE Держите общее состояние минимальным; используйте иммутабельные структуры.

CACHE Кэшируйте горячие ответы; определяйте стратегии инвалидации.

OBS   Логируйте структурировано; метрики P50/P95/P99 и ошибки по классам.

SAFE  Валидация входа, TLS, принцип наименьших привилегий, защита от DoS.

DEP   Автоматизируйте деплой, health-checks, грациозное завершение (graceful shutdown).

TEST  Покройте протокол unit-тестами и тестами совместимости; фейлинъ-инъекции.

Заключение

Серверное программирование – это дисциплина реактивных систем, где строгость протоколов и инвариантов сочетается с инженерной практикой конкурентности, управлением ресурсами и безопасностью. Формализуя модель очередей и задержек, выбирая подходящую транспортную и прикладную семантику, вы строите предсказуемые и масштабируемые сервисы.

Для ЕГЭ по информатике эта тема усиливает ключевые навыки: строгую алгоритмизацию, оценку сложности, работу с очередями и инвариантами, а также внимательное обращение с данными и протоколами. От корректной валидации входа до проектирования бюджета задержки – все эти приёмы формируют базу, необходимую для уверенного решения задач и последующего профессионального роста.