rpc入门笔记0x01

protobuf 复制代码
syntax = "proto3"; // 这是个proto3的文件

message HelloRequest{  // 创建数据对象
  string name = 1; // name表示名称,编号是1
}

生成python文件

安装grpcio和grpcio-tools库

shell 复制代码
pip install grpcio #安装grpc
pip install grpcio-tools #安装grpc tools

生成proto的python文件

shell 复制代码
python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. helloworld.proto
  • python -m grpc_tools.protoc:使用grpc_tools包中的protoc命令进行代码生成。
  • --python_out=.:指定生成的Python代码的存放位置为当前目录。
  • --grpc_python_out=.:指定生成的gRPC代码的存放位置为当前目录。
  • -I.:指定搜索.proto文件的路径为当前目录

总结起来,该命令的作用是将当前目录下的helloworld.proto文件生成对应的Python代码,并将生成的代码存放在当前目录中

python使用grpc

protobuf 复制代码
syntax = "proto3";

// The greeting service definition.
service Greeter {
  // Sends a greeting 下面就是暴露出来的一些方法
  rpc SayHello (HelloRequest) returns (HelloReply) {} // 定义返回什么类型就要返回什么类型

  rpc SayHelloStreamReply (HelloRequest) returns (stream HelloReply) {}

  rpc SayHelloBidiStream (stream HelloRequest) returns (stream 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;
}

生成出来的文件就直接使用他

go使用grpc

生成指令:

shell 复制代码
#好像是版本不兼容了 protoc -I . helloworld.proto --go_out=plugins=grpc:.
protoc -I . --go_out=. --go-grpc_out=. ./hello.proto

样例:

protobuf 复制代码
syntax = "proto3";
option go_package = ".;proto"; // 这个是必须加的

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

https://blog.csdn.net/neve_give_up_dan/article/details/126920398

https://github.com/grpc/grpc-go/issues/3794

https://blog.csdn.net/Mirale/article/details/122736894

UnimplementedXxxServer的作用:https://blog.csdn.net/Canon_in_D_Major/article/details/108135724

https://zhuanlan.zhihu.com/p/660634947

流模式

grpc的流模式主要有三种:

  • 客户端流模式
  • 服务端流模式
  • 双向流模式

proto文件:stream_proto.proto

protobuf 复制代码
syntax = "proto3";

option go_package = ".;proto";

service Greeter {
  // 服务端流模式:客户端是流,服务端不是流
  rpc GetStream(StreamReqData) returns (stream StreamResData); // 服务端流模式
  rpc PostStream(stream StreamReqData) returns (StreamResData); // 客户端流模式
  rpc AllStream(stream StreamReqData) returns (stream StreamResData); // 双向流模式
}

message StreamReqData{
  string data = 1;
}

message StreamResData{
  string data = 1;
}

server.go

go 复制代码
package main

import (
	"GoRpc_quick/stream_grpc_test/proto"
	"fmt"
	"google.golang.org/grpc"
	"net"
	"sync"
	"time"
)

const PORT = ":8080"

type server struct {
	proto.UnimplementedGreeterServer
}

// 服务端流模式
func (s *server) GetStream(req *proto.StreamReqData, streamServer proto.Greeter_GetStreamServer) error {
	i := 0
	for true {
		streamServer.Send(&proto.StreamResData{
			Data: fmt.Sprintf("%v\n + %v", time.Now().Unix(), req.Data),
		})
		time.Sleep(time.Second)
		if i++; i > 10 {
			break
		}
	}
	return nil
}

// 客户端流模式
func (s *server) PostStream(streamServer proto.Greeter_PostStreamServer) error {
	for {
		recv, err := streamServer.Recv()
		if err != nil {
			fmt.Println(err)
			break
		}

		fmt.Println(recv.Data)
	}
	return nil
}

// 双向流模式
func (s *server) AllStream(streamServer proto.Greeter_AllStreamServer) error {
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() { // 负责receive
		defer wg.Done()
		for {
			recv, _ := streamServer.Recv()
			fmt.Println("收到客户端消息:", recv.Data)
		}
	}()

	go func() {
		defer wg.Done()
		for i := 0; i < 10; i++ {
			streamServer.Send(&proto.StreamResData{Data: "我是服务器"})
			time.Sleep(time.Second)
		}
	}()

	wg.Wait()

	return nil
}

func main() {
	listener, err := net.Listen("tcp", PORT)
	if err != nil {
		panic(err)
	}

	s := grpc.NewServer()
	proto.RegisterGreeterServer(s, &server{})
	err = s.Serve(listener)
	if err != nil {
		panic("failed to start grpc")
	}
}

client.go

go 复制代码
package main

import (
	"GoRpc_quick/stream_grpc_test/proto"
	"context"
	"fmt"
	"google.golang.org/grpc"
	"sync"
	"time"
)

func main() {
	conn, err := grpc.Dial("localhost:8080", grpc.WithInsecure())
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	// 服务端流模式(客户端接收流)
	c := proto.NewGreeterClient(conn)
	stream, _ := c.GetStream(context.Background(), &proto.StreamReqData{Data: "alice"})
	for {
		recv, err := stream.Recv() // 实际上就是socket编程
		if err != nil {
			fmt.Println(err.Error())
			break
		}
		fmt.Println(recv)
	}

	// 客户端流模式,客户端发送流
	postStream, err := c.PostStream(context.Background())
	for i := 0; i < 10; i++ {
		_ = postStream.Send(&proto.StreamReqData{Data: fmt.Sprintf("客户端流模式 + %d", i)})
		time.Sleep(time.Second)
	}

	// 双向流模式
	allStream, _ := c.AllStream(context.Background())
	wg := sync.WaitGroup{}
	wg.Add(2)
	go func() { // 负责receive
		defer wg.Done()
		for {
			recv, _ := allStream.Recv()
			fmt.Println("收到服务器消息:", recv.Data)
		}
	}()

	go func() {
		defer wg.Done()
		for i := 0; i < 10; i++ {
			allStream.Send(&proto.StreamReqData{Data: "我是客户端"})
			time.Sleep(time.Second)
		}
	}()

	wg.Wait()

}
相关推荐
Yawesh_best7 小时前
告别系统壁垒!WSL+cpolar 让跨平台开发效率翻倍
运维·服务器·数据库·笔记·web安全
Ccjf酷儿9 小时前
操作系统 蒋炎岩 3.硬件视角的操作系统
笔记
习习.y10 小时前
python笔记梳理以及一些题目整理
开发语言·笔记·python
在逃热干面10 小时前
(笔记)自定义 systemd 服务
笔记
DKPT12 小时前
ZGC和G1收集器相比哪个更好?
java·jvm·笔记·学习·spring
QT 小鲜肉13 小时前
【孙子兵法之上篇】001. 孙子兵法·计篇
笔记·读书·孙子兵法
星轨初途14 小时前
数据结构排序算法详解(5)——非比较函数:计数排序(鸽巢原理)及排序算法复杂度和稳定性分析
c语言·开发语言·数据结构·经验分享·笔记·算法·排序算法
QT 小鲜肉14 小时前
【孙子兵法之上篇】001. 孙子兵法·计篇深度解析与现代应用
笔记·读书·孙子兵法
love530love17 小时前
【笔记】ComfUI RIFEInterpolation 节点缺失问题(cupy CUDA 安装)解决方案
人工智能·windows·笔记·python·插件·comfyui
愚戏师17 小时前
MySQL 数据导出
数据库·笔记·mysql