Ответ
Protobuf (Protocol Buffers) — это бинарный формат сериализации данных от Google. Он эффективен по скорости и размеру данных, что делает его отличным выбором для межсервисного взаимодействия.
Основные способы организации обмена:
-
gRPC (рекомендуемый способ)
gRPC — это фреймворк для удалённого вызова процедур (RPC), который использует Protobuf по умолчанию. Это нативный и наиболее эффективный способ.
- Как работает: Вы описываете сервисы и сообщения в
.protoфайлах. Генератор кода создаёт клиентские и серверные заготовки на Go. - Преимущества: Строгая типизация, высокая производительность, поддержка стриминга, автоматическая сериализация/десериализация.
// Пример запуска gRPC сервера import ( "google.golang.org/grpc" "net" pb "path/to/your/proto/package" ) func main() { lis, err := net.Listen("tcp", ":50051") // ... обработка ошибки s := grpc.NewServer() pb.RegisterYourServiceServer(s, &myServer{}) s.Serve(lis) } - Как работает: Вы описываете сервисы и сообщения в
-
HTTP + Protobuf (бинарный)
Можно передавать бинарные Protobuf-сообщения через обычный HTTP. Это быстрее, чем JSON, но требует от клиентов умения работать с бинарным форматом.
- Как работает: Сервер и клиент договариваются об использовании
Content-Type: application/protobuf. - Сериализация:
data, err := proto.Marshal(myMessage) - Десериализация:
err := proto.Unmarshal(bodyBytes, myMessage)
- Как работает: Сервер и клиент договариваются об использовании
-
HTTP + JSON (для совместимости)
Для взаимодействия с браузерами или системами, которые работают только с JSON, Protobuf-сообщения можно конвертировать в JSON и обратно. Для этого используется специальный пакет
protojson.import "google.golang.org/protobuf/encoding/protojson" // Сериализация в JSON jsonBytes, err := protojson.Marshal(myMessage) // Десериализация из JSON err = protojson.Unmarshal(jsonBytes, myMessage)
Управление .proto файлами
Ключевая задача — обеспечить использование одних и тех же версий .proto файлов во всех микросервисах. Лучшая практика — вынести их в отдельный Git-репозиторий и подключать его к проектам микросервисов через Git-сабмодули или использовать системы управления зависимостями, такие как Buf.
Лучшие практики:
- Версионирование: Включайте версию API в имя пакета Protobuf (например,
package myapi.v1;). - Обратная совместимость: При изменении
.protoфайлов не удаляйте поля и не меняйте их номера, чтобы сохранить обратную совместимость. - Интерцепторы (Interceptors) в gRPC: Используйте их для сквозной функциональности: логирования, сбора метрик, аутентификации.
Ответ 18+ 🔞
А, ну вот, протоколы, сериализация... Ёперный театр, опять эти ваши бинарные форматы! Ну ладно, слушай сюда, раз уж спросил.
Protobuf, блядь, — это такая штука от Гугла, которая данные твои в бинарный вид упаковывает. Быстро, компактно, прям как чемодан у бабки в автобусе — всё впихнули, ничего не торчит. Идеально, чтобы сервисы между собой болтали, не тратя время на ерунду.
Как этим добром обмениваться? Вариантов — овердохуища!
-
gRPC (самый правильный путь, без вариантов)
Это типа как RPC, только на стероидах. Всё из коробки, по уму. Ты описываешь в
.proto-файле, что у тебя за сервис и какие у него сообщения, а потом магическим кодогенератором на Go всё это превращается в готовые заглушки. Красота, блядь!- Что хорошего: Типы проверяются, летает всё как угорелое, стриминг поддерживает, и тебе даже думать не надо, как это сериализовать — всё само.
// Ну вот, смотри, как сервер gRPC поднять import ( "google.golang.org/grpc" "net" pb "path/to/your/proto/package" ) func main() { lis, err := net.Listen("tcp", ":50051") // ... ошибку обработай, конечно, а то пиздец будет s := grpc.NewServer() pb.RegisterYourServiceServer(s, &myServer{}) s.Serve(lis) // И поехали! }
- Что хорошего: Типы проверяются, летает всё как угорелое, стриминг поддерживает, и тебе даже думать не надо, как это сериализовать — всё само.
-
HTTP, но с бинарным Protobuf (для любителей поизвращаться)
Можно и просто по HTTP гонять эти бинарные сообщения. Быстрее JSON, конечно, но клиент должен быть не лыком шит и понимать, что ему в ответ прилетает не текст, а какая-то бинарная каша.
- Как: Договариваешься с клиентом, что
Content-Typeбудетapplication/protobuf. Всё, дальше магия: - Упаковать:
data, err := proto.Marshal(myMessage) - Распаковать:
err := proto.Unmarshal(bodyBytes, myMessage)
- Как: Договариваешься с клиентом, что
-
HTTP + JSON (для тех, у кого всё через жопу)
Ну а если твой клиент — это какой-нибудь древний браузер или система, которая только JSON и жуёт? Без паники! Можно конвертнуть Protobuf в JSON. Для этого есть специальная либа
protojson. Но это уже не та скорость, конечно.import "google.golang.org/protobuf/encoding/protojson" // В JSON jsonBytes, err := protojson.Marshal(myMessage) // Из JSON обратно err = protojson.Unmarshal(jsonBytes, myMessage)
А теперь про самое важное — .proto файлы!
Вот тут, блядь, собака порылась. Главная задача — чтобы во всех твоих микросервисах была одна и та же хуйня в этих файлах. Идеальный вариант — выкинуть их в отдельный репозиторий Git и таскать оттуда, как зависимость. Через сабмодули или, что ещё лучше, через специальные инструменты вроде Buf. Иначе будет бардак, волнение ебать, и все друг друга перестанут понимать.
Чтобы не было пиздеца, запомни:
- Версии — в пакет! Пиши в названии пакета версию:
package myapi.v1;. Потом, когда всё сломаешь, будетmyapi.v2. - Не ломай старое! Меняешь
.protoфайл — не удаляй старые поля и не меняй им номера. Иначе твой старый сервис посмотрит на новое сообщение и просто охуеет. - Перехватчики (Interceptors) в gRPC — твои друзья. Через них удобно логирование, метрики или проверку прав впиливать. Один раз написал — работает везде. Удобно, блядь!
Вот и вся наука. Главное — не выёбывайся и используй gRPC, где можно. А то нагородишь HTTP-эндпоинтов с JSON, а потом будешь разбираться, почему всё тормозит.