zoukankan      html  css  js  c++  java
  • 说说gRPC的四种服务方法

    本文通过一个简单的例子来演示这4种类型的使用方法

    案例代码:https://github.com/artfoxe6/grpc-sample-example

    目录结构说明
    ├── calculator.proto # 定义 protobuf 
    ├── client 
    │   ├── client.go # 客户端
    │   ├── gencode
    │   │   └── calculator.pb.go # protoc-gen-go中间件生成的go中间代码
    │   ├── go.mod
    │   └── go.sum
    ├── README.md
    └── server
        ├── gencode
        │   └── calculator.pb.go # 和上面一样
        ├── go.mod
        ├── go.sum
        └── server.go # 服务端

    client和server是两个完全独立的项目,所以protoc-gen-go生成的中间代码并没有公用,
    而是放到各自单独的项目中,实际上两者内容是完全一样的

    首先来看 calculator.proto

    syntax = "proto3";
    
    package rpc.calculator.test;
    
    service Calculator {
        //简单模式
        rpc Add (TwoNum) returns (Response) {}
    
        //服务端流
        rpc GetStream (TwoNum) returns (stream Response) {}
    
        //客户端流
        rpc PutStream (stream OneNum) returns (Response) {}
    
        //双向流
        rpc DoubleStream (stream TwoNum) returns (stream Response) {}
    }
    
    message TwoNum {
        int32 a = 1;
        int32 b = 2;
    }
    message Response {
        int32 c = 1;
    }
    message OneNum{
        int32 a = 1;
    }

    这里定义了一个计算器服务,包含四个方法,这个四个方法分别演示了个RPC的四种服务类型
    下面分别介绍这个四个方法是做什么的:
    1. 客户端发送一个请求,包含两个数字,服务端是返回两个数字的和,这种最基本也是最常用的叫简单模式,
    客户端发送一次,服务端返回一次,类似于接口请求

    2. 客户端发送一个请求包含两个数字,服务端返回多次,第一次返回两数子和,第二次返回两数字乘,
    这种叫服务端流模式,形象点说就是服务端向客户端搭了一根单向水管,可以不停的往客户端发送数据,
    客户端不停的接收,直到接收到服务端发送的结束标记后停止接收
    使用场景:
    客户端请求一个数据列表,但是这个数据太多了,不可能一次返回,就可以利用这种模式,
    服务端一次返回100条数据,前端一直接收处理

    3. 客户端发送了很多次数据,数据是单个数字,服务端不停的接收数据,客户端发送结束后服务端返回所有数据的总和,
    这就是客户端流模式,形象点说就是客户端往服务端搭了一个单向的水管,可以不停的往服务端发送数据,
    服务端不停的接收,直到接收到客户端发送的结束标记后停止接收,处理完数据后一次性返回给客户端,

    4. 客户端分多次发送数据给服务端,每次数据是两个数,服务端收到数据后多次返回给服务端,每次返回两个数之和,
    客户端可以多次给服务端发送数据,服务端可以多次返回数据,这就是双向流模式,双方都需要同时处理发送数据和接收数据,
    直到双方通道流关闭

    利用calculator.proto生成go中间代码
    在项目跟目录执行:

    protoc -I ./ ./calculator.proto  --go_out=plugins=grpc:./server/gencode
    protoc -I ./ ./calculator.proto  --go_out=plugins=grpc:./client/gencode

    分别在 ./server/gencode 和 ./client/gencode 两个目录生成了相同的go中间代码

    有了中间代码后就可以编写服务端server.go了,由于篇幅限制,这里就不贴完整代码了,只对几个关键点做分析
    导入中间代码

    import pb "rpcserver/gencode"

    定义了一个server,继承自 UnimplementedCalculatorServer

    type server struct {
        pb.UnimplementedCalculatorServer
    }

    这里有个技巧,打开calculator.pb.go你会发现,
    UnimplementedCalculatorServer类已经"实现"了我们在calculator.proto中定义的所有个方法

    type UnimplementedCalculatorServer struct {
    }
    func (*UnimplementedCalculatorServer) Add(ctx context.Context, req *TwoNum) (*Response, error) {
        return nil, status.Errorf(codes.Unimplemented, "method Add not implemented")
    }
    ....

    如果你是新手,可以直接粘贴到server,稍作修改就可以了,函数体还是得自己写

    func (s *server) Add(ctx context.Context, in *pb.TwoNum) (*pb.Response, error) {
        return &pb.Response{C: in.A + in.B}, nil
    }

    其实gRPC的函数不多,定义也非常清晰,比如在写下面这个方法的时候

    func (s *server) GetStream(in *pb.TwoNum, pipe pb.Calculator_GetStreamServer) error {
        _ = pipe.Send(&pb.Response{C: in.A + in.B})
        time.Sleep(time.Second * 2)
        _ = pipe.Send(&pb.Response{C: in.A * in.B})
        return nil
    }

    我也不知道有Send方法,如果用的GoLand,pipe点一下,能用的函数就出来了,就几个,一看就知道什么作用,
    全程都没有用到godoc,当然我还是推荐你仔细看一下文档 https://godoc.org/google.golang.org/grpc

    在来看一下客户端client.go
    导入中间代码

    import pb "rpcclient/gencode"

    客户端就不说了,看一下代码吧

  • 相关阅读:
    POJ 1811 Prime Test(Miller-Rabin & Pollard-rho素数测试)
    HDU 3037 Saving Beans(Lucas定理模板题)
    HDU 5029 Relief grain(离线+线段树+启发式合并)(2014 ACM/ICPC Asia Regional Guangzhou Online)
    Java进阶(二)当我们说线程安全时,到底在说什么
    UML建模一般流程
    Spring事务管理(详解+实例)
    Spring 的 BeanPostProcessor接口实现
    Spring中ApplicationContext和beanfactory区别
    使用Maven Release插件发布项目
    tair与redis比较总结
  • 原文地址:https://www.cnblogs.com/codeAB/p/12643426.html
Copyright © 2011-2022 走看看