Перейти к содержимому

Лекция 4. Прикладные протоколы и форматы данных

Введение

В предыдущих лекциях мы рассмотрели сетевые основы интернет-приложений и базовый протокол прикладного уровня — HTTP. Однако современный backend редко ограничивается «голым» HTTP. Данные нужно передавать защищённо, иногда — в реальном времени, между сервисами — быстро и типобезопасно. А ещё их нужно во что-то упаковать: в JSON, XML, HTML или бинарный формат.

В этой лекции мы разберём:

  • HTTPS и TLS — зачем нужно шифрование и как устроено защищённое соединение (обзорно);
  • WebSocket — протокол двусторонней связи для приложений реального времени;
  • gRPC — высокопроизводительный RPC поверх HTTP/2 и Protobuf (обзорно);
  • форматы данных — JSON (основной для API), XML, HTML и другие;
  • сериализацию и десериализацию — как объект превращается в байты и обратно;
  • сетевую безопасность — основные угрозы и защита (кратко);
  • оптимизацию — кеширование и сжатие (кратко).

Цель — научиться осознанно выбирать протокол и формат под конкретную задачу.


1. HTTPS и TLS

1.1. Зачем нужно шифрование

Обычный HTTP передаёт данные открытым текстом. Любой узел на пути между клиентом и сервером (Wi-Fi-точка, провайдер, прокси) может прочитать или изменить трафик. Это недопустимо для паролей, токенов, платёжных данных и персональной информации.

HTTPS (HTTP Secure) решает проблему: это тот же HTTP, но передаваемый внутри защищённого канала, который создаёт протокол TLS (Transport Layer Security). TLS — преемник устаревшего SSL; сегодня актуальны версии TLS 1.2 и TLS 1.3.

HTTPS обеспечивает три гарантии безопасности:

  • Конфиденциальность — данные зашифрованы, посторонний видит лишь поток случайных байтов.
  • Целостность — попытка изменить данные «на лету» будет обнаружена.
  • Аутентификация — клиент убеждается, что общается с настоящим сервером, а не с подменным (через сертификат).

1.2. TLS-рукопожатие (обзорно)

Прежде чем передать первый байт HTTP, клиент и сервер выполняют TLS handshake — согласование параметров защищённого соединения. Упрощённо:

  1. ClientHello — клиент сообщает поддерживаемые версии TLS и наборы шифров (cipher suites).
  2. ServerHello + сертификат — сервер выбирает параметры и присылает свой TLS-сертификат, выпущенный удостоверяющим центром (CA). Клиент проверяет, что сертификат подлинный и выдан именно для этого домена.
  3. Обмен ключами — стороны с помощью асимметричной криптографии безопасно договариваются об общем секретном ключе.
  4. Готово — дальше весь HTTP-трафик шифруется быстрым симметричным алгоритмом (например, AES) этим общим ключом.

Ключевая идея: асимметричное шифрование (медленное) используется только для безопасного обмена ключом, а основной обмен данными идёт симметричным шифрованием (быстрым). В TLS 1.3 рукопожатие ускорено и требует меньше «кругов» по сети.

Для разработчика backend важно понимать: HTTPS — это стандарт де-факто. Современные браузеры помечают сайты без HTTPS как небезопасные, а многие возможности (Service Workers, геолокация) доступны только по HTTPS. На продакшене TLS обычно «терминируется» на reverse-proxy (nginx) или балансировщике.


2. WebSocket

2.1. Проблема: HTTP однонаправлен

HTTP построен на модели «запрос — ответ»: инициатором всегда выступает клиент, сервер только отвечает. Сервер не может сам «толкнуть» данные клиенту. Для чатов, уведомлений и биржевых котировок это неудобно — раньше приходилось применять костыли вроде постоянного опроса (polling) сервера.

WebSocket — протокол полнодуплексной (двусторонней) связи поверх одного TCP-соединения. После установки соединения и клиент, и сервер могут отправлять сообщения в любой момент.

2.2. Как устанавливается соединение

WebSocket «вырастает» из обычного HTTP-запроса:

  1. HTTP Upgrade — клиент отправляет запрос с заголовком Upgrade: websocket.
  2. Handshake — сервер отвечает кодом 101 Switching Protocols, подтверждая переключение протокола.
  3. Обмен фреймами — соединение остаётся открытым, стороны обмениваются сообщениями (фреймами) с минимальными накладными расходами.
