Getting Started with gRPC, .NET 6, and Amazon EC2
Tags: aws, grpc, dotnet, tutorial
Published: 2022-09-10 15:46:53

Now, I continue to gRPC, why? You have many options to get resources/data from other microservices, like REST or GraphQL. Since I'm exploring gRPC, I want to share my experience too. So, let's go!

## Tools

* [.NET 6 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
* [Go (optional)](https://go.dev/dl/)

## Prepare the Project

You may skip this process if you are willing to try the server code using EC2.

{% github berviantoleo/grpc-explore %}

* Generate `.gitignore` file. Command: `dotnet new gitignore`

* Generate solution file. Command: `dotnet new sln`

Now, we will move to generate gRPC Server Code.

### gRPC Server

* Using dotnet SDK to generate gRPC project. Command: `dotnet new grpc -o GRPCExample`
* Add the project to the solution. Command: `dotnet sln add GRPCExample`
* Try to run your project `dotnet run --project GRPCExample`

### gRPC Client

* Let's move on to our gRPC Client, we will use console app to call the server. First, you will need to generate the project. Command: `dotnet new console -o GRPC.Client`

* Add the project to the solution. Command: `dotnet sln add GRPC.Client`

* Add some packages that will be required. Command:

```bash
dotnet add GRPC.Client package Grpc.Net.Client
dotnet add GRPC.Client package Google.Protobuf
dotnet add GRPC.Client package Grpc.Tools
```

* Copy the `greet.proto` file from `GRPCExample` project, don't forget to have same directory, the directory is `Protos`.

* Update the namespace in the file `greet.proto` at `GRPC.Client`.

```proto
option csharp_namespace = "GRPC.Client";
```

* Update `Program.cs` at our `GRPC.Client`. Don't forget to update the port.

```csharp
using System.Threading.Tasks;
using Grpc.Net.Client;
using GRPC.Client;

// The port number must match the port of the gRPC server.
using var channel = GrpcChannel.ForAddress("http://localhost:5255");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
```

* Done! If you are already run the gRPC server, you may try to run the client project. Command: `dotnet run --project GRPC.Client`. You will get this output.

![dotnet run](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yp9r83il4et2g1b2cpsf.png)

## Let's go to our business

### Setup EC2

* I will use Ubuntu as my base operating system. Feel free to use another operating system.

![image section](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rl057vxs09i0t3lerls6.png)

* I use `t3.micro` just for evaluating my solution.

![vm size](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cxpmezmwi1rg6dwc5hfq.png)

* Don't forget to open the appropriate port. In my case, I will use 80.

### Install .NET SDK on EC2

* SSH into your EC2 Instance using the public IP.
* You may use this [guide](https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu) to install the .NET SDK.

Command:

```bash
sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-6.0
```

### Publish gRPC Server

You will need to publish the gRPC Server source code. I will build the source in my EC2 Instance. There are many alternatives to deploying/delivering your app. Feel free to use another method. In my case, I uploaded my source code to Github.

{% github berviantoleo/grpc-explore %}

### Run gRPC Server

Note: Run all these commands in your EC2 Instance.

* Pull the source code using git. Command: `git clone https://github.com/berviantoleo/grpc-explore`. Please update the command with your own repository if you want to use your code.
* Publish the application. Command: `dotnet publish -o published GRPCExample`. Run this command inside the root directory of the project.
* Run the server. Command: `cd published && sudo dotnet GRPCExample.dll --urls=http://0.0.0.0:80`. I'm using `sudo` since I will run in port 80 which generally can't be used by normal users.

### Test using gRPC Client

* Update the `Program.cs` in your client to point the public IP.
* Run the client

![test result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xyv3uftxtiqww2pxfy39.png)

## (Optional) Using another programming language as the client

Anyway, it's not limited to .NET code as the client. You may use another language, for example, GO. Here is an example. You need to read [this article for the prerequisite](https://grpc.io/docs/languages/go/quickstart/).

* You will need to install some tools using Go.

```bash
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
```

* Create new directory as example `go_client` and init the go module using `go mod init go_client`.

* Install the `gRPC` dependencies. Command: `go get -u google.golang.org/grpc`.

* Copy `greet.proto` into `greet/greet.proto`. Update the `greet.proto` like this.

```proto
syntax = "proto3";

option go_package = "go_client/greet";

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

* Generate the go code. Command: `protoc --go_out=. --go_opt=paths=source_relative     --go-grpc_out=. --go-grpc_opt=paths=source_relative     greet/greet.proto`

* My `main.go` code will be like this.

```go
package main

import (
	"context"
	"go_client/greet"
	"log"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

func main() {
	// don't forget to update the address
	conn, err := grpc.Dial("108.137.77.151:80", grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	greeterClient := greet.NewGreeterClient(conn)
	replyMessage, err := greeterClient.SayHello(context.TODO(), &greet.HelloRequest{
		Name: "Leo",
	})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", replyMessage.GetMessage())
}
```


![result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5hyewpp3q0lebcxud23.png)

So, don't worry if you want to use gRPC. You can use another language as well.

## Thanks for Reading

Thanks for reading! If you have any feedback, feel free to comment here and give your best suggestion. Happy exploring!

![Spongebob Happy GIF](https://media.giphy.com/media/oF5oUYTOhvFnO/giphy.gif)