KeiStory

C# gRPC Streaming

2024. 4. 25. 08:21

C# gRPC Streaming

 

이전 포스팅에이서 gRPC 를 이용해 Streaming Server 를 만들어 Client 간 통신하는 예제입니다.

 

Server 구성

1. ASP.NET Core gRPC 서비스 프로젝트를 생성합니다.


2. proto 파일을 정의합니다. (weather.proto)

요청구조는 없고 api 호출시 WeatherData 를 반환합니다.

returns 인자로 stream WeatherData 로 정의되었습니다.

syntax = "proto3";

import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "GrpcStreamServer";

package WeatherForecast;

// The weather service definition.
service WeatherForecasts {
  // Sends a weatherStream
 rpc GetWeatherStream (google.protobuf.Empty) returns (stream WeatherData);
}

message WeatherData {
  google.protobuf.Timestamp dateTimeStamp = 1;
  int32 temperatureC = 2;
  int32 temperatureF = 3;
  string summary = 4;
}


3. WeatherService.cs 에 동작을 정의합니다.

날짜별 온도값을 랜덤 하게 생성하여 20개를 보냅니다.

using Google.Protobuf.WellKnownTypes;

using Grpc.Core;

using GrpcStreamServer;

using static GrpcStreamServer.WeatherForecasts;

namespace GrpcStreamServer.Services
{
    public class WeatherService : WeatherForecastsBase
    {
        private readonly ILogger<WeatherService> _logger;

        public WeatherService(ILogger<WeatherService> logger) => _logger = logger;

        public override async Task GetWeatherStream(Empty _, IServerStreamWriter<WeatherData> responseStream, ServerCallContext context)
        {
            var rng = new Random();
            var now = DateTime.UtcNow;

            var i = 0;
            while (!context.CancellationToken.IsCancellationRequested && i < 20)
            {
                await Task.Delay(500); // Gotta look busy

                var forecast = new WeatherData
                {
                    DateTimeStamp = Timestamp.FromDateTime(now.AddDays(i++)),
                    TemperatureC = rng.Next(-20, 55),
                    Summary = ""//Summaries[rng.Next(Summaries.Length)]
                };

                _logger.LogInformation("Sending WeatherData response");

                await responseStream.WriteAsync(forecast);
            }
        }
    }
}


4. Program.cs 에서 WeatherService Mapping 코드를 추가합니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapGrpcService<WeatherService>();
});

using GrpcStreamServer.Services;

var builder = WebApplication.CreateBuilder(args);

// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682

// Add services to the container.
builder.Services.AddGrpc();

var app = builder.Build();

app.UseRouting();

app.UseEndpoints(endpoints =>
{
    endpoints.MapGrpcService<WeatherService>();
});

// Configure the HTTP request pipeline.
//app.MapGrpcService<WeatherService>();

app.Run();


5. Properties 의 launchSettings.json 파일에 서비스 주소 정의 및 기타 옵션을 설정합니다.

{
  "profiles": {
    "GrpcStreamServer": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5038;https://localhost:7038",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}


6. appsettings.json 파일에서 Protocols 정의 및 Log Level 지정

Protocols 에 http2 로 설정합니다.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }
}


7. appsettings.Development.json 파일에서 Develope 모드 일 때 Info 도 로그가 찍히도록 Log Level 을 추가합니다.

      "Microsoft.AspNetCore.Hosting": "Information",
      "Microsoft.AspNetCore.Routing.EndpointMiddleware": "Information"

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.AspNetCore.Hosting": "Information",
      "Microsoft.AspNetCore.Routing.EndpointMiddleware": "Information"
    }
  }
}


8. 프로젝트를 실행하여 Server 를 구동합니다.

 

Client 구성

1. 콘솔앱 프로젝트 생성


2. Server 에서 만들어진 proto 파일을 동일하게 Protos 폴더를 만들어 복사/붙여 넣기 합니다.


3. Proto 통신에 필요한 Nuget 패키지를 설치합니다.

Google.Protobuf
Grpc.Net.Client
Grpc.Tools


4. 프로젝트파일 편집

Server 를 Client 로 아래처럼 바꿉니다.
<Protobuf Include="Protos\weather.proto" GrpcServices="Client" />

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <None Remove="Protos\weather.proto" />
  </ItemGroup>

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

  <ItemGroup>
    <Protobuf Include="Protos\weather.proto" GrpcServices="Client" />
  </ItemGroup>

</Project>


4.  빌드합니다.

빌드하게 되면 proto 파일을 이용해 c# 코드가 생성됩니다. (솔루션 탐색기에서 표시되지 않음)


5. 서버 연결 및 통신 처리

using Google.Protobuf.WellKnownTypes;

using Grpc.Core;
using Grpc.Net.Client;

using GrpcStreamClient;

using var channel = GrpcChannel.ForAddress("http://localhost:5038");

var client = new WeatherForecasts.WeatherForecastsClient(channel);

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
using var streamingCall = client.GetWeatherStream(new Empty(), cancellationToken: cts.Token);

try
{
    await foreach (var weatherData in streamingCall.ResponseStream.ReadAllAsync(cancellationToken: cts.Token))
    {
        Console.WriteLine($"{weatherData.DateTimeStamp.ToDateTime():s} | {weatherData.Summary} | {weatherData.TemperatureC} C");
    }
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.Cancelled)
{
    Console.WriteLine("Stream cancelled.");
}

http 주소로 연결합니다.

GetWeatherStream 을 호출하면 서버에서 데이터를 실시간으로 전달해 줍니다.

CancellationTokenSource 로 5초 지나면 호출을 Cancel 합니다.

아래는 서버와 클라이언트 간 테스트 결과




소스 : https://github.com/kei-soft/GrpcSample

 

GitHub - kei-soft/GrpcSample

Contribute to kei-soft/GrpcSample development by creating an account on GitHub.

github.com

 

참고

https://learn.microsoft.com/ko-kr/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-6.0&tabs=visual-studio

 

ASP.NET Core에서 .NET Core gRPC 클라이언트 및 서버 만들기

이 자습서는 ASP.NET Core에서 gRPC 서비스 및 gRPC 클라이언트를 만드는 방법을 보여줍니다. gRPC 서비스 프로젝트를 만들고, proto 파일을 편집하고, 이중 스트리밍 호출을 추가하는 방법을 알아봅니다

learn.microsoft.com

 

반응형

공유하기

facebook twitter kakaoTalk kakaostory naver band