[goframe] (4): It is very convenient to use goframe to access the grpc service. It can easily build and generate service code, and the startup method is also very simple. The local call is successful using the code

foreword


The original link of this article is:
https://blog.csdn.net/freewebsys/article/details/108971807

Not to be reproduced without permission of the blogger.
The blogger’s CSDN address is: https://blog.csdn.net/freewebsys
The blogger’s nugget address is: https://juejin.cn/user/585379920479288
The blogger’s Zhihu address is: https://www.zhihu. com/people/freewebsystem

1. About grpc microservices


Project reference:

https://grpc.io/docs/languages/go/quickstart/

You need the protoc tool to install it directly:

# 手动安装 gf 工具:

git clone https://github.com/gogf/gf && cd gf/cmd/gf && go install

# 安装工具

sudo apt install -y protobuf-compiler
protoc  --version
libprotoc 3.12.4

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

Project address:
https://github.com/gogf/gf-demo-grpc

Then you can execute the pb command

make pb finally shows done! The execution is successful:

$ make pb
/usr/bin/protoc --proto_path=/data/home/test/go/src/gf-demo-grpc/manifest/protobuf --go_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api --go-grpc_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api /data/home/test/go/src/gf-demo-grpc/manifest/protobuf/pbentity/user.proto
/usr/bin/protoc --proto_path=/data/home/test/go/src/gf-demo-grpc/manifest/protobuf --go_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api --go-grpc_out=paths=source_relative:/data/home/test/go/src/gf-demo-grpc/api /data/home/test/go/src/gf-demo-grpc/manifest/protobuf/user/v1/user.proto
done!

Then write the proto file, which is also very simple:
reference document:
https://juejin.cn/post/6978474549025177608

user.proto

// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================

syntax = "proto3";

package pbentity;

option go_package = "github.com/gogf/gf-demo-grpc/api/pbentity";

import "google/protobuf/timestamp.proto";

message User {
    uint32                    Id       = 1   ; // User ID        
    string                    Passport = 2   ; // User Passport  
    string                    Password = 3   ; // User Password  
    string                    Nickname = 4   ; // User Nickname  
    google.protobuf.Timestamp CreateAt = 5   ; // Created Time   
    google.protobuf.Timestamp UpdateAt = 6   ; // Updated Time   
    google.protobuf.Timestamp DeleteAt = 7   ; // Deleted Time   
}

user api proto, a simple method with only one service

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

syntax = "proto3";

package user;

option go_package = "gf-demo-grpc/api/user/v1";

service User{
    rpc Create(CreateReq) returns (CreateRes) {}
}

message CreateReq {
    string Passport = 1; // v: required
    string Password = 2; // v: required
    string Nickname = 3; // v: required
}
message CreateRes {
    string Data = 1; // v: required
}

2. Modify the generated code


Goframe will create a controller-like service by default, which is actually a gprc service:

package user

import (
	"context"
	v1 "github.com/gogf/gf-demo-grpc/api/user/v1"
	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
)

type Controller struct {
    
    
	v1.UnimplementedUserServer
}

func Register(s *grpcx.GrpcServer) {
    
    
	v1.RegisterUserServer(s.Server, &Controller{
    
    })
}

func (*Controller) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
    
    
	return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

But to modify, the default grpc directly returns an exception of unimplemented code:

return nil, gerror.NewCode(gcode.CodeNotImplemented)

changed to:

func (*Controller) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
    
    

	g.Log().Printf(ctx, `Create user get Nickname : %+v`, req.Nickname)

	res = &v1.CreateRes{
    
    }
	res.Data = "OK"

	return res, nil
}

Then modify the test method:

package test

import (
	"fmt"
	"testing"

	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/gogf/gf/v2/test/gtest"

	v1 "github.com/gogf/gf-demo-grpc/api/user/v1"
)

func Test_Create(t *testing.T) {
    
    
	gtest.C(t, func(t *gtest.T) {
    
    
		var (
			ctx  = gctx.GetInitCtx()
			conn = grpcx.Client.MustNewGrpcClientConn("demo")
			user = v1.NewUserClient(conn)
		)
		for i := 1; i <= 10; i++ {
    
    
			res, err := user.Create(ctx, &v1.CreateReq{
    
    
				Passport: fmt.Sprintf(`passport-%d`, i),
				Nickname: fmt.Sprintf(`nickname-%d`, i),
			})
			if err != nil {
    
    
				g.Log().Fatalf(ctx, `create user failed: %+v`, err)
			} else {
    
    
				g.Log().Printf(ctx, `create user success : %+v`, res.Data)
			}
		}
	})
}

Execute 10 times:
Result:

2023-06-06 11:44:26.456 {003338c60bf5651781952122252686fb} create user success : OK

The data data returned by grpc can be obtained.
You can also request data through a direct connection:

		host := "localhost:8000"
		ctx  := gctx.GetInitCtx()
		conn, err := grpc.Dial(host, grpc.WithTransportCredentials(insecure.NewCredentials()) )
		g.Log().Print(ctx, `create ChatMessage response `, err)
		user = v1.NewUserClient(conn)

Why do you want to connect directly, because it may be necessary to provide services to others on the external network.
At the same time, you can use nginx for load balancing, and use grpc_pass reverse proxy directly, which is similar to proxying other services.

Other references: https://juejin.cn/post/7179907227031994405

 upstream grpc_servers {
    
    
   server 192.168.1.101:8000;
   server 192.168.1.102:8000;
 }

   location / {
    
    
       grpc_pass grpc://grpc_servers:8000;
   }

3. Related goframe grpc configuration


Configuration reference:

https://goframe.org/pages/viewpage.action?pageId=80488218

The config.yaml configuration in it:

# GRPC Server.
# 
grpc:
  address: ":8000" # 自定义服务监听地址
  name: "demo"
  logPath: ""
  logStdout: true
  errorStack: true
  errorLogEnabled: true
  errorLogPattern: "error-{Ymd}.log"
  accessLogEnabled: true
  accessLogPattern: "access-{Ymd}.log"

Then start the service in main:

package main

import (
	"github.com/gogf/gf-demo-grpc/internal/controller/user"
	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
)

func main() {
    
    
	// cmd.Main.Run(gctx.New())
	s := grpcx.Server.New()
	user.Register(s)
	s.Run()
}

4. Summary


The service of grpc is indeed a little more troublesome than other service development.
Mainly the installation and configuration of proto tools.
But after mastering it, I found that it is also very convenient, and it can support the mutual calling of multiple languages.

At the same time, with the tool integration of goframe, it is easier to directly help configure the service.
I have helped to write them all, and the rest can be used to write business logic, which is very convenient. Recommended.

The original link of this article is:
https://blog.csdn.net/freewebsys/article/details/108971807

insert image description here

Guess you like

Origin blog.csdn.net/freewebsys/article/details/131028720