Server stream
gRPC
除了常规的 unary
调用之外还支持服务端推送,在一些特定场景下还是很有用的。
网络异常,图片无法展示
|
func (o *Order) ServerStream(in *v1.OrderApiCreate, rs v1.OrderService_ServerStreamServer) error { for i := 0; i < 5; i++ { rs.Send(&v1.Order{ OrderId: in.OrderId, Reason: nil, }) } return nil }
服务端的推送如上所示,调用 Send
函数便可向客户端推送。
for { msg, err := rpc.RecvMsg() if err == io.EOF { marshalIndent, _ := json.MarshalIndent(msgs, "", "\t") fmt.Println(msg) return } }
客户端则通过一个循环判断当前接收到的数据包是否已经截止来获取服务端消息。
为了能更直观的展示这个过程,优化了之前开发的一个 gRPC
客户端,可以直观的调试 stream
调用。
网络异常,图片无法展示
|
上图便是一个服务端推送示例。
Client Stream
网络异常,图片无法展示
|
除了支持服务端推送之外,客户端也支持。
客户端在同一个连接中一直向服务端发送数据,服务端可以并行处理消息。
// 服务端代码 func (o *Order) ClientStream(rs v1.OrderService_ClientStreamServer) error { var value []int64 for { recv, err := rs.Recv() if err == io.EOF { rs.SendAndClose(&v1.Order{ OrderId: 100, Reason: nil, }) log.Println(value) return nil } value = append(value, recv.OrderId) log.Printf("ClientStream receiv msg %v", recv.OrderId) } log.Println("ClientStream finish") return nil } // 客户端代码 for i := 0; i < 5; i++ { messages, _ := GetMsg(data) rpc.SendMsg(messages[0]) } receive, err := rpc.CloseAndReceive()
代码与服务端推送类似,只是角色互换了。
网络异常,图片无法展示
|