gRPC介绍

作者: 阿兵云原生 | 来源:发表于2021-05-21 23:14 被阅读0次

    [TOC]

    gRPC

    image

    gRPC介绍

    gRPC是什么?

    image

    RPC和RESTful的区别是什么?

    RPC的消息传输可以是TCP,可以是UDP,也可以是HTTP,当RPC消息传输是HTTP时,它的结构与RESTful的架构类似

    RPC和RESTful有什么不同呢:

    • 操作的对象不一样的,RESTful会更加灵活

    RPC操作的是方法对象, RESTful操作的是资源

    RPC的客户端和服务器端是紧耦合的,客户端需要知道服务端的函数名字,参数类型、顺序等,才能远程过程调用。

    RESTful基于 http的语义操作资源,参数的顺序一般没有关系

    • RCP更适合定制化

      RESTful执行的是对资源的操作,主要都是CURD(增删改查)的操作,若需要实现一个特定的功能,如计算一个班级的平均分,这个时候使用RPC定义服务器的方法(如:Stu.CalAvg)供客户端调用则显得更有意义

    image

    gRPC的特性是什么?

    • gRPC是可以跨语言开发的

    在gRPC客户端可以直接调用不同服务器上的远程程序,使用姿势看起来就像调用本地过程调用一样,很容易去构建分布式应用和服务。客户端和服务端可以分别使用gRPC支持的不同语言实现。

    image
    • 基于HTTP2标准设计,比其他框架更优的地方有
      • 支持长连接,双向流、头部压缩、多复用请求
      • 节省带宽降低TCP链接次数节省CPU使用延长电池寿命
      • 提高了云端服务和Web应用的性能
      • 客户端和服务端交互透明
      • gRPC默认使用protobuf来对数据序列化

    gRPC的数据交互模式是怎么样的?

    请求应答式

    image

    客户端发出一次请求,可以从服务端读取一系列的消息

    image

    客户端写一系列消息给到服务端,等待服务端应答

    image

    客户端和服务端都可以通过读写数据流来发送一系列消息

    image

    数据的序列化方式 - protobuf

    protobuf 是一个对数据序列化的方式,类似的有JSON,XML等

    简单介绍protobuf的结构定义包含的3个关键字

    • 以.proto做为后缀,除结构定义外的语句以分号结尾
    • 结构定义可以包含:message、service、enum,三个关键字
    • rpc方法定义结尾的分号可有可无

    Message命名采用驼峰命名方式,字段是小写加下划线

     message ServerRequest {
          required string my_name = 1;
      }
    

    Enums类型名采用驼峰命名方式,字段命名采用大写字母加下划线

     enum MyNum {
          VALUE1 = 1;
          VALUE2 = 2;
      }
    

    Service与rpc方法名统一采用驼峰式命名

    service Love {
      // 定义Confession方法
      rpc MyConfession(Request) returns (Response) {}
    }
    

    关于prtobuf的安装可以看看之前写的一个安装步骤《5个步骤搞定PROTOBUF的安装

    在proto文件中使用package关键字声明包名,默认转换成go中的包名与此一致,可以自定义包名,修改go_package即可:

    test.proto

    syntax = "proto3"; // proto版本
    
    package pb; // 指定包名,默认go中包名也是这个
    
    // 定义Love服务
    service Love {
      // 定义Confession方法
      rpc Confession(Request) returns (Response) {}
    }
    
    // 请求
    message Request {
      string name = 1;
    }
    
    // 响应
    message Response {
      string result = 1;
    }
    

    安装好protoc环境之后,进入到proto文件的目录下,(例如打开window git)执行如下命令,将proto文件编译成pb.go文件

     protoc --go_out=plugins=grpc:. test.proto
    

    转换结果:

    // Code generated by protoc-gen-go. DO NOT EDIT.
    // versions:
    //  protoc-gen-go v1.25.0
    //  protoc        v3.13.0
    // source: test.proto
    
    package test
    
    import (
        context "context"
        proto "github.com/golang/protobuf/proto"
        grpc "google.golang.org/grpc"
        codes "google.golang.org/grpc/codes"
        status "google.golang.org/grpc/status"
        protoreflect "google.golang.org/protobuf/reflect/protoreflect"
        protoimpl "google.golang.org/protobuf/runtime/protoimpl"
        reflect "reflect"
        sync "sync"
    )
    
    const (
        // Verify that this generated code is sufficiently up-to-date.
        _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
        // Verify that runtime/protoimpl is sufficiently up-to-date.
        _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
    )
    
    // This is a compile-time assertion that a sufficiently up-to-date version
    // of the legacy proto package is being used.
    const _ = proto.ProtoPackageIsVersion4
    
    type Request struct {
        state         protoimpl.MessageState
        sizeCache     protoimpl.SizeCache
        unknownFields protoimpl.UnknownFields
    
        Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
    }
    
    
    type Response struct {
        state         protoimpl.MessageState
        sizeCache     protoimpl.SizeCache
        unknownFields protoimpl.UnknownFields
    
        Result string `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"`
    }
    
    // LoveServer is the server API for Love service.
    type LoveServer interface {
        Confession(context.Context, *Request) (*Response, error)
    }
    
    

    一个DEMO

    目录结构为:

    
    -------------------------------
    | mygrpc
    | ---------pb
    | -------------test.proto
    | ---------client.go
    | ---------srv.go
    -------------------------------
    

    client.go

    package main
    
    import (
        "context"
        "log"
    
        "mygrpc.com/pb"
    
        "google.golang.org/grpc"
    )
    
    func main() {
        // 连接grpc服务
        conn, err := grpc.Dial(":8888", grpc.WithInsecure())
        if err != nil {
            log.Fatal(err)
        }
        // 很关键
        defer conn.Close()
    
        // 初始化客户端
        c := pb.NewLoveClient(conn)
    
        // 发起请求
        response, err := c.Confession(context.Background(), &pb.Request{Name: "小魔童哪吒"})
        if err != nil {
            log.Fatal(err)
        }
    
        log.Println(response.Result)
    }
    

    server.go

    package main
    
    import (
        "context"
        "log"
        "net"
    
        "google.golang.org/grpc"
        "mygrpc.com/pb"
    )
    
    // 定义Love服务
    type Love struct {
    }
    
    // 实现Love服务接口
    func (l *Love) Confession(ctx context.Context, request *pb.Request) (*pb.Response, error) {
        resp := &pb.Response{}
        resp.Result = "your name is " + request.Name
        return resp, nil
    }
    
    func main() {
        // 监听8888端口
        listen, err := net.Listen("tcp", ":8888")
        if err != nil {
            log.Fatal(err)
        }
    
        // 实例化grpc server
        s := grpc.NewServer()
    
        // 注册Love服务
        pb.RegisterLoveServer(s, new(Love))
    
        log.Println("Listen on 127.0.0.1:8888...")
        s.Serve(listen)
    }
    

    下一次介绍关于gRPC的认证

    技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

    我是小魔童哪吒,欢迎点赞关注收藏,下次见~

    相关文章

      网友评论

        本文标题:gRPC介绍

        本文链接:https://www.haomeiwen.com/subject/vawgjltx.html