1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/akenzc-grpc

Клонировать/Скачать
PROTOCOL-HTTP2.md 26 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 28.05.2025 23:34 0b1547e

gRPC over HTTP2

Введение

Данный документ служит подробным описанием для реализации gRPC, передаваемой через обрамление HTTP2. Документ предполагает знакомство с спецификацией HTTP2.

Протокол

Правила производства используют синтаксис ABNF.

Описание

Вот общий последовательный поток атомов сообщений в потоке запросов и ответов gRPC:

  • Запрос → Заголовки-запроса *Длина-префиксированного-сообщения EOS
  • Ответ → (Заголовки-ответа *Длина-префиксированного-сообщения Хвостовые-заголовки) / Хвостовые-заголовки-только

Запросы

  • Запрос → Заголовки-запроса *Длина-префиксированного-сообщения EOSЗаголовки-запроса передаются в виде HTTP2 заголовков в HEADERS + CONTINUATION фреймах. * Заголовки-запроса → Определение-вызова *Пользовательские-метаданные
  • Определение-вызова → Метод Схема Путь TE [Авторитет] [Таймаут] Тип-содержимого [Тип-сообщения] [Кодировка-сообщения] [Принимаемая-кодировка-сообщения] [User-Agent]
  • Метод → ":method POST"
  • Схема → ":scheme " ("http" / "https")
  • Путь → ":path" "/" Имя-сервиса "/" {имя метода} # Но увидеть примечание ниже.
  • Имя-сервиса → {уникальное имя сервиса на языке IDL}
  • Авторитет → ":authority" {виртуальное имя хоста авторитета}
  • TE → "te" "trailers" # Используется для обнаружения несовместимых прокси
  • Таймаут → "grpc-timeout" Значение-таймаута Единица-таймаута
  • Значение-таймаута → {положительное целое число в виде ASCII-строки длиной не более 8 цифр}
  • Единица-таймаута → Час / Минута / Секунда / Миллисекунда / Микросекунда / Наносекунда
    • Час → "H"
    • Минута → "M"
    • Секунда → "S"
    • Миллисекунда → "m"
    • Микросекунда → "u"
    • Наносекунда → "n"
  • Тип-содержимого → "content-type" "application/grpc" [("+proto" / "+json" / {пользовательский})]
  • Кодировка-содержимого → "identity" / "gzip" / "deflate" / "snappy" / {пользовательский}
  • Кодировка-сообщения → "grpc-encoding" Кодировка-содержимого
  • Принимаемая-кодировка-сообщения → "grpc-accept-encoding" Кодировка-содержимого *("," Кодировка-содержимого)
  • User-Agent → "user-agent" {структурированная строка User-Agent}* Тип сообщения → "grpc-message-type" {имя типа для схемы сообщения}
  • Пользовательские метаданные → Бинарный заголовок / ASCII-заголовок
  • Бинарный заголовок → {Имя заголовка "-bin" } {базовая64-кодированное значение}
  • ASCII-заголовок → Имя заголовка ASCII-значение
  • Имя заголовка → 1*( %x30-39 / %x61-7A / "_" / "-" / ". ") ; 0-9 a-z _ - .
  • ASCII-значение → 1*( %x20-%x7E ) ; пробел и печатаемый ASCIIHTTP2 требует, чтобы зарезервированные заголовки, начинающиеся с двоеточия (":"), появлялись перед всеми другими заголовками. Кроме того, реализации должны отправлять Timeout сразу после зарезервированных заголовков и отправлять заголовки Call-Definition перед отправкой Custom-Metadata.Path чувствителен к регистру. Некоторые реализации gRPC могут позволять переопределять формат Path, показанный выше, но эта функциональность строго не рекомендуется. gRPC не предпринимает особых усилий, чтобы сломать пользователей, использующих эту форму переопределения, но мы не активно поддерживаем её, и некоторые функции (например, поддержка конфигурации сервиса) не будут работать, если Path не соответствует формату, показанному выше.

Если Timeout не указан, сервер должен предполагать бесконечное время ожидания. Реализации клиента могут отправлять по умолчанию минимальное время ожидания, основанное на требованиях их развертывания.

Если Content-Type не начинается с "application/grpc", gRPC-серверы ДОЛЖНЫ отвечать статусом HTTP 415 (Unsupported Media Type). Это предотвратит другие клиенты HTTP/2 от интерпретации ответа ошибки gRPC, который использует статус 200 (OK), как успешного.

Custom-Metadata представляет собой произвольное множество пар ключ-значение, определённое уровнем приложения. Заголовки, начинающиеся с "grpc-", но не перечисленные здесь, зарезервированы для будущего использования gRPC и не должны использоваться приложениями как Custom-Metadata.Обратите внимание, что HTTP/2 не позволяет произвольные последовательности октетов для значений заголовков, поэтому двоичные заголовки должны быть закодированы с помощью Base64 в соответствии с https://tools.ietf.org/html/rfc4648#section-4. Реализации ДОЛЖНЫ принимать закодированные и не закодированные значения и должны отправлять не закодированные значения. Приложения определяют двоичные заголовки тем, что их имена заканчиваются на "-bin". Библиотеки выполнения используют этот суффикс для обнаружения двоичных заголовков и правильного применения кодирования и декодирования Base64 при отправке и получении заголовков.Порядок заголовков Custom-Metadata не гарантируется, за исключением значений с дублирующими заголовками. Дублирующие заголовки могут иметь свои значения объединенными запятой (",") как разделитель и рассматриваться как семантически эквивалентные. Реализации должны разделять Binary-Headers на запятые перед декодированием закодированных значений Base64. Значение ASCII не должно содержать начальных или конечных пробелов. Если такие пробелы присутствуют, их можно удалить. Определенный диапазон символов для Значения ASCII строже, чем в HTTP. Реализации не должны выдавать ошибку при получении недопустимого Значения ASCII, которое является допустимым значением поля в HTTP, но точное поведение не строго определено: они могут игнорировать это значение или принимать его. Если значение принимается, необходимо убедиться, что приложение имеет разрешение повторно отобразить это значение как метаданные. Например, если метаданные предоставляются приложению в виде списка в запросе, приложение не должно вызывать ошибку, предоставив тот же список как метаданные в ответе. Серверы могут ограничивать размер Request-Headers, с рекомендацией по умолчанию 8 КБ.Реализации поощряются вычислять общий размер заголовков, как это делается в HTTP/2 для SETTINGS_MAX_HEADER_LIST_SIZE: сумма всех заголовков, для каждого поля сумма несжатых длины имени и значения заголовка плюс 32, с длиной бинарных значений после Base64.Повторяющаяся последовательность элементов Length-Prefixed-Message передается в DATA-фреймах.

  • Length-Prefixed-Message → Compressed-Flag Message-Length Message
  • Compressed-Flag → 0 / 1 # закодировано как 1-байтовое беззнаковое целое число
  • Message-Length → {длина Message} # закодировано как 4-байтовое беззнаковое целое число (big endian)
  • Message → *{бинарный октет}

Значение Compressed-Flag равное 1 указывает на то, что последовательность бинарных октетов Message сжата с использованием механизма, объявленного заголовком Message-Encoding. Значение 0 указывает на то, что сжатие Message не применялось. Контексты сжатия не сохраняются между границами сообщений, реализации должны создавать новый контекст для каждого сообщения в потоке. Если заголовок Message-Encoding отсутствует, то Compressed-Flag должен быть равен 0.

Для запросов EOS (end-of-stream) указывается наличием флага END_STREAM в последнем полученных DATA-фрейме. В ситуациях, когда поток Request должен быть закрыт, но больше данных отправлено не будет, реализации должны отправить пустой DATA-фрейм с этим флагом установленным.

Ответы* Response → (Response-Headers *Length-Prefixed-Message Trailers) / Trailers-Only

  • Response-Headers → HTTP-Status [Message-Encoding] [Message-Accept-Encoding] Content-Type *Custom-Metadata
  • Trailers-Only → HTTP-Status Content-Type Trailers
  • Trailers → Status [Status-Message] *Custom-Metadata
  • HTTP-Status → ":status 200"
  • Status → "grpc-status" 1*DIGIT ; 0-9
  • Status-Message → "grpc-message" Percent-Encoded
  • Percent-Encoded → 1*(Percent-Byte-Unencoded / Percent-Byte-Encoded)
  • Percent-Byte-Unencoded → 1*( %x20-%x24 / %x26-%x7E ) ; space and VCHAR, except %
  • Percent-Byte-Encoded → "%" 2HEXDIGIT ; 0-9 A-F