GET /ws HTTP/1.1
Host: chat.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

2.3. Когда нужен WebSocket

Применяйте WebSocket, когда данные должны приходить от сервера по инициативе сервера и в реальном времени:

  • чаты и мессенджеры;
  • онлайн-игры;
  • биржевые котировки и торговые терминалы;
  • совместное редактирование документов;
  • дашборды мониторинга и live-уведомления.

Если же клиент просто запрашивает данные время от времени — достаточно обычного HTTP. Не используйте WebSocket там, где хватает «запрос — ответ»: постоянное соединение расходует ресурсы сервера. FastAPI поддерживает WebSocket «из коробки» через декоратор @app.websocket(...).


3. gRPC

3.1. Идея RPC

RPC (Remote Procedure Call, удалённый вызов процедур) — подход, при котором вызов функции на другом сервере выглядит для программиста почти как вызов обычной локальной функции. Детали сети скрыты.

gRPC — современный RPC-фреймворк от Google. Его три кита:

  • HTTP/2 как транспорт — мультиплексирование нескольких вызовов в одном соединении, сжатие заголовков, потоковая передача.
  • Protocol Buffers (Protobuf) — компактный бинарный формат сериализации и язык описания интерфейсов (IDL).
  • Генерация кода — по описанию .proto автоматически создаётся клиентский и серверный код для многих языков.

3.2. Описание сервиса

Контракт сервиса описывается в .proto-файле:

syntax = "proto3";
service UserService {
rpc GetUser (UserRequest) returns (User);
}
message UserRequest {
int32 id = 1;
}
message User {
int32 id = 1;
string name = 2;
string email = 3;
}

Из этого файла генерируются типобезопасные клиент и сервер. Числа (= 1, = 2) — это теги полей, обеспечивающие совместимость версий.

3.3. Типы вызовов и применение

gRPC поддерживает четыре вида взаимодействия:

  • Unary — один запрос, один ответ (как обычный вызов функции);
  • Server streaming — один запрос, поток ответов;
  • Client streaming — поток запросов, один ответ;
  • Bidirectional streaming — потоки в обе стороны.

Где применяют: связь между микросервисами внутри инфраструктуры, системы реального времени, IoT. gRPC быстрее и компактнее REST/JSON за счёт бинарного формата, но менее удобен для отладки (бинарь не прочитать глазами) и хуже работает напрямую из браузера. Поэтому типичный выбор: REST/JSON наружу (для публичного API и фронтенда) и gRPC внутри (между сервисами).


4. Форматы данных

Данные, которыми обмениваются клиент и сервер, нужно представить в виде, понятном обеим сторонам. Выбор формата влияет на читаемость, размер, скорость обработки и совместимость.

4.1. JSON — основной формат API

JSON (JavaScript Object Notation) — лёгкий текстовый формат, сегодня это стандарт де-факто для REST API.

{
"id": 123,
"name": "John Doe",
"age": 30,
"isActive": true,
"address": {
"city": "New York",
"zipCode": "10001"
},
"hobbies": ["reading", "coding"],
"spouse": null
}

Поддерживаемые типы данных:

  • string — строка в двойных кавычках;
  • number — целое или вещественное число;
  • booleantrue / false;
  • null — отсутствие значения;
  • object — набор пар «ключ — значение» в { };
  • array — упорядоченный список в [ ].

Достоинства: читается человеком, компактнее XML, быстро парсится, поддерживается всеми языками, нативен для JavaScript.

Ограничения: нет комментариев, нет встроенных типов для дат и бинарных данных (дату передают строкой в формате ISO 8601), нет встроенной схемы. Для описания структуры используют JSON Schema; в FastAPI это решается через модели Pydantic, которые валидируют входящий JSON автоматически.

4.2. XML

XML (eXtensible Markup Language) — расширяемый язык разметки. Те же данные:

<?xml version="1.0" encoding="UTF-8"?>
<user id="123">
<name>John Doe</name>
<age>30</age>
<address>
<city>New York</city>
<zipCode>10001</zipCode>
</address>
<hobbies>
<hobby>reading</hobby>
<hobby>coding</hobby>
</hobbies>
</user>

Особенности: строгая валидация по схемам (DTD, XSD), пространства имён, мощные языки запросов (XPath, XQuery), атрибуты у элементов. Минусы: многословность, больший объём, медленнее парсится. XML по-прежнему встречается в корпоративных системах (протокол SOAP), форматах RSS/Atom и конфигурационных файлах, но в новых веб-API почти вытеснен JSON.

