Gone框架介绍29 - 在Gone中使用gRPC通信

gone是可以高效开发Web服务的Golang依赖注入框架

github地址:https://github.com/gone-io/gone

文档地址:https://goner.fun/zh/

文章目录

使用gRPC通信

首先创建一个grpc目录,在这个目录中初始化一个golang mod:

bash 复制代码
mkdir grpc
cd grpc
go mod init grpc

编写proto文件,生成golang代码

  • 编写协议文件
    定义一个简单的Hello服务,包含一个Say方法
    文件名:proto/hello.proto
proto 复制代码
syntax = "proto3";

option go_package="/proto";

package Business;

service Hello {
  rpc Say (SayRequest) returns (SayResponse);
}

message SayResponse {
  string Message = 1;
}

message SayRequest {
  string Name = 1;
}
  • 生成golang代码
bash 复制代码
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
proto/hello.proto

其中,protoc的安装参考Protocol Buffer 编译器安装

编写服务端代码

文件名:server/main.go

go 复制代码
package main

import (
	"context"
	"github.com/gone-io/gone"
	"github.com/gone-io/gone/goner"
	"github.com/gone-io/gone/goner/cmux"
	"google.golang.org/grpc"
	"grpc/proto"
	"log"
)

type server struct {
	gone.Flag
	proto.UnimplementedHelloServer // 嵌入UnimplementedHelloServer
}

// 重载协议中定义的服务
func (s *server) Say(ctx context.Context, in *proto.SayRequest) (*proto.SayResponse, error) {
	log.Printf("Received: %v", in.GetName())
	return &proto.SayResponse{Message: "Hello " + in.GetName()}, nil
}

// 实现 gone_grpc.Service接口的RegisterGrpcServer方法,该方法在服务器启动时会被自动调用
func (s *server) RegisterGrpcServer(server *grpc.Server) {
	proto.RegisterHelloServer(server, s)
}

func main() {
	gone.
		Prepare(func(cemetery gone.Cemetery) error {
			_ = cmux.Priest(cemetery) // 注册cmux,可以让gRPC服务 和 HTTP服务共享一个端口

			_ = goner.GrpcServerPriest(cemetery) // 注册gRPC服务器

			cemetery.Bury(&server{}) // 注册gRPC服务
			return nil
		}).
        // 启动服务
		Serve()
}

注册客户端

文件名:client/main.go

go 复制代码
package main

import (
	"context"
	"fmt"
	"github.com/gone-io/gone"
	"github.com/gone-io/gone/goner"
	"google.golang.org/grpc"
	"grpc/proto"
	"log"
)

type helloClient struct {
	gone.Flag
	proto.HelloClient // 嵌入HelloClient

	host string `gone:"config,server.host"`
	port string `gone:"config,server.port"`
}

// 实现 gone_grpc.Client接口的Address方法,该方法在客户端启动时会被自动调用
// 该方法的作用是告诉客户端gRPC服务的地址
func (c *helloClient) Address() string {
	return fmt.Sprintf("%s:%s", c.host, c.port)
}

// 实现 gone_grpc.Client接口的Stub方法,该方法在客户端启动时会被自动调用
// 在该方法中,完成 HelloClient的初始化
func (c *helloClient) Stub(conn *grpc.ClientConn) {
	c.HelloClient = proto.NewHelloClient(conn)
}

func main() {
	gone.
		Prepare(func(cemetery gone.Cemetery) error {
			_ = goner.GrpcClientPriest(cemetery) // 注册gRPC客户端注册器Goner

			cemetery.Bury(&helloClient{}) //注册我们的实现的helloClient
			return nil
		}).
		Run(func(in struct {
			hello *helloClient `gone:"*"`// 在Run方法的参数中,注入 helloClient
		}) {
            // 调用Say方法,给服务段发送消息
			say, err := in.hello.Say(context.Background(), &proto.SayRequest{Name: "gone"})
			if err != nil {
				log.Printf("er:%v", err)
				return
			}
			log.Printf("say result: %s", say.Message)
		})
}

编写配置文件

文件名:config/default.properties

properties 复制代码
# 设置grpc服务的端口和host
server.port=9001
server.host=127.0.0.1

# 设置客户端使用的grpc服务端口和host
server.grpc.port=${server.port}
server.grpc.host=${server.host}

测试

  • 先运行服务端:
bash 复制代码
go run server/main.go

程序等待请求,屏幕打印内容:

log 复制代码
2024-06-19 22:02:41.971|INFO|/Users/jim/works/gone-io/gone/goner/grpc/server.go:84||Register gRPC service *main.server
2024-06-19 22:02:41.971|INFO|/Users/jim/works/gone-io/gone/goner/grpc/server.go:88||gRPC server now listen at 127.0.0.1:9001
  • 然后,另外开窗口启动客户端:
bash 复制代码
go run client/main.go

程序执行完退出,屏幕打印内容如下:

log 复制代码
2024-06-19 22:06:20.713|INFO|/Users/jim/works/gone-io/gone/goner/grpc/client.go:59||register gRPC client *main.helloClient on address 127.0.0.1:9001

2024/06/19 22:06:20 say result: Hello gone
  • 回到服务端窗口,可以看到服务器接收到请求,新打印一行日志:
log 复制代码
2024/06/19 22:06:08 Received: gone

总结

在Gone中使用gRPC,需要完成以下几步:

  • 编写服务端

    1. 编写服务端Goner,匿名嵌入proto协议生成代码的 默认实现
    2. 重载proto文件中定义的接口方法,编写提供服务的具体业务逻辑
    3. 实现gone_grpc.Service接口的RegisterGrpcServer方法,在该方法中完成服务注册
    4. 将 服务端Goner 注册到 Gone框架
    5. 启动服务
  • 编写客户端

    1. 编写客户端Goner,嵌入proto协议生成代码的客户端接口
    2. 实现gone_grpc.Client接口的AddressStub方法,Address方法返回服务端地址,Stub初始化客服端接口
    3. 将 客户端Goner 注册到 Gone框架
    4. 启动客户端,调用客服端接口方法

本文的代码开源在: https://github.com/gone-io/gone/tree/main/example/grpc

相关推荐
tyler_download1 小时前
golang 实现比特币内核:实现基于椭圆曲线的数字签名和验证
开发语言·数据库·golang
hlsd#1 小时前
go mod 依赖管理
开发语言·后端·golang
杜杜的man1 小时前
【go从零单排】迭代器(Iterators)
开发语言·算法·golang
亦世凡华、1 小时前
【启程Golang之旅】从零开始构建可扩展的微服务架构
开发语言·经验分享·后端·golang
Chrikk10 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*10 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue10 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man10 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
有梦想的咸鱼_14 小时前
go实现并发安全hashtable 拉链法
开发语言·golang·哈希算法
杜杜的man18 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang