Published on
🍵 5 min read

gRPC in .NET

Authors

Photo

Overview

Target Audience

I've aimed this article at people who want to learn using gRPC in dotnet

Learning Objectives

After completing this article, you will know how to do the following:

  • Create a simple gRPC dotnet application
  • Benefits of gRPC
  • Create a gRPC service

What is gRPC ?

gRPC (gRPC Remote Procedure Calls) is an open-source framework designed by Google for building efficient, scalable, and high-performance APIs and microservices.

Here are the key features and concepts of gRPC:

  1. Protocol Buffers: gRPC uses Protocol Buffers (protobufs) as its interface definition language (IDL) for defining the structure of the data and service interfaces. Protobufs are a language-agnostic, platform-neutral extensible mechanism for serializing structured data, similar to XML or JSON but smaller, faster, and simpler.

  2. High Performance: gRPC supports HTTP/2, providing significant performance improvements over traditional HTTP/1.1, including multiplexing multiple requests over a single connection, header compression, and server push.

  3. Cross-Platform: gRPC supports a wide range of programming languages. This makes it suitable for building cross-platform applications and services.

  4. Bi-Directional Streaming: gRPC supports multiple types of streaming:

    • Unary: Single request and single response.
    • Server Streaming: Single request followed by a stream of responses.
    • Client Streaming: Stream of requests followed by a single response.
    • Bi-Directional Streaming: Streams of requests and responses simultaneously.
  5. Pluggable Authentication: gRPC supports pluggable authentication mechanisms, such as SSL/TLS for encryption and OAuth tokens for authorization, ensuring secure communication between clients and servers.

  6. Load Balancing and Name Resolution: gRPC provides built-in support for load balancing and service discovery, making it easier to manage microservices architectures.

  7. Code Generation: gRPC uses the protobuf compiler (protoc) to generate client and server code in various programming languages, enabling developers to quickly implement services without writing boilerplate code.

Example workflow in dotnet

  • Define service and messages in a .proto file.
  • Implement the generated service methods

Create a gRPC dotnet service

you can use --list keyword to list all of the templates that you can create.

dotnet new --list

to create a gRPC service use the following command:

dotnet new grpc -o my-grpc-service

As you can see from the example project all you need to do is define a protobuf, include the Grpc.AspNetCore package and implement the methods.

Example code

syntax = "proto3";

option csharp_namespace = "remove_grpc_service";

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;
}

Here is an example for the implementation of greet.proto



public class GreeterService : Greeter.GreeterBase

{


public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)

{

return Task.FromResult(new HelloReply

{

Message = "Hello " + request.Name

});

}

}

you also need to enable http2 for kestrel.

"Kestrel": {

"EndpointDefaults": {

"Protocols": "Http2"

}

}

example Program.cs


var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();

var app = builder.Build();

app.MapGrpcService<GreeterService>();

app.Run();

Benefits

  • High Performance: Efficient serialization with Protocol Buffers ensures low-latency communication.
  • Bi-Directional Streaming: Supports real-time, two-way data streams between client and server.
  • Cross-Platform: Provides strong support for multiple programming languages, enhancing versatility.
  • HTTP/2 Support: Leverages HTTP/2 features like multiplexing and compression for better performance.
  • Automatic Code Generation: Simplifies development by generating client and server code from protobuf definitions.

Call gRPC services with the .NET client

var channel = GrpcChannel.ForAddress("https://localhost:5001");

var greeterClient = new Greet.GreeterClient(channel);
var counterClient = new Count.CounterClient(channel);

// Use clients to call gRPC services

How can we make a call from client ?

If you want to make a api call from web application you can use a proxy server to handle this process or you can use json transcoding for dotnet.

Envoy

Currently, browser api doesn't support gRPC on the client-side. We can use Envoy server to handle this issue.

Envoy can be used as a proxy server and it has built-in support for gRPC.

Here is an example yaml file for envoy proxy to handle grpc

static_resources:
  listeners:
    - name: listener_0
      address:
        socket_address: { address: 0.0.0.0, port_value: 8000 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: auto
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: local_service
                      domains: ['*']
                      routes:
                        - match: { prefix: '/' }
                          route:
                            cluster: greeter_service
                            max_stream_duration:
                              grpc_timeout_header_max: 0s
                      cors:
                        allow_origin_string_match:
                          - prefix: '*'
                        allow_methods: GET, PUT, DELETE, POST, OPTIONS
                        allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
                        max_age: '1728000'
                        expose_headers: custom-header-1,grpc-status,grpc-message
                http_filters:
                  - name: envoy.filters.http.grpc_web
                    typed_config:
                      '@type': type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
                  - name: envoy.filters.http.cors
                    typed_config:
                      '@type': type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
                  - name: envoy.filters.http.router
                    typed_config:
                      '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
    - name: greeter_service
      connect_timeout: 0.25s
      type: logical_dns
      http2_protocol_options: {}
      lb_policy: round_robin
      load_assignment:
        cluster_name: cluster_0
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: grpc_server_service
                      port_value: 50051