Поделиться через


Транскодирование JSON gRPC в ASP.NET Core

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 9 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 9 этой статьи.

Внимание

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

В текущем выпуске см . версию .NET 9 этой статьи.

Автор: Джеймс Ньютон-Кинг (James Newton-King)

gRPC — это высокопроизводительная платформа удаленного вызова процедур (RPC). gRPC использует HTTP/2, потоковую передачу, Protobuf и контракты сообщений для создания высокопроизводительных служб в реальном времени.

Одним из ограничений gRPC является то, что не каждая платформа может использовать ее. Браузеры не полностью поддерживают HTTP/2, поэтому API REST и JSON являются основными способами для передачи данных в браузерные приложения. Несмотря на преимущества, которые gRPC приносит, REST API и JSON имеют важное место в современных приложениях. Создание веб-API gRPC и JSON добавляет нежелательные затраты на разработку приложений.

В этом документе рассматривается создание веб-API JSON с помощью служб gRPC.

Обзор

Перекодирование gRPC JSON — это расширение для ASP.NET Core, которое создает API JSON RESTful для служб gRPC. Настроенное перекодирование позволяет приложениям вызывать службы gRPC, используя следующие привычные понятия HTTP:

  • HTTP-команды
  • привязку параметра URL-адреса;
  • запросы и ответы JSON.

gRPC по-прежнему можно использовать для вызова служб.

Примечание.

Транскодирование JSON gRPC заменяет API HTTP gRPC, альтернативное экспериментальное расширение.

Использование

  1. Добавьте ссылку на пакет для Microsoft.AspNetCore.Grpc.JsonTranscoding.

  2. Зарегистрируйте перекодирование в коде запуска сервера, добавив AddJsonTranscoding: в Program.cs файле изменится builder.Services.AddGrpc(); на builder.Services.AddGrpc().AddJsonTranscoding();.

  3. Добавьте <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos> в группу свойств в файле проекта (.csproj):

    <Project Sdk="Microsoft.NET.Sdk.Web">
    
      <PropertyGroup>
        <TargetFramework>net8.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
        <InvariantGlobalization>true</InvariantGlobalization>
        <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos>
      </PropertyGroup>
    
  4. Заметьте методы gRPC в .proto файлах с привязками и маршрутами HTTP:

    syntax = "proto3";
    
    option csharp_namespace = "GrpcServiceTranscoding";
    import "google/api/annotations.proto";
    
    package greet;
    
    // The greeting service definition.
    service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {
        option (google.api.http) = {
          get: "/v1/greeter/{name}"
        };
      }
    }
    
    // The request message containing the user's name.
    message HelloRequest {
      string name = 1;
    }
    
    // The response message containing the greetings.
    message HelloReply {
      string message = 1;
    }
    

Теперь метод SayHello gRPC можно вызывать как gRPC и веб-API JSON:

  • Запрос: GET /v1/greeter/world
  • Ответ: { "message": "Hello world" }

Если сервер настроен на запись журналов для каждого запроса, журналы сервера показывают, что служба gRPC выполняет http-вызов. Перекодирование сопоставляет входящий HTTP-запрос с сообщением gRPC и преобразует ответное сообщение в JSON.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
      Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.996ms 200 application/json

Аннотировать методы gRPC

Методы gRPC должны быть аннотированы с помощью правила HTTP, прежде чем они поддерживают перекодирование. Правило HTTP содержит сведения о том, как вызвать метод gRPC, например метод HTTP и маршрут.

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

Пример процедуры:

  • Определяет Greeter службу с методом SayHello . Метод имеет правило HTTP, указанное с помощью имени google.api.http.
  • Метод доступен с запросами GET и маршрутом /v1/greeter/{name} .
  • name Поле сообщения запроса привязано к параметру маршрута.

Многие варианты доступны для настройки привязки метода gRPC к API RESTful. Дополнительные сведения о аннотации методов gRPC и настройке JSON см. в разделе "Настройка HTTP и JSON для транскодирования JSON gRPC".

Методы потоковой передачи

