rpc入门笔记0x01

syntax = "proto3"; // 这是个proto3的文件

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

生成python文件

安装grpcio和grpcio-tools库

pip install grpcio #安装grpc
pip install grpcio-tools #安装grpc tools

生成proto的python文件

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

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

生成指令:

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

样例:

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

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

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

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()

}

你可能感兴趣的:(rpc,笔记)