Почему микросервисы начинают использовать grpc

задняя часть Go

RPC

Что такое RPС-фреймворк?image.pngПроще говоря, когда служба A вызывает службу B, ей не нужно явно инициировать запрос http или tcp, достаточно вызвать локальную функцию, которая затем инициирует вызов через http или tcp, после чего возвращаются данные. . Для службы A не важно, как сетевые вызовы реализованы внутри функции, поэтому для реализации rpc-фреймворка требуется:

  1. Потому что есть много сервисов и функций. Служба A может вызвать f1 службы B, а также может вызвать f2 службы B. Как правило, функция соответствует идентификатору. Для функции, предоставляемой службой B, каждая функция должна быть уникальной. Идентификаторы могут быть числовой картой или строкой.
  2. Параметры, полученные func, должны быть переданы, что включает в себя сериализацию. Сериализация может передавать идентификатор и параметры вместе, либо json, либо xml.
  3. Сериализованные данные передаются по сети, которая может быть протоколом http или протоколом tcp.
  4. Служба B прослушивает сокет и получает пакет данных.
  5. Десериализовать в соответствии с заранее согласованной схемой сериализации.
  6. Десериализовать, получить идентификатор и параметры выполняемой функции и найти реальную выполняемую функцию с помощью сопоставления идентификаторов.
  7. Введите параметры в func и выполните.
  8. Результат сериализуется и возвращается по сети
  9. Сервис A анализирует данные таким же образом и получает результат.

Преимущество RPC заключается в том, что удаленный вызов инкапсулируется в локальный вызов, который скрывает детали связи внизу.Для разработчиков они сосредоточены только на вводе и выводе бизнес-функций, и им не нужно заботиться о том, как данные передается.

GRPC

Первоначально разработанная Google, gRPC является независимой от языка и платформы системой удаленного вызова процедур (RPC) с открытым исходным кодом. grpc — это просто специальная структура протокола rpc, производительность grpc выше, чем у обычного rpc.

  • http2.0
  • protobuf

Преимущества http2.0 заключаются в двоичном кадрировании, мультиплексировании, сжатии заголовков и отправке на сервер. Я не буду вдаваться в подробности здесь, пожалуйста, обратитесь к деталямПочему http2.0 такой быстрыйСтоимость передачи пакетов данных в сеть и из сети связана со стоимостью полосы пропускания. В методе сериализации grpc используется protobuf, который намного лучше, чем json и xml, недостатком которого является то, что его не так легко читать, как json. В эффективной полосе пропускания один и тот же пакет данных protobuf может передавать большее количество раз. И чем меньше данных, тем быстрее сериализация. protobuf является кроссплатформенным и не зависит от языка. Вы можете использовать инструмент proto для генерации кода на разных языках, что очень удобно.

  • json — это текстовый файл, а текстовые файлы основаны на символах.
  • protobuf имеет двоичную кодировку, основанную на значениях.

В чем разница между ними, например: для таких чисел, как 123, кодировка json занимает 3 байта, а для двоичного кодирования, поскольку 123 может быть представлено типом int8, оно занимает один байт. С точки зрения кодирования целых чисел и чисел с плавающей запятой, в большинстве случаев место, занимаемое json, больше, чем protobuf (1, 2 и т.д. каждый — 1 байт).
Приблизительная структура данных сообщения, сериализованного protobuf, выглядит следующим образом:

image.pngНаши параметры могут иметь filed1, field2 . Эти поля компактны, как k, v, разница в том, что некоторые требуют длины, повторяющиеся значения одного типа могут быть соединены между собой, а затем формировать весь поток данных сообщения.
Тогда для k, который является частью тега, его структура данных может быть такой:

image.png

  • number — это номер каждого поля, когда мы определяем proto
  • wire_type всегда занимает младшие 3 бита, которые могут представлять в общей сложности 8 чисел, каждое из которых представляет другой тип.

image.pngСм. пример:

image.png
1 из int64, как protobuf сжимает пространство:

  1. Во-первых, младшие 3 бита, 000, представляют 0, и если 0 равен 0, используйте кодировку varint.
  2. Результат после кодирования всего 8 бит - 1 байт

Int64 обычно занимает 8 байт для 64 бит, но здесь нужен только 1 байт.

varint

Процесс кодирования:

  1. Получите соответствующее дополнение
  2. Начиная с младшего бита кода дополнения, берутся каждые 7 бит и соединяются по очереди от старшего к младшему.
  3. Процесс объединения, если текущая позиция должна быть заполнена позже. Текущий старший бит заполняется 1, в противном случае он заполняется 0.

Возьмите 251 из int32 в качестве примера:

image.pngДополнением положительного числа является само, возьмите младшие 7 бит, если предположить, что это называется сегментом A.image.png
Т.к. впереди еще 1, то берем 7 бит, предположим, что он называется сегментом B, начинаем склейку, сегмент A находится перед сегментом B, а после сегмента A есть сегмент B, поэтому старший бит сегмента A дополняется на 1, а старший бит сегмента B дополняется 0. Итак, в итоге получается:

image.pngКонец варинтного кодирования, для которого изначально требовалось 4 байта памяти, теперь требует только 2 байта. Старший бит каждого байта не представляет сам себя, но указывает, есть ли за ним данные.
Процесс декодирования также обратный:image.pngСуществуют и недостатки вариантного кодирования. Например, для данных типа int32 каждый байт занимает один старший бит, поэтому он может представлять не более 2^28 чисел. байт. Однако чем больше число, тем меньше вероятность его появления.

zigzag

varint может иметь большую оптимизацию пространства для положительных чисел, но отрицательные числа контрпродуктивны, с -1 int32 в качестве столбца:
image.pngСтарший бит отрицательного числа всегда равен 1, что означает, что отрицательное число заполнит весь байт. Если используется кодировка varint:
Сначала возьмем дополнение (знаковый бит остается неизменным, остальные биты инвертируются, а в конце добавляется 1):image.pngЗатем для каждых 7 бит добавьте старший бит:
image.pngНаконец нашелся простой -1, и еще один байт через варинт-кодировку.

Чтобы объяснить, поскольку protobuf поддерживает много языков, в некоторых языках нет понятия int8 и int16, поэтому в protobuf нет int8 и int16.

Идея зигзага состоит в том, чтобы отображать, преобразовывать отрицательные числа в положительные числа, а затем кодировать положительные числа через варинт, чтобы уменьшить пространство.
Давайте сначала рассмотрим проблему 1+(-1) = -2:

image.pngСложение исходного кода 1 и исходного кода -1 на самом деле равно -2, что явно противоречит здравому смыслу, поэтому разработан дополнительный код Добавление дополнительного кода 1 и дополнительного кода - 1 равно 0. способ работы.
Давайте посмотрим на процесс кодирования -1 (int32):

  1. -1 дополнение int32 1111xxxx1111
  2. Сдвиг на один бит влево 1111xxxx1110
  3. Сдвиг вправо на 31 бит 1111xxxx1111
  4. Исключающее ИЛИ 0000xxxx 0001

image.png Таким образом, можно увидеть, что -1 преобразуется в 1, а затем сжимается с помощью varint, старший 0 удаляется, и, наконец, -1 из 4 байтов преобразуется в 1 из 1 байта.
Алгоритм кодека ядра Zigzag:

编码:(n << 1) ^ (n >> 31)
解码:(((unsignedint)n) >>1) ^ -(n & 1)