Традиционный API gRPC по HTTP/2 поддерживает потоковую передачу во всех направлениях. Перекодирование предназначено только для серверной потоковой передачи. Методы клиентской и двунаправленной потоковой передачи не поддерживаются.

Методы потоковой передачи сервера используют json с разделителями строк. Каждое сообщение, написанное с помощью WriteAsync , сериализуется в ФОРМАТЕ JSON и следует новая строка.

Следующий метод серверной потоковой передачи записывает три сообщения:

public override async Task StreamingFromServer(ExampleRequest request,
    IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
    for (var i = 1; i <= 3; i++)
    {
        await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}

Клиент получает три объекта JSON с разделителями строк:

{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}

Обратите внимание, что WriteIndented параметр JSON не применяется к методам потоковой передачи сервера. Красивая печать добавляет новые строки и пробелы в JSON, которые нельзя использовать с разделителями строк JSON.

Просмотр или скачивание примера приложения ASP.NET Core gPRC для перекодирования и потоковой передачи.

Протокол HTTP

Шаблон службы ASP.NET Core gRPC, включенный в пакет SDK для .NET, создает приложение, настроенное только для HTTP/2. HTTP/2 является хорошим по умолчанию, если приложение поддерживает только традиционные gRPC по протоколу HTTP/2. Однако перекодирование работает как с HTTP/1.1, так и с HTTP/2. Некоторые платформы, например UWP или Unity, не могут использовать HTTP/2. Чтобы обеспечить поддержку всех клиентских приложений, настройте сервер для включения HTTP/1.1 и HTTP/2.

Обновите протокол умолчанию в файле appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Как вариант, вы можете настроить конечные точки Kestrel в коде запуска.

Чтобы включить HTTP/1.1 и HTTP/2 на одном порте, требуется TLS для согласования протокола. Дополнительные сведения о настройке протоколов HTTP в приложении gRPC см. в разделе Согласование протокола gRPC в ASP.NET Core.

Транскодирование json gRPC и gRPC-Web

Как перекодирование, так и gRPC-Web позволяют вызывать службы gRPC из браузера. Однако способы, которыми они это делают, отличаются.

  • gRPC-Web позволяет браузерным приложениям вызывать службы gRPC из браузера с помощью клиента gRPC-Web и Protobuf. gRPC-Web требует, чтобы приложение браузера создало клиент gRPC и имеет преимущество отправки небольших, быстрых сообщений Protobuf.
  • Транскодирование позволяет приложениям браузера вызывать службы gRPC, как если бы они были API RESTful с JSON. Браузерному приложению не нужно создавать клиент gRPC и не нужно ничего знать о gRPC.

Предыдущую службу Greeter можно вызывать с помощью API JavaScript браузера:

var name = nameInput.value;

fetch('/v1/greeter/' + name)
  .then((response) => response.json())
  .then((result) => {
    console.log(result.message);
    // Hello world
  });

grpc-gateway

grpc-gateway — еще одна технология создания API RESTful JSON из служб gRPC. В нем используются те же .proto заметки для сопоставления концепций HTTP с службами gRPC.

grpc-gateway использует генерирование кода для создания обратного прокси-сервера. Обратный прокси-сервер преобразует вызовы RESTful в gRPC+Protobuf и отправляет вызовы по протоколу HTTP/2 в службу gRPC. Преимущество этого подхода заключается в том, что служба gRPC не знает об API JSON RESTful. Любой сервер gRPC может использовать grpc-gateway.

Между тем перекодирование JSON gRPC выполняется в приложении ASP.NET Core. При этом JSON десериализируется в сообщения Protobuf, а затем вызывается служба gRPC напрямую. Перекодирование в ASP.NET Core предоставляет следующие преимущества для разработчиков приложений .NET:

  • Снижение сложности: и службы gRPC и сопоставленные API JSON RESTful выполняются из одного приложения ASP.NET Core.
  • Улучшенная производительность: транскодирование десериализирует json в сообщения Protobuf и вызывает службу gRPC напрямую. Существует значительное преимущество, связанное с производительностью, при выполнении этого внутрипроцессного вызова, а не при вызове gRPC к другому серверу.
  • Снижение стоимости: меньшее количество серверов приводит к уменьшению ежемесячного счета за размещение.

Сведения об установке и использовании grpc-gateway см. в файле сведений для grpc-gateway.

Дополнительные ресурсы

gRPC — это высокопроизводительная платформа удаленного вызова процедур (RPC). gRPC использует HTTP/2, потоковую передачу, Protobuf и контракты сообщений для создания высокопроизводительных служб в реальном времени.

Одним из ограничений gRPC является то, что не каждая платформа может использовать ее. Браузеры не полностью поддерживают HTTP/2, поэтому API REST и JSON являются основными способами для передачи данных в браузерные приложения. Несмотря на преимущества, которые gRPC приносит, REST API и JSON имеют важное место в современных приложениях. Создание веб-API gRPC и JSON добавляет нежелательные затраты на разработку приложений.

В этом документе рассматривается создание веб-API JSON с помощью служб gRPC.

Обзор

Перекодирование gRPC JSON — это расширение для ASP.NET Core, которое создает API JSON RESTful для служб gRPC. Настроенное перекодирование позволяет приложениям вызывать службы gRPC, используя следующие привычные понятия HTTP:

  • HTTP-команды
  • привязку параметра URL-адреса;
  • запросы и ответы JSON.

gRPC по-прежнему можно использовать для вызова служб.

Примечание.

Транскодирование JSON gRPC заменяет API HTTP gRPC, альтернативное экспериментальное расширение.

Использование

  1. Добавьте ссылку на пакет для Microsoft.AspNetCore.Grpc.JsonTranscoding.
  2. Зарегистрируйте перекодирование в коде запуска сервера, добавив AddJsonTranscoding: в Program.cs файле изменится builder.Services.AddGrpc(); на builder.Services.AddGrpc().AddJsonTranscoding();.
  3. Создайте структуру /google/api каталогов в каталоге проекта, который содержит .csproj файл.
  4. Добавьте google/api/http.proto и google/api/annotations.proto файлы в /google/api каталог.
  5. Заметьте методы gRPC в .proto файлах с привязками и маршрутами HTTP:
syntax = "proto3";

option csharp_namespace = "GrpcServiceTranscoding";
import "google/api/annotations.proto";

package greet;

// The greeting service definition.
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

Теперь метод SayHello gRPC можно вызывать как gRPC и веб-API JSON:

  • Запрос: GET /v1/greeter/world
  • Ответ: { "message": "Hello world" }

Если сервер настроен на запись журналов для каждого запроса, журналы сервера показывают, что служба gRPC выполняет http-вызов. Перекодирование сопоставляет входящий HTTP-запрос с сообщением gRPC и преобразует ответное сообщение в JSON.

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
      Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1.996ms 200 application/json

Аннотировать методы gRPC

Методы gRPC должны быть аннотированы с помощью правила HTTP, прежде чем они поддерживают перекодирование. Правило HTTP содержит сведения о том, как вызвать метод gRPC, например метод HTTP и маршрут.

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "/v1/greeter/{name}"
    };
  }
}

