RPC
Что такое RPС-фреймворк?Проще говоря, когда служба A вызывает службу B, ей не нужно явно инициировать запрос http или tcp, достаточно вызвать локальную функцию, которая затем инициирует вызов через http или tcp, после чего возвращаются данные. . Для службы A не важно, как сетевые вызовы реализованы внутри функции, поэтому для реализации rpc-фреймворка требуется:
- Потому что есть много сервисов и функций. Служба A может вызвать f1 службы B, а также может вызвать f2 службы B. Как правило, функция соответствует идентификатору. Для функции, предоставляемой службой B, каждая функция должна быть уникальной. Идентификаторы могут быть числовой картой или строкой.
- Параметры, полученные func, должны быть переданы, что включает в себя сериализацию. Сериализация может передавать идентификатор и параметры вместе, либо json, либо xml.
- Сериализованные данные передаются по сети, которая может быть протоколом http или протоколом tcp.
- Служба B прослушивает сокет и получает пакет данных.
- Десериализовать в соответствии с заранее согласованной схемой сериализации.
- Десериализовать, получить идентификатор и параметры выполняемой функции и найти реальную выполняемую функцию с помощью сопоставления идентификаторов.
- Введите параметры в func и выполните.
- Результат сериализуется и возвращается по сети
- Сервис 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, выглядит следующим образом:
Наши параметры могут иметь filed1, field2 . Эти поля компактны, как k, v, разница в том, что некоторые требуют длины, повторяющиеся значения одного типа могут быть соединены между собой, а затем формировать весь поток данных сообщения.
Тогда для k, который является частью тега, его структура данных может быть такой:
- number — это номер каждого поля, когда мы определяем proto
- wire_type всегда занимает младшие 3 бита, которые могут представлять в общей сложности 8 чисел, каждое из которых представляет другой тип.
См. пример:
1 из int64, как protobuf сжимает пространство:
- Во-первых, младшие 3 бита, 000, представляют 0, и если 0 равен 0, используйте кодировку varint.
- Результат после кодирования всего 8 бит - 1 байт
Int64 обычно занимает 8 байт для 64 бит, но здесь нужен только 1 байт.
varint
Процесс кодирования:
- Получите соответствующее дополнение
- Начиная с младшего бита кода дополнения, берутся каждые 7 бит и соединяются по очереди от старшего к младшему.
- Процесс объединения, если текущая позиция должна быть заполнена позже. Текущий старший бит заполняется 1, в противном случае он заполняется 0.
Возьмите 251 из int32 в качестве примера:
Дополнением положительного числа является само, возьмите младшие 7 бит, если предположить, что это называется сегментом A.
Т.к. впереди еще 1, то берем 7 бит, предположим, что он называется сегментом B, начинаем склейку, сегмент A находится перед сегментом B, а после сегмента A есть сегмент B, поэтому старший бит сегмента A дополняется на 1, а старший бит сегмента B дополняется 0. Итак, в итоге получается:
Конец варинтного кодирования, для которого изначально требовалось 4 байта памяти, теперь требует только 2 байта. Старший бит каждого байта не представляет сам себя, но указывает, есть ли за ним данные.
Процесс декодирования также обратный:Существуют и недостатки вариантного кодирования. Например, для данных типа int32 каждый байт занимает один старший бит, поэтому он может представлять не более 2^28 чисел. байт. Однако чем больше число, тем меньше вероятность его появления.
zigzag
varint может иметь большую оптимизацию пространства для положительных чисел, но отрицательные числа контрпродуктивны, с -1 int32 в качестве столбца:
Старший бит отрицательного числа всегда равен 1, что означает, что отрицательное число заполнит весь байт. Если используется кодировка varint:
Сначала возьмем дополнение (знаковый бит остается неизменным, остальные биты инвертируются, а в конце добавляется 1):Затем для каждых 7 бит добавьте старший бит:
Наконец нашелся простой -1, и еще один байт через варинт-кодировку.
Чтобы объяснить, поскольку protobuf поддерживает много языков, в некоторых языках нет понятия int8 и int16, поэтому в protobuf нет int8 и int16.
Идея зигзага состоит в том, чтобы отображать, преобразовывать отрицательные числа в положительные числа, а затем кодировать положительные числа через варинт, чтобы уменьшить пространство.
Давайте сначала рассмотрим проблему 1+(-1) = -2:
Сложение исходного кода 1 и исходного кода -1 на самом деле равно -2, что явно противоречит здравому смыслу, поэтому разработан дополнительный код Добавление дополнительного кода 1 и дополнительного кода - 1 равно 0. способ работы.
Давайте посмотрим на процесс кодирования -1 (int32):
- -1 дополнение int32 1111xxxx1111
- Сдвиг на один бит влево 1111xxxx1110
- Сдвиг вправо на 31 бит 1111xxxx1111
- Исключающее ИЛИ 0000xxxx 0001
Таким образом, можно увидеть, что -1 преобразуется в 1, а затем сжимается с помощью varint, старший 0 удаляется, и, наконец, -1 из 4 байтов преобразуется в 1 из 1 байта.
Алгоритм кодека ядра Zigzag:
编码:(n << 1) ^ (n >> 31)
解码:(((unsignedint)n) >>1) ^ -(n & 1)