Why gRPC does not maintain state between service method calls?

Viewed 672

Below is my proto service:

service Greeter {
  // Sends a greeting
  rpc IntroduceYourName(HelloRequest) returns (google.protobuf.Empty);
  rpc SayHellos (RepeatHelloRequest) returns (stream HelloReply);
}

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

message RepeatHelloRequest {
  int32 count = 1;
}


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

This is a simple service, I am trying to set the Name property in the IntroduceYourName method and get the Name back in the SayHellos method .

However, it doesn't work and Name is null when client calls the SayHellos method.

I am working on Net Core 3.1.

Server Implementaion:

public override Task<Empty> IntroduceYourName(HelloRequest request, ServerCallContext context)
{
    this.Name = request.Name;    
    _logger.LogInformation($"Name : {this.Name}");    
    return Task.FromResult(new Empty());
}
    
public override async Task SayHellos(RepeatHelloRequest request, IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
    logger.LogInformation($"SayHellos Name : {this.Name}");
    // _logger.LogInformation("SayRepeatHello called");
    int i = 0;
    while (!context.CancellationToken.IsCancellationRequested && i++ < request.Count)
    {
        var reply = new HelloReply
        {
            Message = DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff tt") + $" Hello {i} " +this.Name
        };
        await responseStream.WriteAsync(reply);
        await Task.Delay(1000);
    }
    if (context.CancellationToken.IsCancellationRequested)
    {
        _logger.LogInformation("The client cancelled their request");
    }
}

Client code:

using var channel = GrpcChannel.ForAddress("https://localhost:5001");
CancellationToken ct = new CancellationToken();
Greeter.GreeterClient client = new Greeter.GreeterClient(channel);
client.IntroduceYourName(new HelloRequest() { Name = "Foo" });
    
using var stream = client.SayHellos(new RepeatHelloRequest() { Count = 10 }, cancellationToken: ct);
while (await stream.ResponseStream.MoveNext(ct))
{
    Console.WriteLine("Greeting: " + stream.ResponseStream.Current.Message);
}
1 Answers

That's because .net core's IoC container creates new instances for each gRPC GreeterService on server's side. So you should tell the IoC to consider your gRPC service as singleton. Add the following to to server's Startup.cs.

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGrpc();
        services.AddSingleton<GreeterService>();
    }

credit goes to this SO post

Related