Пример процедуры:

  • Определяет Greeter службу с методом SayHello . Метод имеет правило HTTP, указанное с помощью имени google.api.http.
  • Метод доступен с запросами GET и маршрутом /v1/greeter/{name} .
  • name Поле сообщения запроса привязано к параметру маршрута.

Многие варианты доступны для настройки привязки метода gRPC к API RESTful. Дополнительные сведения о аннотации методов gRPC и настройке JSON см. в разделе "Настройка HTTP и JSON для транскодирования JSON gRPC".

Методы потоковой передачи

Традиционный API gRPC по HTTP/2 поддерживает потоковую передачу во всех направлениях. Перекодирование предназначено только для серверной потоковой передачи. Методы клиентской и двунаправленной потоковой передачи не поддерживаются.

Методы потоковой передачи сервера используют json с разделителями строк. Каждое сообщение, написанное с помощью WriteAsync , сериализуется в ФОРМАТЕ JSON и следует новая строка.

Следующий метод серверной потоковой передачи записывает три сообщения:

public override async Task StreamingFromServer(ExampleRequest request,
    IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
    for (var i = 1; i <= 3; i++)
    {
        await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
        await Task.Delay(TimeSpan.FromSeconds(1));
    }
}

Клиент получает три объекта JSON с разделителями строк:

