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.

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

Part 1 — C# Rest API: A simple service build to run in Docker (Linux) with EF and Nancy FX

Part 1: Dockerized REST API in C# .NET (this part)

Part 2: Dockerized gRPC API in C# .NET

How did I come about to try this out? TLDR: This implementation came out of a conversation about modernizing a .NET shop to make use of modern micro-service paradigms. ;)

Recently I moved the NYC from Seattle and although I love both cities it’s definitely been a different experience meeting people. While talking to Bryce (Another person I’ve had the privilege to work with in Seattle) about the ups and downs for building a network in NYC, he introduced me to Jonathan who’s working in midtown for a financial company (wait… NYC has finance? ;), who knew!). We started chatting about life and pretty soon were geeking about various tech stacks and whatever might be hip these days. At a certain point we got on the topic of .NET shops. Which honestly aren’t exactly known to be cutting edge. But these days Microsoft has been tweeting in my ears again on cool stuff they’ve been promoting. They are pretty far behind in the open source community and related practices. However their efforts are definitely in the right direction. For example I was surprised to see that for the most part everything in these posts works the same in Windows, Linux, and macOS. After a wonderful chat about people stuck in their ways and how you could bring modern style development and ops to people that are used to a stack that doesn’t really promote that, I wondered if it would be possible to get a quick micro style service running on docker in AWS/Azure/GCP on linux written in C#. (It definitely morphed into more hence the followup posts) The following is that story!

What are we Building?
For this example we’re going to build an internal application registry. The idea is that we’ll have a simple C# REST service where we can store and retrieve information about the organizations available web apps. Things like it’s name, description, url, etc. Then we’ll have a gRPC service that has information about the state of the service (things like online, offline, etc). On top of that we’ll have a graphql service that links the two pieces, and finally a react.js client that consumes that graphql service.

arch-diagram.png

 

Getting Started — What’s the tech involved (check out the code here)

  • C# (mono or dotnet)
  • Grab you favorite IDE (I’m using Rider)
  • Docker
  • Rancher (out of scope, and out of scope but part of our CI/CD story)
  • Drone (out of scope but part of our CI/CD story)
  • AWS/Azure (out of scope ;))

Mono vs. dotnet - checkout the answer on stackoverflow

What frameworks are we going to use

  • .NET core 2.0
  • Nancy fx
  • Entity Framework

Create a .NET core project — first commit in the project should Give you an idea of what that looks like :)
Now let’s start by getting Nancy Fx going. Here you should use Nuget

> dotnet add package Nancy -v 2.0.0-clienteastwood
> dotnet add package Nancy.Authentication.Stateless -v 2.0.0-clienteastwood
> dotnet add package Nancy.Hosting.Self -v 2.0.0-clienteastwood

 — Checkpoint 1 (Basic service running)
Modify your Program.cs file to look like the one at this checkpoint. One thing to point out is that I’m doing a “Thread.Sleep(Timeout.Infinite);” at line 28. This may seem weird at first since most of the examples have a waiting for key press to kill the service. However this is going to make it so that we can start the service in a Docker container later.
Note: If you’re on windows and don’t have admin rights by default. First poor you… I do feel your pain! Second you’ll need to run something like the following with Administrator privilege:

> netsh http add urlacl url=http://+:8888/ user=Everyone

 — Checkpoint 2 (Creating your endpoint)
Now looking at this checkpoint we’ll find two new files. models/Applications.cs which is just a POCO (Plain old C# object) and modules/Applications.cs which will contain our routes for Nancy FX. Running this locally we essentially have http://baseurl:8888/v1/applications as our first route!
 — Checkpoint 3 (Adding data source via code first in Entity Framework)
Now from this checkpoint you see the following needs to happen.

1. More Nuget

> dotnet add package Microsoft.EntityFrameworkCore -v 2.0.0
> dotnet add package Microsoft.EntityFrameworkCore.SqlServer -v 2.0.0
> dotnet add package Microsoft.EntityFrameworkCore.Tools -v 2.0.0

2. contexts/AppDbContext contains the connection information as well as what DbSets (models bound to the database) are available. You may notice that I’m using environment variables to load the host, user and password. I’m doing that so I can later configure it inside a container.

3. models/Application.cs now has annotations for the tables name and the data types

4. modules/Applications.cs now has the database context injected, has well as the full CRUD endpoints.

5. This is a weird piece but do use the code to table generation you’ll need to add the DotNetCliToolReference like the following code chunk. This will let you run “dotnet ef” commands :)

6. At this point you should now be able to create your database using:

> dotnet ef migrations add initial (this will create a Migrations folder)
> dotnet ef database update

 — Checkpoint 4 (Lets add some performance metrics)

Now looking at this checkpoint you’ll see helpers/MiddlewareWrapper.cs has an intercept and we’re using it in modules/Applications.cs to get timing information on our requests.

 — Checkpoint 5 (Let’s build and Docker this thing up)

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

dotnet publish -c Release -r linux-x64 -o out
docker build -t sample-dotnet-rest .
docker run sample-dotnet-rest (you'll need the host, username and password as environment variables)

Congrats you now have a simple C# cross platform REST service using Entity Framework with code first 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.

Bryce Covert presenting "Automate Creation of CI/CD Pipeline by Bryce Covert"

Our recent ShareOut here at Pelotech covered a lot of ground. Even though there's a lot to take in, Bryce has done an excellent job of breaking apart the various elements and features of the tooling to describe all of the moving parts. Check out the video. If you're interested, please give Bryce a follow @_bcovert_ and Pelotech @Pelotechnology, and feel free to strike up conversation or ask questions about the talk.