Службы gRPC на языке C#

Этот документ описывает понятия, необходимые для написания приложений gRPC на C#. Рассматриваемые здесь темы применимы к приложениям gRPC как на основе C-core, так и на основе ASP.NET Core.

Файл PROTO

Для разработки API в gRPC используется подход, при котором сначала создается контракт. Буферы протоколов (protobuf) по умолчанию используются в качестве языка IDL. Файл .proto содержит следующие компоненты:

  • Определение службы gRPC.
  • Сообщения, передаваемые между клиентами и серверами.

Дополнительные сведения о синтаксисе файлов protobuf см. в статье Создание сообщений protobuf для приложений .NET.

Например, рассмотрим файл greet.proto, используемый в разделе о начале работы со службами gRPC:

  • Определяет службу Greeter.
  • Служба Greeter определяет вызов SayHello.
  • SayHello отправляет сообщение HelloRequest и получает сообщение HelloReply:
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

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

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

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

Добавление файла .proto в приложение C#

Файл .proto включается в проект путем его добавления в группу элементов <Protobuf>:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

По умолчанию ссылка на <Protobuf> создает конкретный клиент и базовый класс службы. С помощью атрибута GrpcServices элемента ссылки можно ограничить создание ресурсов на C#. Допустимые значения GrpcServices:

  • Both (по умолчанию, если значение не задано)
  • Server
  • Client
  • None

Средства C# для работы с файлами .proto

Для создания ресурсов C# из файлов .proto требуется пакет инструментов Grpc.Tools. Создаваемые ресурсы (файлы):

  • создаются по мере необходимости при каждой сборке проекта;
  • не добавляются в проект или не возвращаются в систему управления версиями;
  • представляют собой артефакт сборки, находящийся в каталоге obj.

Этот пакет требуется как для серверных, так и для клиентских проектов. Метапакет Grpc.AspNetCore содержит ссылку на Grpc.Tools. Серверные проекты могут добавлять Grpc.AspNetCore с помощью диспетчера пакетов в Visual Studio или путем добавления <PackageReference> в файл проекта:

<PackageReference Include="Grpc.AspNetCore" Version="2.32.0" />

Клиентские проекты должны непосредственно ссылаться на Grpc.Tools вместе с другими пакетами, необходимыми для использования клиента gRPC. Этот пакет инструментов не требуется во время выполнения, поэтому зависимость помечается как PrivateAssets="All":

<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

Создаваемые ресурсы C#

Пакет инструментов создает типы C#, которые представляют сообщения, определенные во включаемых файлах .proto.

Для ресурсов на стороне сервера создается абстрактный базовый тип службы. Базовый тип содержит определения всех вызовов gRPC, содержащихся в .proto файле. Создайте конкретную реализацию службы, производную от этого базового типа, и реализуйте логику для вызовов gRPC. Для greet.proto в описанном выше примере создается абстрактный тип GreeterBase, содержащий виртуальный метод SayHello. Конкретная реализация GreeterService переопределяет метод и реализует логику, обрабатывающую вызов gRPC.

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

Для клиентских ресурсов создается конкретный тип клиента. Вызовы gRPC в файле превратятся в .proto методы конкретного типа, который можно вызвать. Для greet.proto в описанном выше примере создается конкретный тип GreeterClient. Вызовите GreeterClient.SayHelloAsync, чтобы инициировать вызов gRPC на сервере.

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

По умолчанию серверные и клиентские ресурсы создаются для каждого файла .proto, включаемого в группу элементов <Protobuf>. Чтобы гарантировать, что в серверном проекте создаются только серверные ресурсы, атрибуту GrpcServices присваивается значение Server.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Аналогичным образом атрибуту присваивается значение Client в клиентских проектах.

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

Этот документ описывает понятия, необходимые для написания приложений gRPC на C#. Рассматриваемые здесь темы применимы к приложениям gRPC как на основе C-core, так и на основе ASP.NET Core.

Файл PROTO

