Use Golang to build gRPC service and provide it to. NetCore client calls

Posted by adavis on Wed, 06 Oct 2021 03:34:10 +0200

gRPC overview

RPC

When it comes to gRPC, I have to mention RPC. The so-called RPC(remote procedure call) framework actually provides A set of mechanisms to enable communication between applications. In short, the functions written on machine A can be called directly on machine B through the RPC Protocol.

It differs from http in that:

  • RPC is implemented based on TCP and RESTFUL is implemented based on HTTP.
  • In terms of transmission speed, because HTTP encapsulates more data, the data transmission volume is larger, so the transmission speed of RPC is faster than RESTFUL.

Why is rpc used internally (services and services under contract) and http used externally (to customer)

  • Because HTTP protocol is generally supported by all frameworks. In the case of toC, because you don't know the framework of the situation source and the data situation, you can use restful and HTTP to accept it at the gateway. Among the modules within the microservice, because the protocol schemes are determined by the company, we know various data modes, and TCP transmission can be used to make the data transmission between modules faster. Therefore, restful can be used for data transmission between the gateway and the outside world, and RPC can be used between modules within the microservice.

What is gRPC

gRPC is a high-performance, open-source general RPC framework, originally created by Google. For more than a decade, Google has used a general RPC infrastructure called Stubby to connect a large number of microservices running in and across its data centers. In March 2015, Google decided to build the next version of Stubby and make it open source. The result is   gRPC, which is now used by many organizations outside Google to support use cases from microservices to "last mile" Computing (mobile, network and Internet of things).

gRPC official documents: What is gRPC? | gRPC

In gRPC, client applications can directly call methods on server applications on different machines as if it were local objects, making it easier for you to create distributed applications and services. Like many RPC systems, gRPC specifies methods that can be called remotely through parameters and return types based on the idea of defining services. On the server side, the server implements this interface and runs a gRPC server to handle client calls. On the client, the client has a stub (in some languages referred to as the client), which provides the same method as the server.

install

Golang IDE(Goland)

Goland detailed installation steps: Establishment of Golang development environment_ Han Xiaochao's blog - CSDN blog_ go environment construction

For details of Golang syntax: Detailed explanation of Golang data type and syntax_ Han Xiaochao's blog - CSDN blog

Protocol Buffer

gRPC services can be easily created through Go, C + +, c#, Java, Python and other languages. At the same time, it also means that it can make remote procedure calls across languages. Therefore, an intermediate language (IDL) is needed to restrict and define the interface constraints of communication between remote procedure calls. Protocol Buffer is officially recommended and used by Google. It has slightly simplified syntax, some useful new functions, and supports more languages. Proto3 can be used in Java, C + +, Dart, python, Objective-C, c# etc

Protocol Buffer official document: https://developers.google.com/protocol-buffers

Download Protocal Buffer

Under the protocol buffers project of GitHub, Download the ProtocalBuffer compiler

Configuring the prototype buffer compiler environment variable

Unzip the downloaded Protocal Buffer package, and configure the running directory to the environment variable

After adding environment variables, open the cmd window to execute protocol -- version. The version number appears, indicating that the configuration is successful

protoc-gen-go

Protoc Gen Go is the Go version in the protobuf compilation plug-in series. Protoc Gen Go can convert and encapsulate the interface definition written in Protocol Buffer into Golang code

Before downloading the protocol Gen go, let's set the Golang proxy address

# Seven cattle cloud
go env -w GOPROXY=https://goproxy.cn,direct

Download protocol Gen go

go get -u github.com/golang/protobuf/protoc-gen-go

If there is this file in the bin directory of GOPATH, the download is successful
[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-2tcbyjoo-163354844949) (fdae29ac35e14b0e87e0dbe7a84caaf1)]

Define Protocal Buffer

Open the IDE, create a pbfiles folder in the src directory of GOPATH, and add a product.proto file to the folder to describe the interface definition

syntax = "proto3";
package pbfiles;

option go_package = "../services";

message Product{
    int32 id = 1;
    string name = 2;
    int32 count = 3;
    string description = 4;
}

service pdService{
    rpc GetProduct(Product) returns(Product);
}

After adding, compile the file into Golang code through protoc ol

protoc --go_out=plugins=grpc:./ *.proto

At this time, we found that protoc will automatically create a services directory under the src directory, and automatically compile the proto file written above into product.pb.go

Because the compiled Golang code uses packages such as google.golang.org, we add a mod file to pull the missing modules.

