Go-gRPC的简单使用

RPC简介

Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统

gRPC开发步骤

  • 编写.proto文件,生成指定语言源代码
  • 编写服务端代码
  • 编写客户端代码

安装

创建项目

mkdir grpc_demo
cd grpc_demo
go mod init grpc_demo

安装gRPC

go get -u google.golang.org/grpc

安装Protocol Buffers v3

安装用于生成gRPC服务代码的协议编译器。软件地址

  • 解压下载好的文件
  • protoc二进制文件的路径加到环境变量中
  • 安装protoc的Go插件go get -u github.com/golang/protobuf/protoc-gen-go
    • 编译插件protoc-gen-go将会安装到$GOBIN,默认是$GOPATH/bin,它必须在你的$PATH中以便协议编译器protoc能够找到它。
C:UsersAlbin>d:

D:>cd D:PracticeScriptsgosrcgitee.comliubstdgo

D:PracticeScriptsgosrcgitee.comliubstdgo>mkdir grpc_demo

D:PracticeScriptsgosrcgitee.comliubstdgo>cd grpc_demo

D:PracticeScriptsgosrcgitee.comliubstdgogrpc_demo>go mod init grpc_demo
go: creating new go.mod: module grpc_demo

D:PracticeScriptsgosrcgitee.comliubstdgogrpc_demo>go get -u google.golang.org/grpc
go: downloading golang.org/x/net v0.0.0-20190311183353-d8887717615a
go: extracting golang.org/x/net v0.0.0-20190311183353-d8887717615a
go: downloading golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
go: extracting golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
go: finding golang.org/x/sys latest
go: finding google.golang.org/genproto latest
go: finding golang.org/x/net latest

D:PracticeScriptsgosrcgitee.comliubstdgogrpc_demo>go get -u github.com/golang/protobuf/protoc-gen-go

示例

创建项目代码目录结构

mkdir helloworldpb
mkdir helloworldserver
mkdir helloworldclient

D:PracticeScriptsgosrcgitee.comliubstdgogrpc_demo>tree
文件夹 PATH 列表
卷序列号为 A021-AE06
D:.
└─helloworld
    ├─client
    ├─pb
    └─server

编写proto代码

gRPC是基于Protocol Buffers。

Protocol Buffers是一种与语言无关,平台无关的可扩展机制,用于序列化结构化数据。使用Protocol Buffers可以一次定义结构化的数据,然后可以使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据。

编写文件

vi helloworld/pb/helloworld.proto

syntax = "proto3"; // 版本声明,使用Protocol Buffers v3版本

package pb; // 包名


// 定义一个打招呼服务
service Greeter {
    // SayHello 方法
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 包含人名的一个请求消息
message HelloRequest {
    string name = 1;
}

// 包含问候语的响应消息
message HelloReply {
    string message = 1;
}
生成go语言源代码
protoc -I helloworld/ helloworld/pb/helloworld.proto --go_out=plugins=grpc:helloworld

gRPC_demo/helloworld/pb目录下会生成helloworld.pb.go文件。

编写server端go代码

vi grpc_demo/helloworld/server/server.go

package main

import (
	"fmt"
	"net"

	pb "grpc_demo/helloworld/pb"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "hello " + in.Name}, nil
}

func main() {
	// 监听本地的8972端口
	lsnr, err := net.Listen("tcp", ":8972")
	if err != nil {
		fmt.Printf("failed to listen: %v", err)
		return
	}

	s := grpc.NewServer()                  // 创建gRPC服务器
	pb.RegisterGreeterServer(s, &server{}) // 在gRPC服务端注册服务

	reflection.Register(s) // 在给定的gRPC服务器上注册服务器反射服务

	// Serve方法在lsnr上接受传入连接,为每个连接创建一个ServerTransport和server的goroutine。
	// 该goroutine读取gRPC请求,然后调用已注册的处理程序来响应它们。
	err = s.Serve(lsnr)
	if err != nil {
		fmt.Printf("failed to serve: %v", err)
		return
	}
}

编译并执行
cd helloworld/server
go build
./server

编写客户端go代码

package main

import (
	"context"
	"fmt"

	pb "grpc_demo/helloworld/pb"

	"google.golang.org/grpc"
)

func main() {
	// 连接服务器
	conn, err := grpc.Dial(":8972", grpc.WithInsecure())
	if err != nil {
		fmt.Printf("faild to connect: %v", err)

	}
	defer conn.Close()

	c := pb.NewGreeterClient(conn)

	// 调用服务端的SayHello

	r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "biao"})

	if err != nil {
		fmt.Printf("could not greet: %v", err)
	}
	fmt.Printf("Greeting: %s !
", r.Message)
}

运行

image-20200817152151917

gRPC跨语言调用

使用Python语言编写Client,然后向上面使用go语言编写的server发送RPC请求

安装相关python模块
pip3 install grpcio
pip3 install grpcio-tools
pip3 install protobuf

image-20200817153035358

生成python代码

gRPC_demo目录执行命令

python -m grpc_tools.protoc -I helloworld/pb/ --python_out=helloworld/client/ --grpc_python_out=helloworld/client/ helloworld/pb/helloworld.proto

上面命令执行完成后,在grpc_demo/helloworld/client/目录生成如下两个python文件

image-20200817154205980

编写python版client代码
#!/usr/bin/env python
# coding=utf-8

import logging
import grpc

import helloworld_pb2
import helloworld_pb2_grpc

def run():
    # 注意(gRPC Python Team): .close()方法在channel上是可用的。
    # 并且应该在with语句不符合代码需求的情况下使用。
    with grpc.insecure_channel('localhost:8972') as channel:
        stub = helloworld_pb2_grpc.GreeterStub(channel)
        response = stub.SayHello(helloworld_pb2.HelloRequest(name='标'))
    print("Greeter client received: {}!".format(response.message))


if __name__ == '__main__':
    logging.basicConfig()
    run()
运行

image-20200817154821958

原文地址:https://www.cnblogs.com/binliubiao/p/13518149.html