В этом посте я собираюсь привести расширенный пример по теме, которая довольно популярна в наши дни: gRPC.
gRPC - это современный высокопроизводительный RPC-фреймворк с открытым исходным кодом, который может работать в любой среде. Он может эффективно соединять службы внутри и между центрами обработки данных с подключаемой поддержкой балансировки нагрузки, трассировки, проверки работоспособности и аутентификации. Это также применимо на последней миле распределенных вычислений для подключения устройств, мобильных приложений и браузеров к серверным службам. Grpc.io
gRPC также отлично подходит для использования в качестве протокола связи между микросервисами, написанными на разных языках программирования.
О gRPC можно сказать гораздо больше, однако я Я не буду вдаваться в подробности, так как предполагаю, что вы уже знакомы с ним. Если вы не знакомы с этим, вот отличная статья, в которой это подробно объясняется.
Когда я начал работать над gRPC, я быстро понял, что на самом деле он поставляется со встроенным механизмом сериализации и десериализации под названием Protobuf (буферы протокола). Буферы протокола - это не зависящий от языка и платформы, расширяемый механизм Google для сериализации структурированных данных - подумайте об XML, но меньше, быстрее и проще. Вы определяете, как вы хотите, чтобы ваши данные были структурированы один раз, а затем вы можете использовать специальный сгенерированный исходный код, чтобы легко записывать и считывать структурированные данные в различные потоки данных и из них, используя множество языков. Однако, если у вас нет определенного типа сообщения, вы почувствуете необходимость отключить сериализацию и десериализацию Protobuf. Давайте посмотрим, как это сделать в Go:
Следующий main.proto описывает службу Main, которая использует двунаправленную потоковую передачу Удаленный вызов процедур и передает необработанные данные. байты в качестве типа сообщения.
syntax = “proto3”; package rpc; service Main { rpc RPC (stream Payload) returns (stream Payload) {} } message Payload { bytes Data = 1; }
После создания прото-файла нам нужно сгенерировать исходный код для сервера и клиента, используя этот файл:
protoc -I main/ main.proto — go_out=plugins=grpc:main
Эта команда сгенерирует необходимый исходный код, который будет использоваться в вашем проекте. Следующим шагом является создание структуры Payload, которая будет передавать сообщение между парами сервер-клиент.
package rpc // Payload defines the service message format. type Payload struct { data []byte } // NewPayload creates and returns a new payload with the given byte slice. func NewPayload(d []byte) *Payload { p := new(Payload) if d != nil { p.Set(d) } return p } // Set sets the payload func (p *Payload) Set(d []byte) { p.data = d } // Get returns the payload func (p *Payload) Get() []byte { return p.data }
Теперь мы подошли к моменту, когда нам нужно добавить собственный кодек в библиотеку gRPC, чтобы он не пытался сериализовать и десериализовать байты, которые мы отправляем по сети. Основная причина этого - ускорить обмен данными, поскольку мы не знаем размер потока между сервером gRPC и клиентом.