Enter the src directory and execute the go mod init gRPCdemo command

After creation, enter the command go mod tidy, and the product.pb.go code generated above will not be missing references and marked red

Add gRPC service

Implementation of Golang server

Create the grpc-server.go file in the src directory and enter the code:

package main

import (
	"context"
	"fmt"
	"gRPCdemo/services"
	"google.golang.org/grpc"
	"net"
)

type productRequest struct {
}

func (this *productRequest) GetProduct(context context.Context, request *services.Product) (*services.Product, error) {
	var product services.Product
	switch request.Id {
	case 1:
		product.Id = 1
		product.Name = "Apple"
		product.Description = "Little apple"
	case 2:
		product.Id = 1
		product.Name = "watermelon"
		product.Description = "Big watermelon"
	default:
		product.Id = 3
		product.Name = "Banana"
		product.Description = "Banana"
	}
	return &product, nil
}

func main() {
	grpcService := grpc.NewServer()
	services.RegisterPdServiceServer(grpcService, new(productRequest))

	listen, err := net.Listen("tcp", ":5000")
	if err != nil {
		fmt.Println("listen err:", err)
		return
	}
	grpcService.Serve(listen)
}

Open the terminal under the code directory, enter go run grpc-server.go to run the program and start listening

Golang client implementation

Create the grpc-client.go file in the src directory and enter the code:

package main

import (
	"context"
	"fmt"
	"gRPCdemo/services"
	"google.golang.org/grpc"
)

func main() {
	grpcCnn, err := grpc.Dial(":5000", grpc.WithInsecure())
	if err != nil {
		fmt.Println("grpc.dial err:", err)
		return
	}

	grpcClient := services.NewPdServiceClient(grpcCnn)

	var request services.Product
	request.Id = 1

	res, err := grpcClient.GetProduct(context.TODO(), &request)
	if err != nil {
		fmt.Println("GetProduct err:", err)
		return
	}

	fmt.Println(res)
}

Open the terminal in the code directory and enter go run grpc-client.go to run the program


At this point, you can see that the gRPC service has been successfully accessed

. NetCore accesses the gRPC service built by Golang

  1. Open vs create console project grpcClient
  2. Right click the Nuget package of project management and add the following package
    • Grpc.Net.Client, which contains the. NET Core client.
    • Google.Protobuf contains protobuf messages for C#
    • Grpc.Tools includes C# tool support for Protobuf files. The runtime does not require a toolkit, so the dependency is marked PrivateAssets="All".
  3. Create the Protos folder in the gRPC client project
  4. Copy the proto (pbfiles/product.proto) document just created in the Golang project to the Protos of the current. NetCore client project.
  5. Update the namespace in the product.proto file to the namespace of the. NetCore project:
syntax = "proto3";
package pbfiles;

option csharp_namespace = "grpcClient";

message Product{
    int32 id = 1;
    string name = 2;
    int32 count = 3;
    string description = 4;
}

service pdService{
    rpc GetProduct(Product) returns(Product);
}
  1. Edit the grpcClient.csproj project file
  2. Add an item group with < protobuf > elements that reference the greet.proto file:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Google.Protobuf" Version="3.18.0" />
    <PackageReference Include="Grpc.Net.Client" Version="2.39.0" />
    <PackageReference Include="Grpc.Tools" Version="2.41.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    
    <!--add to Protobuf Element group-->
    <Protobuf Include="Protos\product.proto" GrpcServices="Client" />
  </ItemGroup>

</Project>

  1. Build a client project to create a type in the grpcClient namespace. GrpcGreeter types are automatically generated by the build process.
  2. Update the Program.cs file of grpcClient client with the following code:
using Grpc.Net.Client;
using System;

namespace grpcClient
{
    class Program
    {
        static void Main(string[] args)
        {
            // Only. NET Core 3.x requires the System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport switch NET 5 does not require any additional configuration, nor does it require this.
            AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
            
            using var channel = GrpcChannel.ForAddress("http://localhost:5000");
            var client = new pdService.pdServiceClient(channel);
            var reply = client.GetProduct(new Product { Id = 1 });
            Console.WriteLine(reply);

            Console.ReadKey();
        }
    }
}


After starting the program,. NetCore perfectly accesses the gRPC service built by Golang

reference resources

gRPC official documents: What is gRPC? | gRPC

Protocol Buffer official document: https://developers.google.com/protocol-buffers

MSDN: Create. NET Core gRPC client and server in ASP.NET Core | Microsoft Docs

Topics: Go