Для разработки API в gRPC используется подход, при котором сначала создается контракт. Буферы протоколов (protobuf) по умолчанию используются в качестве языка IDL. Файл .proto содержит следующие компоненты:

  • Определение службы gRPC.
  • Сообщения, передаваемые между клиентами и серверами.

Дополнительные сведения о синтаксисе файлов protobuf см. в статье Создание сообщений protobuf для приложений .NET.

Например, рассмотрим файл greet.proto, используемый в разделе о начале работы со службами gRPC:

  • Определяет службу Greeter.
  • Служба Greeter определяет вызов SayHello.
  • SayHello отправляет сообщение HelloRequest и получает сообщение HelloReply:
syntax = "proto3";

option csharp_namespace = "GrpcGreeter";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

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

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

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

Добавление файла .proto в приложение C#

Файл .proto включается в проект путем его добавления в группу элементов <Protobuf>:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

По умолчанию ссылка на <Protobuf> создает конкретный клиент и базовый класс службы. С помощью атрибута GrpcServices элемента ссылки можно ограничить создание ресурсов на C#. Допустимые значения GrpcServices:

  • Both (по умолчанию, если значение не задано)
  • Server
  • Client
  • None

Средства C# для работы с файлами .proto

Для создания ресурсов C# из файлов .proto требуется пакет инструментов Grpc.Tools. Создаваемые ресурсы (файлы):

  • создаются по мере необходимости при каждой сборке проекта;
  • не добавляются в проект или не возвращаются в систему управления версиями;
  • представляют собой артефакт сборки, находящийся в каталоге obj.

Этот пакет требуется как для серверных, так и для клиентских проектов. Метапакет Grpc.AspNetCore содержит ссылку на Grpc.Tools. Серверные проекты могут добавлять Grpc.AspNetCore с помощью диспетчера пакетов в Visual Studio или путем добавления <PackageReference> в файл проекта:

<PackageReference Include="Grpc.AspNetCore" Version="2.28.0" />

Клиентские проекты должны непосредственно ссылаться на Grpc.Tools вместе с другими пакетами, необходимыми для использования клиента gRPC. Этот пакет инструментов не требуется во время выполнения, поэтому зависимость помечается как PrivateAssets="All":

<PackageReference Include="Google.Protobuf" Version="3.11.4" />
<PackageReference Include="Grpc.Net.Client" Version="2.52.0" />
<PackageReference Include="Grpc.Tools" Version="2.28.1">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

Создаваемые ресурсы C#

Пакет инструментов создает типы C#, которые представляют сообщения, определенные во включаемых файлах .proto.

Для ресурсов на стороне сервера создается абстрактный базовый тип службы. Базовый тип содержит определения всех вызовов gRPC, содержащихся в .proto файле. Создайте конкретную реализацию службы, производную от этого базового типа, и реализуйте логику для вызовов gRPC. Для greet.proto в описанном выше примере создается абстрактный тип GreeterBase, содержащий виртуальный метод SayHello. Конкретная реализация GreeterService переопределяет метод и реализует логику, обрабатывающую вызов gRPC.

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

Для клиентских ресурсов создается конкретный тип клиента. Вызовы gRPC в файле превратятся в .proto методы конкретного типа, который можно вызвать. Для greet.proto в описанном выше примере создается конкретный тип GreeterClient. Вызовите GreeterClient.SayHelloAsync, чтобы инициировать вызов gRPC на сервере.

static async Task Main(string[] args)
{
    // The port number(5001) must match the port of the gRPC server.
    using var channel = GrpcChannel.ForAddress("https://localhost:5001");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

По умолчанию серверные и клиентские ресурсы создаются для каждого файла .proto, включаемого в группу элементов <Protobuf>. Чтобы гарантировать, что в серверном проекте создаются только серверные ресурсы, атрибуту GrpcServices присваивается значение Server.

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

Аналогичным образом атрибуту присваивается значение Client в клиентских проектах.

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