A Modern Cross-Platform approach to µServices in .NET

Part 2: Dockerized gRPC API in C# on .NET

Part 1: Dockerized REST API in C# .NET

Part 2: Dockerized gRPC API in C# .NET (This part)

A quick note: If you haven’t yet, it’s probably a good thing to start at Part 1 ;)

What’s this part about (gRPC in C#)?

For those new to gRPC, there’s a decent amount of talk online about the trade offs with other service apis. You can check out SO or tons of blogs, but generally speaking gRPC has binary exchange and supports streaming. It generally makes it faster than the likes of REST, but like all technology choices there are trade-offs you need to think about. My personal advice falls into

Use gRPC

  1. You’re a mature(ish) tech org
  2. Have good build and deployment practices
  3. Need fast, streaming information
  4. Want a very clear contract from clients to services

Think twice using gRPC

  1. Have a hard time understanding how to create services
  2. Have a environment where setting up tooling, builds, services, etc is difficult
  3. Don’t have clear experience on designing simple APIs

4. Have lots of other places you can clean up performance issues

Here we’re going to create something that should look very similar to Part 1 except instead of creating restful endpoints, we’re going to create a gRPC service. The repo is located at (https://github.com/josmo/sample-dotnet-grpc). Now going ahead and Create a .NET core 2.0 project ;)

— Checkpoint 1 (Creating the service definition)

Looking at this checkpoint, you can see the proto/internal_application.proto file.

 If you’re not super familiar with protobuf head over to https://grpc.io/docs/there’s tons of information on how to get started. In this case we’re going to generate C# and JavaScript files from it.

It’s relatively simple and just do the following: (note that the protoc-gen-grpc needs to be the location of where the grpc.tools nuget package gets installed. This will general the server part of the code)

> dotnet add package Grpc.Core
> dotnet add package Grpc.Tools
> dotnet add package Google.Protobuf
> protoc --csharp_out=code_gen_csharp proto/internal_application.proto --grpc_out=code_gen_csharp --plugin=protoc-gen-grpc=/Users/{youruser}/.nuget/packages/grpc.tools/1.6.0/tools/macosx_x64/grpc_csharp_plugin
> protoc -I=./proto --js_out=code_gen_js proto/internal_application.proto

This will output C# and Javascript files representing the schema above. We don’t need Javascript yet, but I’m generating the scripts for the client site in the next post. I’m going to commit these files into the repo but normally you would publish this to an internal nuget/npm registry, or equivalent location.

— Checkpoint 2 (Creating the server and dummy implementation)

This checkpoint is probably the meat of the project. We’re going to look at:

services/StatusImpl.cs -> this has the implementation for the service (we’re just going to have dummy static data) If you look at it. It’s really just an implementation of the interface created from the proto file by the code-gen. In this case you get a request object and create and return the response object.

Program.cs -> will create and startup the server. The main thing here is that the generated code includes the server piece and you just need to configure a few things with the service implementation and add it to the server :)

Now you can start the service up and it should work :) One thing note worthy is that unlike REST services, it’s a bit harder to test and validate to see if everything seems kosher. My poor mans version of testing is to add a “client request” after server startup. You can check out the master branch for an example in Program.cs.

 — Checkpoint 3 (Grabbing meta data if we need it)

So what happens when you need to start thinking about authentication type stuff a la “Authorization” headers in REST services? This is where meta-data stuff comes in handy.

Meta data is pretty simple to grab check out this checkpoint. Unfortunately at the time of this post there isn’t an implementation for interceptors (if you need that go and checkout the grpc github project and start contributing ;)). 

Look at services/StatusImpl.cs to see about grabbing metadata from the service.

var headers = context.RequestHeaders;
var token = headers.Where(item => item.Key == "token").Select(item => item.Value).FirstOrDefault();
if (token != null)
{
    //Congrats you have a token on the metadata headers ;) This is a great way to pass jwt tokens
}

 — Checkpoint 4 (Building and throwing it in Docker)

Looking at this checkpoint you’ll see that running the following commands will build your service

dotnet publish -c Release -r linux-x64 -o out
docker build -t sample-dotnet-grpc .
docker run sample-dotnet-grpc

Congrats you now have a simple C# cross platform gRPC running in docker!

With the LIFFFT/Pelo.tech @pelotechnology crew, we’re on the next versions of dev concepts which allow for complete self-hosted apps, deployments which are based on high-availability, high-scalability, and simple blue/green style deployments. Hit me up if you’re interested in more info about it!

Joachim Hill-Grannec @lindyblues is a Partner at http://www.pelo.tech, a group that helps organizations improve their dev practices and culture. These days you’ll also find him traveling around the world dancing at West Coast Swing events.