Данный документ представляет собой подробное описание реализации gRPC, передаваемой через HTTP2 фрейминг. Предполагается знакомство с спецификацией HTTP2.
Производственные правила используют синтаксис ABNF.
Следующее является общей последовательностью атомов сообщений в потоке запросов и ответов gRPC
Request-Headers передаются как HTTP2 заголовки в фреймах HEADERS + CONTINUATION.
HTTP2 требует, чтобы зарезервированные заголовки, начинающиеся с ":", появлялись перед всеми другими заголовками. Кроме того, реализации должны отправлять Timeout сразу после зарезервированных заголовков, а также отправлять заголовки Call-Definition перед отправкой Custom-Metadata.
Path чувствителен к регистру. Некоторые реализации gRPC могут позволять переопределять формат Path, показанный выше, но эта функциональность настоятельно не рекомендуется. gRPC не стремится нарушать работу пользователей, использующих этот вид переопределения, но мы не активно поддерживаем его, и некоторые функции (например, поддержка конфигурации службы) не будут работать, если путь не имеет указанного выше формата.
Если Timeout опущен, сервер должен предполагать бесконечный тайм-аут. Реализации клиентов свободны отправлять минимальный тайм-аут по умолчанию на основе своих требований к развертыванию.
Если Content-Type не начинается с "application/grpc", gRPC серверы ДОЛЖНЫ отвечать HTTP статусом 415 (Unsupported Media Type). Это предотвратит другие клиенты HTTP/2 от интерпретации ошибочного ответа gRPC, который использует статус 200 (OK), как успешный.
Custom-Metadata — это произвольный набор пар ключ-значение, определенных на уровне приложения. Имена заголовков, начинающиеся с "grpc-", но не перечисленные здесь, зарезервированы для будущего использования gRPC и не должны использоваться приложениями как Custom-Metadata.
Обратите внимание, что HTTP2 не позволяет использовать произвольные последовательности октетов для значений заголовков, поэтому бинарные значения заголовков должны быть закодированы с использованием Base64 согласно https://tools.ietf.org/html/rfc4648#section-4. Реализации ДОЛЖНЫ принимать как заполненные, так и незаполненные значения и должны отправлять незаполненные значения. Приложения определяют бинарные заголовки, добавляя суффикс "-bin" к их именам. Библиотеки времени выполнения используют этот суффикс для обнаружения бинарных заголовков и правильно применяют кодирование и декодирование base64 при отправке и получении заголовков.
Порядок заголовков Custom-Metadata не гарантируется сохранением, за исключением значений с одинаковыми именами заголовков. Значения с одинаковыми именами заголовков могут быть объединены с использованием "," в качестве разделителя и считаться семантически эквивалентными. Реализации должны разделять Binary-Header на "," перед декодированием значений, закодированных в base64.
Значения ASCII-Value не должны иметь начальных или конечных пробелов. Если они содержат начальные или конечные пробелы, они могут быть удалены. Определенный диапазон символов для ASCII-Value строже, чем в HTTP. Реализации не должны выдавать ошибку при получении недействительного ASCII-Value, который является допустимым field-value в HTTP, но точное поведение не строго определено: они могут игнорировать значение или принять его. Если значение принято, следует убедиться, что приложение разрешено эхом отвечать этим значением как метаданными. Например, если метаданные предоставляются приложению в виде списка в запросе, приложение не должно вызывать ошибку, предоставляя тот же список как метаданные в ответе.
Серверы могут ограничивать размер Request-Headers, с рекомендуемым значением по умолчанию 8 КБ. Реализации рекомендуют вычислять общий размер заголовков аналогично HTTP/2's SETTINGS_MAX_HEADER_LIST_SIZE
: сумма всех полей заголовков, для каждого поля сумма длины незакодированного имени поля и значения плюс 32, с учетом длины бинарных значений после кодирования base64.
Повторяющаяся последовательность элементов Length-Prefixed-Message передается в фреймах DATA
Значение Compressed-Flag равное 1 указывает на то, что последовательность бинарных октетов Message сжата с использованием механизма, объявленного в заголовке Message-Encoding. Значение 0 указывает на то, что кодирование байтов Message не происходило. Контексты сжатия НЕ сохраняются между границами сообщений, реализации должны создавать новый контекст для каждого сообщения в потоке. Если заголовок Message-Encoding опущен, то значение Compressed-Flag должно быть 0.
Для запросов конец потока (EOS) указывается наличием флага END_STREAM на последнем полученном фрейме DATA. В сценариях, где поток запроса нужно закрыть, но данных для отправки больше нет, реализации ДОЛЖНЫ отправить пустой фрейм DATA с этим флагом установленным.
Response-Headers и Trailers-Only передаются в одном блоке фреймов HTTP2 HEADERS. Большинство ответов ожидается будут иметь как заголовки, так и трейлеры, но разрешены и только трейлеры для вызовов, которые вызывают немедленную ошибку. Статус должен быть отправлен в трейлерах даже если код статуса — OK.
Для ответов конец потока указывается наличием флага END_STREAM на последнем полученном фрейме HEADERS, который содержит трейлеры.
Реализации должны ожидать неработающие развертывания, которые отправляют HTTP статусы отличные от 200 в ответах, а также различные недопустимые типы контента и отсутствие Status и Status-Message. Реализации ДОЛЖНЫ синтезировать Status и Status-Message, чтобы передать их на уровень приложения при возникновении таких ситуаций.
Клиенты могут ограничивать размер Response-Headers, Trailers, и Trailers-Only, с рекомендуемым значением по умолчанию 8 КБ каждый.
Значение части Status — это десятичное целое число в виде ASCII строки без ведущих нулей.
Значение части Status-Message концептуально является строковым описанием ошибки Unicode, физически закодированной как UTF-8 с последующим процентным кодированием. Процентное кодирование определено в RFC 3986 §2.1, хотя форма, используемая здесь, имеет другие ограниченные символы. При декодировании недействительных значений реализации НЕ ДОЛЖНЫ выдавать ошибку или игнорировать сообщение. В худшем случае реализация может полностью прекратить декодирование статусного сообщения таким образом, что пользователь получит исходную форму процентного кодирования. Альтернативно, реализация может декодировать действительные части, оставляя сломанные %-кодировки без изменений или заменяя их символом замены (например, '?' или символ замены Unicode).
Status-Details допускается только если Status не равен OK. Если он установлен, он содержит дополнительную информацию об ошибке RPC. Если он содержит поле кода статуса, оно НЕ ДОЛЖНО противоречить заголовку Status. Потребитель ДОЛЖЕН проверить это требование.
Пример унарного вызова с показом последовательности фреймов 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 вызовы не считаются идемпотентными. Конкретно:
Все вызовы gRPC должны указывать внутренний ID. Мы будем использовать HTTP2 stream-id как идентификаторы вызовов в этой схеме. ПРИМЕЧАНИЕ: Эти ID контекстуальны открытой сессии HTTP2 и не будут уникальными в рамках процесса, обрабатывающего более одной сессии HTTP2; их также нельзя использовать как GUIDs.
Границы фреймов DATA не связаны с границами Length-Prefixed-Message, и реализации не должны делать предположений о их совпадении.
Когда во время RPC происходит ошибка приложения или среды выполнения, статус и сообщение статуса передаются в трейлерах.
В некоторых случаях возможно, что фрейминг потока сообщений был поврежден, и среда выполнения RPC выберет использование фрейма RST_STREAM, чтобы указать это состояние своему собеседнику. Реализации сред выполнения RPC должны интерпретировать RST_STREAM как немедленное полное закрытие потока и должны передавать ошибку на уровень вызывающего приложения.
Применяется следующее соответствие кодов ошибок RST_STREAM кодам ошибок gRPC.
HTTP2 Code | GRPC Code |
---|---|
NO_ERROR(0) | INTERNAL - Явный статус GRPC OK должен был быть отправлен, но это может использоваться для агрессивного lameduck в некоторых сценариях. |
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 в сочетании с проприетарными механизмами транспортной безопасности о которых спецификация не может сделать осмысленных рекомендаций.
Отправляется серверами клиентам для указания на то, что они больше не будут принимать новые потоки на связанных соединениях. Этот фрейм включает ID последнего успешно принятого потока сервером. Клиенты должны рассматривать любой поток, инициированный после последнего успешно принятого потока как UNAVAILABLE и повторять вызов в другом месте. Клиенты свободны продолжать работу с уже принятыми потоками до их завершения или завершения соединения.
Серверы должны отправлять GOAWAY перед завершением соединения для надежного информирования клиентов о том, какая работа была принята сервером и выполняется.
И клиенты, и серверы могут отправлять фрейм PING, на который собеседник должен ответить точным эхом того, что получил. Это используется для утверждения того, что соединение все еще активно, а также для предоставления средства оценки конечной задержки. Если серверный PING не получает ответа в пределах времени ожидания среды выполнения все активные вызовы на сервере будут закрыты со статусом CANCELLED. Истекший клиентский PING приведет к закрытию всех вызовов со статусом UNAVAILABLE. Обратите внимание, что частота PING сильно зависит от сетевой среды; реализации свободны регулировать частоту PING на основе сетевых и прикладных требований.
Если на клиенте обнаруживается сбой соединения все вызовы будут закрыты со статусом UNAVAILABLE. Для серверов открытые вызовы будут закрыты со статусом CANCELLED.
Служебные интерфейсы, объявленные protobuf легко мапятся на gRPC с помощью расширений генерации кода для protoc. Следующее определяет маппинг для использования.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )