gRPC 的4种请求/响应模式 - Go语言中文社区

gRPC 的4种请求/响应模式


参考:https://www.2cto.com/kf/201805/745745.html

gRPC简介

  gRPC(https://grpc.io)是一个由Google开发的高性能、开源、跨多种编程语言和通用的远程过程调用协议(RPC)框架,用于客户端和服务端之间的通信,使用HTTP/2协议并将ProtoBuf(https://developers.google.com/protocol-buffers)作为序列工具.


gRPC模式

demo来源:https://github.com/grpc/grpc-go/tree/master/examples/route_guide

route_guide.pb.go文件

// A feature names something at a given point.
//
// If a feature could not be named, the name is empty.
type Feature struct {
    // The name of the feature.
    Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
    // The point where the feature is detected.
    Location             *Point   `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

// Points are represented as latitude-longitude pairs in the E7 representation
// (degrees multiplied by 10**7 and rounded to the nearest integer).
// Latitudes should be in the range +/- 90 degrees and longitude should be in
// the range +/- 180 degrees (inclusive).
type Point struct {
    Latitude             int32    `protobuf:"varint,1,opt,name=latitude,proto3" json:"latitude,omitempty"`
    Longitude            int32    `protobuf:"varint,2,opt,name=longitude,proto3" json:"longitude,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}

// RouteGuideServer is the server API for RouteGuide service.
type RouteGuideServer interface {
    // A simple RPC.
    //
    // Obtains the feature at a given position.
    //
    // A feature with an empty name is returned if there's no feature at the given
    // position.
    GetFeature(context.Context, *Point) (*Feature, error)
}
  // A server-to-client streaming RPC.
    //
    // Obtains the Features available within the given Rectangle.  Results are
    // streamed rather than returned at once (e.g. in a response message with a
    // repeated field), as the rectangle may cover a large area and contain a
    // huge number of features.
    ListFeatures(*Rectangle, RouteGuide_ListFeaturesServer) error
    // A client-to-server streaming RPC.
    //
    // Accepts a stream of Points on a route being traversed, returning a
    // RouteSummary when traversal is completed.
    RecordRoute(RouteGuide_RecordRouteServer) error
    // A Bidirectional streaming RPC.
    //
    // Accepts a stream of RouteNotes sent while a route is being traversed,
    // while receiving other RouteNotes (e.g. from other users).
    RouteChat(RouteGuide_RouteChatServer) error

  gRPC主要有4种请求/响应模式,分别是

(1)简单模式(Simple RPC)
  这种模式最为传统,即客户端发起一次请求,服务端响应一个数据

func (s *routeGuideServer) GetFeature(ctx context.Context, point *pb.Point) (*pb.Feature, error) {
    for _, feature := range s.savedFeatures {
        if proto.Equal(feature.Location, point) {
            return feature, nil
        }
    }
    // No feature was found, return an unnamed feature
    return &pb.Feature{"", point}, nil
}

(2)服务端数据流模式(Server-side streaming RPC)
  这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端。

func (s *routeGuideServer) ListFeatures(rect *pb.Rectangle, stream pb.RouteGuide_ListFeaturesServer) error {
    for _, feature := range s.savedFeatures {
        if inRange(feature.Location, rect) {
            if err := stream.Send(feature); err != nil {
                return err
            }
        }
    }
    return nil
}

(3)客户端数据流模式(Client-side streaming RPC)
  与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。典型的例子是物联网终端向服务器报送数据。**
  这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端。

func (s *routeGuideServer) RecordRoute(stream pb.RouteGuide_RecordRouteServer) error {
    var pointCount, featureCount, distance int32
    var lastPoint *pb.Point
    startTime := time.Now()
    for {
        point, err := stream.Recv()
        if err == io.EOF {
            endTime := time.Now()
            return stream.SendAndClose(&pb.RouteSummary{
                PointCount:   pointCount,
                FeatureCount: featureCount,
                Distance:     distance,
                ElapsedTime:  int32(endTime.Sub(startTime).Seconds()),
            })
        }
        if err != nil {
            return err
        }
        pointCount++
        for _, feature := range s.savedFeatures {
            if proto.Equal(feature.Location, point) {
                featureCount++
            }
        }
        if lastPoint != nil {
            distance += calcDistance(lastPoint, point)
        }
        lastPoint = point
    }
}

(4)双向数据流模式(Bidirectional streaming RPC)
  顾名思义,这是客户端和服务端都可以向对方发送数据流,这个时候双方的数据可以同时互相发送,也就是可以实现实时交互。典型的例子是聊天机器人。

func (s *routeGuideServer) RouteChat(stream pb.RouteGuide_RouteChatServer) error {
    for {
        in, err := stream.Recv()
        if err == io.EOF {
            return nil
        }
        if err != nil {
            return err
        }
        key := serialize(in.Location)
                ... // look for notes to be sent to client
        for _, note := range s.routeNotes[key] {
            if err := stream.Send(note); err != nil {
                return err
            }
        }
    }
}
版权声明:本文来源简书,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://www.jianshu.com/p/c703ce510f26
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-02 14:52:58
  • 阅读 ( 1628 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