gRPC阅读日记(七)客户端的RPC构建
Client-side streaming RPC
客户端的流式方法RecordRoute跟服务端的相似,除了我们只传了context,获取到RouteGuide_RecordRouteClient流对象回来。流可以让我们既可以写也可以读消息。
// Create a random number of random points
r := rand.New(rand.NewSource(time.Now().UnixNano()))
pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points
var points []*pb.Point
for i := 0; i < pointCount; i++ {
points = append(points, randomPoint(r))
}
log.Printf("Traversing %d points.", len(points))
stream, err := client.RecordRoute(context.Background())
if err != nil {
log.Fatalf("%v.RecordRoute(_) = _, %v", client, err)
}
for _, point := range points {
if err := stream.Send(point); err != nil {
log.Fatalf("%v.Send(%v) = %v", stream, point, err)
}
}
reply, err := stream.CloseAndRecv()
if err != nil {
log.Fatalf("%v.CloseAndRecv() got error %v, want %v", stream, err, nil)
}
log.Printf("Route summary: %v", reply)
RouteGuide_RecordRouteClient有Send方法,可以发送请求给server,一旦我们用Send发完了请求,让gRPC知道我们已经结束写阶段,希望获取响应了,就能从CloseAndRecv()返回的err得治RPC状态。如果状态是nil,那么CloseAndRecv()返回的就是有效的服务响应。
Bidirectional streaming RPC
双向流RPC RouteChat(),使用了goroutine去对steam做读,然后主的goroutine去做写,最后client端洗完了,调用了CloseSend()最后还做了线程同步,等goroutine都结束。
stream, err := client.RouteChat(context.Background())
waitc := make(chan struct{})
go func() {
for {
in, err := stream.Recv()
if err == io.EOF {
// read done.
close(waitc)
return
}
if err != nil {
log.Fatalf("Failed to receive a note : %v", err)
}
log.Printf("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude)
}
}()
for _, note := range notes {
if err := stream.Send(note); err != nil {
log.Fatalf("Failed to send a note: %v", err)
}
}
stream.CloseSend()
<-waitc
外加再补充一句,客户端和服务端请求和响应的消息顺序一直是有序的,但是他们处理消息的顺序可以in any orider。这句话基础教程里提了好多次了
下一期讲gRPC basics tutorial的总结, respect!!!










网友评论