4.3. HTML

HTML (HyperText Markup Language) — язык разметки для представления страниц в браузере. В отличие от JSON и XML, он предназначен не для обмена данными между программами, а для отображения контента человеку.

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Страница</title>
</head>
<body>
<h1>Заголовок</h1>
<p>Текст параграфа</p>
</body>
</html>

Backend может либо отдавать готовый HTML (рендеринг на сервере, например через шаблонизатор Jinja2), либо отдавать JSON, а HTML формировать на стороне клиента (SPA). В современном HTML5 важны семантические теги (<header>, <nav>, <main>, <article>, <footer>), делающие структуру понятной.

4.4. Другие форматы (кратко)

  • YAML — человекочитаемый формат для конфигов и CI/CD (отступы вместо скобок). Удобен людям, но чувствителен к форматированию.
  • Protocol Buffers — бинарный типизированный формат от Google, основа gRPC. Компактнее и быстрее JSON, но не читается глазами.
  • MessagePack — бинарный «JSON в сжатом виде» для высоконагруженных систем.
  • Мультимедиа — изображения (JPEG, PNG, SVG, WebP), видео (MP4, WebM), аудио (MP3, AAC, Opus). Передаются как бинарные данные с соответствующим Content-Type.

4.5. Сравнение форматов

КритерийJSONXMLProtobuf
Представлениетексттекстбинарь
Читаемость для человекавысокаясредняянет
Размерсреднийбольшойминимальный
Скорость обработкивысокаянизкаяочень высокая
Схема/валидациявнешняя (JSON Schema)встроенная (XSD)встроенная (.proto)
Типичное применениеREST APIкорпоративные системы, SOAPgRPC, микросервисы

5. Сериализация и десериализация

В памяти программы данные хранятся как объекты (например, экземпляр класса User в Python). Чтобы передать их по сети, нужно превратить объект в последовательность байтов — это сериализация (или маршалинг). Обратный процесс на принимающей стороне — десериализация: из байтов восстанавливается объект.

Объект в памяти --сериализация--> байты (JSON/XML/Protobuf) --сеть-->
<--десериализация-- байты <--

Простой пример на Python со стандартным JSON:

import json
user = {"id": 123, "name": "John", "is_active": True}
# Сериализация: объект -> строка JSON
text = json.dumps(user) # '{"id": 123, "name": "John", "is_active": true}'
# Десериализация: строка JSON -> объект
obj = json.loads(text) # {'id': 123, 'name': 'John', 'is_active': True}

В FastAPI сериализация и десериализация в основном выполняются автоматически: входящий JSON-запрос разбирается и валидируется в модель Pydantic, а возвращаемый объект сериализуется обратно в JSON. Это снимает с разработчика рутину и снижает число ошибок.

Важно помнить о соответствии типов: например, дату в JSON передают строкой, а при десериализации преобразуют обратно в объект даты. Несогласованность форматов — частый источник ошибок интеграции.


6. Сетевая безопасность (кратко)

Безопасность — обязательная часть проектирования backend. Рассмотрим основные категории угроз и защиту от них.

6.1. Основные угрозы

  • Перехват трафика (sniffing) — пассивное прослушивание сети, кража паролей и токенов. Защита: шифрование (TLS/HTTPS).
  • Подмена данных и Man-in-the-Middle — злоумышленник встраивается между сторонами, изменяет трафик или выдаёт себя за сервер. Защита: TLS-сертификаты, цифровые подписи, проверка целостности.
  • DoS / DDoS — перегрузка сервера лавиной запросов до отказа в обслуживании. Защита: ограничение частоты запросов (rate limiting), балансировка, фильтрация трафика, CDN.

6.2. Практические меры

  • HTTPS везде — базовая мера; заголовок Strict-Transport-Security принуждает браузер всегда использовать HTTPS.
  • Заголовки безопасностиContent-Security-Policy (защита от внедрения скриптов), X-Frame-Options (защита от clickjacking), X-Content-Type-Options: nosniff.
  • Аутентификация и авторизацияJWT (самодостаточные подписанные токены), OAuth 2.0 (делегированный доступ), OpenID Connect (стандартная аутентификация поверх OAuth).
  • Валидация входных данных — никогда не доверять данным от клиента; проверять и очищать всё, что приходит снаружи (в FastAPI помогает Pydantic).

