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)
	}
}
  • 目录
posted @   lwx_R  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示