go 学习 之 GRPC微服务示例

发布于:2024-07-03 ⋅ 阅读:(20) ⋅ 点赞:(0)

1. 背景

学习ing

2. HTTP 微服务 与 GRPC 微服务的区别

grpc和http协议比较大的差异在于grpc需要通过 protobuf 来实现API接口以及数据结构的定义。

2.1. 通信协议和效率:

  • gRPC: 基于HTTP/2协议,利用ProtoBuf(Protocol Buffers)作为高效的二进制序列化格式,这使得gRPC在数据传输上更为高效,减少带宽消耗并提高速度。gRPC还利用了HTTP/2的多路复用特性,可以在单个TCP连接上并行处理多个请求响应,减少了网络延迟。

  • HTTP微服务: 通常使用JSON作为数据交换格式,通过HTTP/1.1或HTTP/2协议。虽然HTTP/2也支持多路复用,但在实际应用中,HTTP请求往往比gRPC更冗长,因为JSON相比ProtoBuf来说体积更大,解析也更耗时。

2.2. 接口定义和代码生成:

  • gRPC: 强依赖于.proto文件来定义服务接口和消息结构,然后通过gRPC工具自动生成客户端和服务端的存根代码(Stub),支持多种编程语言,大大简化了跨语言通信的复杂度。

  • HTTP微服务: 通常采用RESTful风格,接口定义较为灵活,但缺乏标准的接口描述语言和自动代码生成工具。开发者需要手动编写和维护客户端和服务端的API调用逻辑。

2.3. 功能特性:

  • gRPC: 支持双向流、服务端流、客户端流以及双向流式处理,这对于实时数据传输和交互式服务非常有利。此外,gRPC提供了丰富的元数据支持和身份验证机制。

  • HTTP微服务: 虽然可以通过长轮询或者SSE(Server-Sent Events)模拟流式处理,但并不原生支持双向或多向流。RESTful API在设计上更侧重于资源的表述和操作,适合简单的CRUD操作。

2.4. 适用场景:

  • gRPC: 适合内部微服务通信,尤其是那些对性能有高要求、需要频繁且低延迟通信的服务间交互。

  • HTTP微服务: 更适用于对外暴露的API,因为其简单性和广泛接受度,以及浏览器和许多第三方库的良好支持。

2.5. 社区和生态系统:

  • HTTP微服务: 由于RESTful API的普及,拥有更广泛的社区支持和成熟的工具链。

  • gRPC: 虽然相对较新,但得益于Google的推动和其在高性能场景下的优势,生态也在迅速发展,特别是在云原生和微服务架构中。

3. 创建文件:helloworld.proto

syntax = "proto3";

package protobuf;

option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf";


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

以上protobuf文件通过以下命令执行编译(请提前安装protoc工具):

gf gen pb

将会生成对应的proto go数据结构文件以及grpc接口文件:

helloworld.pb.go
helloworld_grpc.pb.go

4. 创建 controller.go

控制器用于实现proto中定义的接口方法

type Controller struct {
	protobuf.UnimplementedGreeterServer
}

func Register(s *grpcx.GrpcServer) {
	protobuf.RegisterGreeterServer(s.Server, &Controller{})
}

// SayHello implements helloworld.GreeterServer
func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) {
	return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil
}

5. 创建 config.yaml

服务端配置文件,在该配置文件中指定了该服务的名称为demo。微服务的名称用于服务间通信的唯一识别标识。在不显式配置服务端的监听端口时,服务端将会随机监听可用的本地端口。在微服务模式下,由于使用服务名称进行通信,服务端口往往不需要显式指定,随机监听即可。

grpc:
  name:            "demo"
  logPath:          "./log"
  logStdout:        true
  errorLogEnabled:  true
  accessLogEnabled: true
  errorStack:       true

6. 创建 server.go

grpc服务端,在不显式指定服务端使用的服务注册发现组件时,服务端默认使用系统文件注册发现组件,该组件仅用于单机测试。其中的controller.Register即调用我们通过工具生成的控制器注册方法将具体的接口实现注册到服务端中

package main

import (
	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
	"github.com/gogf/gf/example/rpc/grpcx/basic/controller"
)

func main() {
	s := grpcx.Server.New()
	controller.Register(s)
	s.Run()
}

7. 创建 client.go

grpc客户端,在创建连接时需要给定服务端服务的具体名称。这里的服务端服务名称为demo,指定的是上面提到的微服务名称。在不显式指定客户端使用的服务注册发现组件时,客户端默认使用系统文件注册发现组件,该组件仅用于单机测试。

package main

import (
	"github.com/gogf/gf/contrib/rpc/grpcx/v2"
	"github.com/gogf/gf/example/rpc/grpcx/basic/protobuf"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
)

func main() {
	var (
		ctx    = gctx.New()
		conn   = grpcx.Client.MustNewGrpcClientConn("demo")
		client = protobuf.NewGreeterClient(conn)
	)
	res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"})
	if err != nil {
		g.Log().Error(ctx, err)
		return
	}
	g.Log().Debug(ctx, "Response:", res.Message)
}

8. 执行结果

服务端输出:服务端输出了一下DEBU调试信息,用于显示一些服务注册的细节。同时,由于没有显式指定服务端的监听端口,这里随机监听了一个本地端口。

$ go run server.go  
2023-03-14 20:50:58.465 [DEBU] set default registry using file registry as no custom registry set
2023-03-14 20:50:58.466 [DEBU] service register: &{Head: Deployment: Namespace: Name:demo Version: Endpoints:10.35.12.81:64517 Metadata:map[protocol:grpc]}
2023-03-14 20:50:58.466 [INFO] pid[98982]: grpc server started listening on [:64517]
2023-03-14 20:52:37.059 {9898c809364a4c17da79e47f3e6c3b8f} /protobuf.Greeter/SayHello, 0.003ms, name:"World", message:"Hello World"

客户端输出:客户端通过微服务名称访问,并接收到了服务端的返回。注意客户端的日志和服务端的日志中,链路跟踪的TraceID是相同的(9898c809364a4c17da79e47f3e6c3b8f),表示同一个请求产生的日志。GoFrame的微服务特性默认开启了链路跟踪能力。

$ go run client.go  
2023-03-14 20:52:37.060 [DEBU] {9898c809364a4c17da79e47f3e6c3b8f} Response: Hello World

网站公告

今日签到

点亮在社区的每一天
去签到