Заголовки-ответа и Трейлеры-только отправляются в отдельных блоках HTTP2 HEADERS. Большинство ответов должны содержать как заголовки, так и трейлеры, но Трейлеры-только допускаются для вызовов, которые приводят к немедленной ошибке. Статус должен отправляться в Трейлерах, даже если код состояния является OK. Для завершения потока используется флаг END_STREAM в последующем получаемом фрейме HEADERS, который содержит Трейлеры.Реализации должны ожидать, что в ответах могут поступать HTTP-статусы, отличные от 200, а также различные типы содержимого, отличные от GRPC, а также отсутствие Status и Status-Message. Реализации должны синтезировать Status и Status-Message для передачи на уровень приложения в случае возникновения таких ситуаций.

Клиенты могут ограничивать размер Response-Headers, Trailers и Trailers-Only с рекомендацией по умолчанию в 8 КБ для каждого.

Часть значения Status представляет собой десятичное число, закодированное в ASCII без ведущих нулей.

Часть значения Status-Message представляет собой концептуально Unicode-строку, описывающую ошибку, физически закодированную в UTF-8, за которым следует percent-encoding. Percent-encoding определен в RFC 3986 §2.1, хотя форма, используемая здесь, имеет другие ограниченные символы. При декодировании недействительных значений реализации не должны генерировать ошибки или игнорировать сообщение. В худшем случае реализация может прервать декодирование сообщения статуса, так что пользователь получит сырую percent-закодированную форму. В качестве альтернативы реализация может декодировать корректные части, оставляя поврежденные %-закодированные части без изменений или заменяя их символом замены (например, '?' или Unicode-символом замены).#### Пример

Пример одиночного вызова, показывающий последовательность фреймов HTTP2

Запрос

HEADERS (flags = END_HEADERS)
:method = POST
:scheme = http
:path = /google.pubsub.v2.PublisherService/CreateTopic
:authority = pubsub.googleapis.com
grpc-timeout = 1S
content-type = application/grpc+proto
grpc-encoding = gzip
authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v

DATA (flags = END_STREAM)
<Length-Prefixed Message>

Ответ

HEADERS (flags = END_HEADERS)
:status = 200
grpc-encoding = gzip
content-type = application/grpc+proto

DATA
<Length-Prefixed Message>

HEADERS (flags = END_STREAM, END_HEADERS)
grpc-status = 0 # OK
trace-proto-bin = jher831yy13JHy3hc

Пользовательские агенты

Хотя протокол не требует функционирования user-agent, рекомендуется, чтобы клиенты предоставляли структурированную строку user-agent, которая предоставляет базовое описание вызывающей библиотеки, версии и платформы для облегчения диагностики проблем в разнородных окружениях. Рекомендуемая структура для библиотекарей:

User-Agent → "grpc-" Language ?("-" Variant) "/" Version ?( " ("  *(AdditionalProperty ";") ")" )

Пример:

grpc-java/1.2.3
grpc-ruby/1.2.3
grpc-ruby-jruby/1.3.4
grpc-java-android/0.9.1 (gingerbread/1.2.4; nexus5; tmobile)

Идемпотентность и повторные попытки

Если явно не определено, gRPC вызовы не считаются идемпотентными. В частности:

  • Вызовы, которые не могут быть доказаны как начавшиеся, не будут повторены.
  • Нет механизма для подавления дубликатов, так как это не обязательно.
  • Вызовы, отмеченные как идемпотентные, могут быть отправлены несколько раз.#### Маппинг транспорта HTTP2
Идентификация потока

Все GRPC вызовы должны указывать внутренний ID. Мы будем использовать HTTP2 stream-ids как идентификаторы вызовов в этой схеме. ЗАМЕЧАНИЕ: Эти ID являются контекстными для открытой HTTP2 сессии и не будут уникальными в процессе, обрабатывающем более одной HTTP2 сессии, и не могут быть использованы как GUID.

Фреймы данных

Границы фреймов DATA не имеют отношения к границам Length-Prefixed-Message и реализации не должны делать предположений о их выравнивании.

Ошибки

Когда приложение или среда выполнения сталкиваются с ошибкой во время RPC, Status и Status-Message передаются в Trailers.

В некоторых случаях возможно, что форматирование потока сообщений стало повреждённым, и среда выполнения RPC выберет использовать фрейм RST_STREAM для указания этого состояния своему сопровождающему. Реализации среды выполнения RPC должны интерпретировать RST_STREAM как полное немедленное закрытие потока и должны передать ошибку в приложение-посыльное.Следующее отображение кодов ошибок RST_STREAM на коды ошибок GRPC применяется.

HTTP2 Код GRPC Код
NO_ERROR(0) INTERNAL - Ясное GRPC состояние OK должно было быть отправлено, но это может использоваться для агрессивного lameducking в некоторых сценариях.
PROTOCOL_ERROR(1) INTERNAL
INTERNAL_ERROR(2) INTERNAL
FLOW_CONTROL_ERROR(3) INTERNAL
SETTINGS_TIMEOUT(4) INTERNAL
STREAM_CLOSED Нет соответствия, так как открытого потока для распространения нет. Реализации должны регистрировать.
FRAME_SIZE_ERROR INTERNAL
REFUSED_STREAM UNAVAILABLE - Указывает, что обработка не происходила, и запрос может быть повторен, возможно, в другом месте.
CANCEL(8) Мапится на отмену вызова, когда отправлено клиентом. Мапится на CANCELLED, когда отправлено сервером. Обратите внимание, что серверы должны использовать этот механизм только в том случае, если им нужно отменить вызов, но последовательность байтов содержимого не завершена.
COMPRESSION_ERROR INTERNAL
CONNECT_ERROR INTERNAL
ENHANCE_YOUR_CALM RESOURCE_EXHAUSTED ... с дополнительными деталями ошибки, предоставленными средой выполнения, чтобы указать, что исчерпанный ресурс - это пропускная способность.
INADEQUATE_SECURITY PERMISSION_DENIED … с дополнительными деталями, указывающими, что разрешение было отказано, так как протокол недостаточно безопасен для вызова.
БезопасностьСпецификация HTTP2 требует использования TLS 1.2 или более поздней версии при использовании TLS с HTTP2. Она также устанавливает дополнительные ограничения на допустимые шифры в развертываниях для предотвращения известных проблем и требует поддержки SNI. Ожидается, что HTTP2 будет использоваться в сочетании с собственными транспортными механизмами безопасности, для которых спецификация не может сделать значимые рекомендации.
Управление соединениями
Фрейм GOAWAY

Отправляется сервером клиенту для указания, что сервер больше не будет принимать новые потоки на связанных соединениях. Этот фрейм включает идентификатор последнего успешно принятого потока сервером. Клиенты должны рассматривать любой поток, инициированный после последнего успешно принятого потока, как недоступный и повторно пытаться вызов в другом месте. Клиенты могут продолжать работать с уже принятыми потоками до тех пор, пока они не завершатся или соединение не будет завершено.

Серверы должны отправлять фрейм GOAWAY перед завершением соединения для надежного уведомления клиентов о том, какие работы были приняты сервером и выполняются.###### PING Frame Оба клиента и серверы могут отправлять PING frame, на который соответствующий узел должен ответить, точно повторяя то, что получил. Это используется для проверки, что соединение все еще активно, а также для оценки задержки от конца до конца. Если сервер, инициированный PING, не получит ответа в течение ожидаемого срока выполнения, все ожидающие вызовы на сервере будут закрыты со статусом CANCELLED. Устаревший клиент, инициированный PING, приведет к закрытию всех вызовов со статусом UNAVAILABLE. Обратите внимание, что частота PING зависит от сетевой среды, реализации могут корректировать частоту PING в зависимости от сетевых и прикладных требований.###### Сбой соединения Если обнаруживается сбой соединения на клиенте, все вызовы будут закрыты со статусом UNAVAILABLE. Для серверов открытые вызовы будут закрыты со статусом CANCELLED.

Приложение A - GRPC для Protobuf

Интерфейсы служб, объявленные в protobuf, легко отображаются на GRPC с помощью расширений генерации кода для protoc. Ниже приведено определение отображения, которое следует использовать.

  • Service-Name → {proto package name} "." {service name}
  • Message-Type → {fully qualified proto message name}
  • Content-Type → "application/grpc+proto"

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/akenzc-grpc.git
git@api.gitlife.ru:oschina-mirror/akenzc-grpc.git
oschina-mirror
akenzc-grpc
akenzc-grpc
master