gRPC
gRPC 使用 Protocol Buffers,这是 Google 用于序列化结构化数据的成熟开源机制,用于数据序列化,比JSON,XML更紧凑
传输使用HTTP/2
测试时使用postman 改成gRPC协议
1.protoc
Protocol Buffer 协议缓冲区编译器
gRPC 应用程序通常利用Protocol Buffers 进行服务定义和数据序列化
协议缓冲区编译器 protoc 用于编译包含服务和消息定义的 .proto 文件。
1.1 安装
winget install protobuf
下载不下来从这里下压缩包解压,需要配环境变量
https://d.serctl.com/?uuid=25b56669-f36c-4d4b-a6ea-c0209c16e5d1
- 下载protoc-gen-go
下载完提示没找到的话 需要吧gopath下的bin目录加入环境变量
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
- 下载protoc-gen-go-grpc
下载完提示没找到的话 需要吧gopath下的bin目录加入环境变量
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
2.案例
github/grpc-go项目
下载引入到项目
运行examples/helloworld 的服务端和客户端
3.更新gRPC服务
- proto
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}
- 重新生成.pb.go文件
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative helloworld
/helloworld.proto
- service.go
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}
- client.go
main函数最后加
r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: *name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())
4. .proto文件
4.1 定义服务
四种方法
- 简单 RPC
- 服务器端流式 RPC:客户端向服务器发送请求,并获取一个流来读取一系列消息。客户端从返回的流中读取,直到没有更多消息为止
- 客户端流式 RPC: 客户端写入一系列消息并使用提供的流将其发送到服务器。一旦客户端完成消息写入,它会等待服务器读取所有消息并返回响应。
- 双向流式 RPC:双方都使用读写流发送一系列消息。这两个流独立运行,因此客户端和服务器可以按任意顺序读取和写入
service serviceName {
rpc GetFeature(Point) returns (Feature) {}
rpc ListFeatures(Rectangle) returns (stream Feature) {}
rpc RecordRoute(stream Point) returns (RouteSummary) {}
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
4.2 定义消息
message Point {
int32 latitude = 1;
int32 longitude = 2;
}
4.3 生成文件
- .pb.go: 包含所有用于填充、序列化和检索请求和响应消息类型的协议缓冲区代码。
- grpc.pb.go: 一个接口类型(或存根),供客户端调用,其中包含在 RouteGuide 服务中定义的方法。一个接口类型,供服务器实现,也包含在 RouteGuide 服务中定义的方法。
4.4 服务端
- ctx context.Context: RPC 的上下文对象
- point *pb.Point: Point 协议缓冲区请求
- *pb.Feature: 返回的一个包含响应信息的 Feature 协议缓冲区对象
type routeGuideServer struct {
...
}
...
func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {
...
}
- 启动
lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
var opts []grpc.ServerOption
...
grpcServer := grpc.NewServer(opts...)
pb.RegisterRouteGuideServer(grpcServer, newServer())
grpcServer.Serve(lis)
5.客户端
6.postman测试
6.1 新建gRPC
6.2 选择.protoc
import文件即可
7.测试Demo
- proto
syntax = "proto3";
option go_package = "./gRPCDemo";
package gRPCDemo;
service Lwx {
rpc LwxTest (LwxTestIn) returns (LwxTestOut) {}
}
message LwxTestIn {
string name = 1;
}
message LwxTestOut {
string message = 1;
}
- service
package main
import (
pb "RPCGoDemo/gRPCDemo"
"context"
"flag"
"fmt"
"google.golang.org/grpc"
"log"
"net"
)
var (
port = flag.Int("port", 50051, "The server port")
)
type server struct {
pb.UnimplementedLwxServer
}
func (s *server) LwxTest(_ context.Context, in *pb.LwxTestIn) (*pb.LwxTestOut, error) {
log.Printf("Received: %v", in.GetName())
return &pb.LwxTestOut{Message: "Hello " + in.GetName()}, nil
}
func main() {
flag.Parse()
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterLwxServer(s, &server{})
log.Printf("server listening at %v", lis.Addr())
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
- 目录
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律