Real-Time Backend

JSON vs Binary протоколы

Discord в 2020 году передавал 100+ млн сообщений в день через WebSocket Gateway. JSON парсинг занимал значимую долю CPU на gateway серверах. Переход сначала на Erlang ETF (бинарный), затем на Protobuf дал 40% снижение трафика и заметное снижение CPU. Один инженерный выбор - формат сериализации - изменил cost structure инфраструктуры.

  • **gRPC (Google, Cloud)** - Protobuf как стандарт для всех внутренних RPC; автогенерация клиентов для 10+ языков
  • **MessagePack в Redis** - встроенная сериализация для RESP3 бинарных расширений
  • **Apache Kafka** - Schema Registry + Avro/Protobuf для типобезопасной эволюции сообщений

JSON при масштабе: когда парсинг становится узким местом

Discord переключился с JSON на Protobuf и получил 40% снижение трафика. При 100 тысячах сообщений в секунду парсинг JSON начинает доминировать в CPU профиле. Причины: JSON текстовый (числа как строки), имена полей повторяются в каждом сообщении, нет схемы - тип поля нужно угадывать из значения.

ХарактеристикаJSONMessagePackProtobuf
РазмерBaseline~30% меньше~60-80% меньше
Скорость парсинга1x2-5x быстрее5-10x быстрее
СхемаНетНетОбязательна (.proto)
Human-readableДаНетНет
Backward compatМануальноМануальноВстроена (field numbers)

Почему JSON неэффективен при высоком трафике (100k+ сообщений/сек)?

MessagePack: бинарный JSON-совместимый формат

MessagePack - бинарная сериализация с той же моделью данных что и JSON: строки, числа, массивы, объекты, null, bool. Нет схемы - имена ключей хранятся в каждом сообщении (как JSON). Главный выигрыш: числа хранятся в бинарном виде, строки - без escape, структура кодируется типовыми байтами.

**Когда MessagePack:** когда нужна бинарная эффективность JSON без изменения архитектуры. Работает как drop-in замена JSON в WebSocket протоколах. Особенно эффективен для числовых данных и коротких строк. Не даёт преимуществ схемы - нет backward compatibility гарантий.

Главное отличие MessagePack от Protobuf:

Protocol Buffers: schema-first с backward compatibility

Protocol Buffers (Protobuf) - Google's бинарный формат с обязательной схемой в `.proto` файле. Компилятор `protoc` генерирует typed код для 10+ языков. Ключевое: каждое поле имеет **field number** вместо имени - это обеспечивает forward и backward compatibility.

Что обеспечивает backward compatibility в Protobuf при добавлении нового поля?

Критерии выбора формата: JSON, MessagePack или Protobuf

Выбор формата - это trade-off между простотой разработки, производительностью и совместимостью. Нет универсального ответа - контекст определяет всё.

СценарийРекомендацияПричина
REST API, внешние партнёрыJSONHuman-readable, инструменты everywhere, нет нужды в скорости
WebSocket, 10-100k msg/sMessagePackDrop-in замена JSON, ~30% экономия без схемы
gRPC, внутренние микросервисыProtobufТипобезопасность, codegen, 60-80% компактнее
IoT устройства, ограниченный каналProtobuf или CBORМинимальный размер, схема для экономии байт
Debugging, loggingJSONЧитаемость важнее размера

**Гибридный подход:** внешний API - JSON (партнёры, SDK, браузеры), внутренние сервисы - Protobuf/gRPC. Это позволяет сохранить developer experience на внешней границе и производительность внутри.

Protobuf всегда лучше JSON - нужно везде переходить на Protobuf.

Protobuf требует схему, codegen и DevEx overhead. Для внешних API, debugging и малого трафика JSON предпочтителен. Protobuf выигрывает при высоком трафике и строгих требованиях к типам между сервисами.

Выбор формата - engineering trade-off. Developer experience, tooling и совместимость часто важнее нескольких процентов CPU при малом трафике.

Новый WebSocket сервис обменивается 50k сообщений/сек с браузерными клиентами. JSON тормозит, но нет времени писать .proto схемы. Что выбрать?

JSON vs Binary протоколы

  • **JSON при масштабе:** имена полей повторяются, числа как строки, текстовый парсинг - CPU bottleneck от 10k+ msg/s
  • **MessagePack:** бинарный JSON без схемы; drop-in замена; ~30% компактнее, 2-5x быстрее парсинг
  • **Protobuf:** schema-first (.proto); field numbers = backward compatibility; 60-80% компактнее, 5-10x быстрее; codegen для 10+ языков
  • **Выбор:** JSON для внешних API и debugging; MessagePack как быстрая замена JSON; Protobuf для высоконагруженных внутренних сервисов и gRPC

Связанные темы

Выбор формата сериализации - часть общей архитектуры real-time систем.

  • WebSocket протокол — MessagePack и Protobuf часто используются поверх WebSocket для бинарных фреймов
  • gRPC и streaming — gRPC использует Protobuf как транспортный формат с двунаправленным streaming

Вопросы для размышления

  • Почему backward compatibility в Protobuf основана на field numbers, а не именах полей - и что это означает при рефакторинге схемы?
  • В каком сценарии MessagePack не даёт значимого преимущества над JSON, несмотря на бинарный формат?
  • Как выбор формата сериализации влияет на observability системы - логирование, distributed tracing, debugging в production?

Связанные уроки

  • rt-07 — First real-time app is built with JSON; knowing what you're optimizing away from matters
  • rt-05 — WebSocket carries binary frames natively; protocol knowledge anchors the serialization choice
  • rt-09 — Socket.IO uses both JSON and binary - this lesson explains what's happening under the hood
  • rt-11 — uWebSockets.js is the performance runtime where binary protocols pay off most
  • net-54-rpc
JSON vs Binary протоколы

0

1

Войти