golang grpc基本使用

2023年 9月 26日 65.2k 0

golang grpc基本使用

什么是PRC&GRPC

RPC是远程过程调用(Remote Procedure Call)的缩写形式, RPC 的主要功能目标是让构建分布式计算(应用)更容易,在提供强大的远程调用能力时不损失本地调用的语义简洁性。通俗地讲,使用RPC进行通信,调用远程函数就像调用本地函数一样,RPC底层会做好数据的序列化与传输。 下图是dubbo rpc实现的图解,以便于大家理解
RPC:image-20230925212828173.png

GRPC是rpc框架的实现,是一个基于Protobuf序列化协议开发的高性能,开源和通用的RPC框架,且支持众多开发语言。
从图中还可以看出,proto文件的编译支持多种语言(Go、Java、Python等),可以轻松实现跨语言调用。

image-20230925212929084.png
RPC调用之前需要进行IDL文件定义编写和对应语言调用模板方法生成(protoc自动生成)

RPC调用大致步骤:

  • 客户端建立连接(gRPC Stub)并调用A方法,发起RPC调用
  • gRPC框架对请求信息使用Protobuf进行对象序列化压缩(IDL)
  • 服务端(gPRC Server)接收到请求后,解码反序列化,进行业务逻辑处理并返回。
  • 对响应结果使用Protobuf进行对象序列化压缩(IDL)
  • 客户端接受到服务端响应,解码发序列化。回调被调用的A方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果。
  • Go gRPC 环境准备

    本人是在WSL环境(window linux 子系统)进行的,window 和 mac 可以自行尝试,原理和步骤都一样。

  • Go 语言环境安装,下载对应的安装包,配置GOPATH、GOROOT、GOPROXY,以及GO111MODULE 设置为on,具体安装和配置细节可参考官网和其他教程,这里列出自己的go env信息:
  • bash
    #GO111MODULE on模式
    GO111MODULE="on"
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/home/lizheng/.cache/go-build"
    GOENV="/home/lizheng/.config/go/env"
    GOEXE=""
    GOEXPERIMENT=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    GOINSECURE=""
    GOMODCACHE="/home/lizheng/gopath/pkg/mod"
    GONOPROXY=""
    GONOSUMDB=""
    GOOS="linux"
    # GOPATH 配置
    GOPATH="/home/lizheng/gopath"
    GOPRIVATE=""
    # GOPROXY 配置
    GOPROXY="https://goproxy.cn"
    # GOROOT 配置
    GOROOT="/home/lizheng/go"
    GOSUMDB="sum.golang.org"
    GOTMPDIR=""
    GOTOOLDIR="/home/lizheng/go/pkg/tool/linux_amd64"
    GOVCS=""
    GOVERSION="go1.17.7"
    GCCGO="gccgo"
    AR="ar"
    CC="gcc"
    CXX="g++"
    CGO_ENABLED="1"
    GOMOD="/dev/null"
    CGO_CFLAGS="-g -O2"
    CGO_CPPFLAGS=""
    CGO_CXXFLAGS="-g -O2"
    CGO_FFLAGS="-g -O2"
    CGO_LDFLAGS="-g -O2"
    PKG_CONFIG="pkg-config"
    GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build1495300227=/tmp/go-build -gno-record-gcc-switches"
    
  • Protocol buffer 编译器配置 这里的Protocol buffer编译器用来编译 .proto RPC协议定义文件,自动生成对应语言的目标代码,减少开发量。安装步骤参考:protoc 安装文档
  • xxx:~$  apt install -y protobuf-compiler
    xxx:~$ protoc --version
    libprotoc 3.6.1
    
    
  • Protocol buffer Go语言编译插件配置安装 因为我们使用的是go语言实现grpc,所以 protoc 命令在执行编译的时候,会调用go语言插件,来生成golang代码。
  • xxx:~$ go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28
    xxx:~$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
    

    注意:这里安装完成之后,会将对应命令安装到gopath配置目录下的bin文件夹下如下图

    WeChat6c26678b4e298c2fc77a0e741cca19ec.jpg

    我们需要确保bin下文件命令可以被全局访问到,配置到PATH中即可,如果是window需要配置到环境变量path中

    image-20230925213213725.png

    实战编写和调用

    经过上述步骤环境已经完成配置,我们开始一个helloword的程序开发,包括服务端和客户端两部分。

  • 新建一个文件夹 go_grpc,使用 `go mod init go_rpc初始化项目

  • 建立子文件夹:client、server、proto,分别存储客户端、服务端、grpc存根文件。

    目录树

  • image-20230925213633075.png

  • 进入proto,新建一个 helloworld.proto 文件,编写一下内容:
  • syntax="proto3";
    option go_package="./proto";
    package proto;
    
    
    service Game{
        rpc SayHello(HelloRequest) returns (HelloResponse);
    }
    
    message HelloRequest{
        string id=1;
    }
    message HelloResponse{
        string value=1;
    }
    

    上面只是一个简单的定义,细节proto语法可自行官网学习

  • 执行protoc命令,生成目标语言文件
  • xxx:~$ protoc --go_out=. --go-grpc_out=. ./proto/helloworld.proto
    

    执行成功会生成:helloworld.pb.go 和 helloworld_grpc.pb.go 两个文件

    image-20230925213808095.png

  • 执行 go mod tidy 下载依赖包,主要是grpc相关的包
  • 编写服务端和客户端代码
    • 服务端
    package main
    import (
    	"net"
    	"context"
    	"fmt"
    	"go_rpc/proto"
    	"google.golang.org/grpc"
    )
    
    type server struct{
    	proto.UnimplementedGameServer
    }
    
    func (s *server) SayHello(c context.Context,request *proto.HelloRequest) (*proto.HelloResponse, error){
    	fmt.Println("收到id为",request.GetId())
    	fmt.Println("回复消息:收到")
    	return  &proto.HelloResponse{Value:request.GetId()},nil
    
    }
    
    func main(){
    
    	con ,err := net.Listen("tcp",":10800")
    	if err != nil{
    		panic("端口被占用了")
    	}
    	defer con.Close()
    	
    	s := grpc.NewServer()
    	proto.RegisterGameServer(s,&server{})
    
    	// 启动RPC监听
    	if err = s.Serve(con); err!=nil{
    		panic(err)
    	}
    	defer s.Stop()
    }
    
    • 客户端
    package main
    import (
    "strconv"
    "sync"
    "time"
    "context"
    "fmt"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"

    "go_rpc/proto"
    )

    func main(){
    con,err := grpc.Dial("localhost:10800",grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil{
    panic(err)
    }
    defer con.Close()
    c := proto.NewGameClient(con)

    ctx ,cancel := context.WithTimeout(context.Background(),time.Second*5)

    fmt.Println("调用sayHello")
    var wg sync.WaitGroup

    for i:=0;i

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论