{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}

Обратите внимание, что WriteIndented параметр JSON не применяется к методам потоковой передачи сервера. Красивая печать добавляет новые строки и пробелы в JSON, которые нельзя использовать с разделителями строк JSON.

Просмотр или скачивание примера приложения ASP.NET Core gPRC для перекодирования и потоковой передачи.

Протокол HTTP

Шаблон службы ASP.NET Core gRPC, включенный в пакет SDK для .NET, создает приложение, настроенное только для HTTP/2. HTTP/2 является хорошим по умолчанию, если приложение поддерживает только традиционные gRPC по протоколу HTTP/2. Однако перекодирование работает как с HTTP/1.1, так и с HTTP/2. Некоторые платформы, например UWP или Unity, не могут использовать HTTP/2. Чтобы обеспечить поддержку всех клиентских приложений, настройте сервер для включения HTTP/1.1 и HTTP/2.

Обновите протокол умолчанию в файле appsettings.json:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

Как вариант, вы можете настроить конечные точки Kestrel в коде запуска.

Чтобы включить HTTP/1.1 и HTTP/2 на одном порте, требуется TLS для согласования протокола. Дополнительные сведения о настройке протоколов HTTP в приложении gRPC см. в разделе Согласование протокола gRPC в ASP.NET Core.

Транскодирование json gRPC и gRPC-Web

Как перекодирование, так и gRPC-Web позволяют вызывать службы gRPC из браузера. Однако способы, которыми они это делают, отличаются.

  • gRPC-Web позволяет браузерным приложениям вызывать службы gRPC из браузера с помощью клиента gRPC-Web и Protobuf. gRPC-Web требует, чтобы приложение браузера создало клиент gRPC и имеет преимущество отправки небольших, быстрых сообщений Protobuf.
  • Транскодирование позволяет приложениям браузера вызывать службы gRPC, как если бы они были API RESTful с JSON. Браузерному приложению не нужно создавать клиент gRPC и не нужно ничего знать о gRPC.

Предыдущую службу Greeter можно вызывать с помощью API JavaScript браузера:

var name = nameInput.value;

fetch('/v1/greeter/' + name)
  .then((response) => response.json())
  .then((result) => {
    console.log(result.message);
    // Hello world
  });

grpc-gateway

grpc-gateway — еще одна технология создания API RESTful JSON из служб gRPC. В нем используются те же .proto заметки для сопоставления концепций HTTP с службами gRPC.

grpc-gateway использует генерирование кода для создания обратного прокси-сервера. Обратный прокси-сервер преобразует вызовы RESTful в gRPC+Protobuf и отправляет вызовы по протоколу HTTP/2 в службу gRPC. Преимущество этого подхода заключается в том, что служба gRPC не знает об API JSON RESTful. Любой сервер gRPC может использовать grpc-gateway.

Между тем перекодирование JSON gRPC выполняется в приложении ASP.NET Core. При этом JSON десериализируется в сообщения Protobuf, а затем вызывается служба gRPC напрямую. Перекодирование в ASP.NET Core предоставляет следующие преимущества для разработчиков приложений .NET:

  • Снижение сложности: и службы gRPC и сопоставленные API JSON RESTful выполняются из одного приложения ASP.NET Core.
  • Улучшенная производительность: транскодирование десериализирует json в сообщения Protobuf и вызывает службу gRPC напрямую. Существует значительное преимущество, связанное с производительностью, при выполнении этого внутрипроцессного вызова, а не при вызове gRPC к другому серверу.
  • Снижение стоимости: меньшее количество серверов приводит к уменьшению ежемесячного счета за размещение.

Сведения об установке и использовании grpc-gateway см. в файле сведений для grpc-gateway.

Дополнительные ресурсы