7. Оптимизация (кратко)

Быстрый отклик напрямую влияет на пользовательский опыт. Две самые доступные техники — кеширование и сжатие.

7.1. Кеширование

Кеширование избавляет от повторного выполнения дорогих операций и повторной передачи неизменившихся данных.

  • На клиенте — браузерный кеш, локальное хранилище.
  • На сервере и в сети — CDN (географически распределённые серверы отдают статику ближе к пользователю), reverse-proxy, кеш на уровне приложения (например, Redis).
  • Управление через заголовки HTTP:
Cache-Control: public, max-age=3600
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

Заголовки ETag и Last-Modified позволяют клиенту сделать условный запрос: если ресурс не изменился, сервер отвечает 304 Not Modified с пустым телом, экономя трафик.

7.2. Сжатие

Текстовые данные (HTML, JSON, CSS, JS) хорошо сжимаются перед передачей:

  • Gzip — повсеместно поддерживается, экономит до ~70 % объёма;
  • Brotli — современный алгоритм, сжимает текст ещё эффективнее.

Клиент сообщает поддержку заголовком Accept-Encoding: gzip, br, сервер отвечает Content-Encoding: gzip. Сжатие обычно настраивается на reverse-proxy и почти не требует усилий со стороны разработчика, давая заметный выигрыш.

Современные версии протокола (HTTP/2 и HTTP/3) сами по себе ускоряют обмен за счёт мультиплексирования потоков и сжатия заголовков.


8. Сравнение протоколов

КритерийHTTPWebSocketgRPC
Модель связизапрос — ответполный дуплексRPC (вызов процедур)
Инициаторклиентобе стороныклиент (есть стриминг)
ТранспортTCP (HTTP/1.1, /2)TCPHTTP/2
Формат данныхлюбой (обычно JSON)любойProtobuf (бинарь)
Реальное времянетдачастично (стриминг)
Читаемостьвысокаязависитнизкая (бинарь)
Типичное применениеREST API, вебчаты, liveсвязь микросервисов

Краткие итоги

  • HTTPS = HTTP внутри TLS. Шифрование даёт конфиденциальность, целостность и аутентификацию сервера. Рукопожатие согласует параметры: асимметричная криптография — для обмена ключом, симметричная — для основного трафика. HTTPS сегодня обязателен.
  • WebSocket — двусторонняя связь поверх одного TCP-соединения, устанавливается через HTTP Upgrade (101 Switching Protocols). Нужен для реального времени: чаты, котировки, уведомления. Где хватает «запрос — ответ» — он избыточен.
  • gRPC — RPC поверх HTTP/2 с бинарным Protobuf и генерацией кода. Быстр и типобезопасен, удобен между микросервисами; снаружи обычно остаётся REST/JSON.
  • Форматы: JSON — основной для API (читаемый, универсальный); XML — корпоративные системы; HTML — отображение для человека; Protobuf/MessagePack — бинарные для производительности.
  • Сериализация/десериализация превращает объект в байты и обратно; в FastAPI это делает Pydantic.
  • Безопасность: угрозы перехвата, подмены и отказа в обслуживании; защита — TLS, заголовки безопасности, JWT/OAuth, валидация ввода.
  • Оптимизация: кеширование (заголовки, CDN, 304 Not Modified) и сжатие (gzip/Brotli) дают быстрый отклик малой ценой.

Вопросы для самопроверки

  1. Чем HTTPS отличается от HTTP и какие три гарантии безопасности он обеспечивает?
  2. Зачем в TLS используется и асимметричное, и симметричное шифрование? Какую роль играет каждое?
  3. В чём принципиальное отличие WebSocket от модели «запрос — ответ» HTTP? Приведите два примера задач, где он нужен.
  4. Каким HTTP-кодом сервер подтверждает переход на WebSocket?
  5. На каких трёх технологиях основан gRPC? Почему его обычно используют между сервисами, а не наружу?
  6. Перечислите типы данных JSON. Как в JSON принято передавать дату и почему?
  7. Сравните JSON и XML по читаемости, размеру и применению.
  8. Что такое сериализация и десериализация? Какой инструмент выполняет их в FastAPI?
  9. Назовите три основные категории сетевых угроз и способ защиты от каждой.
  10. Как кеширование и сжатие ускоряют работу приложения? Что означает ответ 304 Not Modified?