Bidirectional streaming RPCs

2 phút đọcSeries: Tìm hiểu gRPC - Qua các ví dụ bằng Golang1 lượt xem

Unary RPCs là phương thức gọi function từ xa trong đó cả hai bên gửi một chuỗi tin nhắn bằng read-write stream. Hai luồng hoạt động độc lập nên server và client có thể đọc và ghi theo bất kỳ thứ tự nào họ muốn; ví dụ: server có thể đợi để nhận tất cả tin nhắn của client trước khi phản hồi hoặc có thể luân phiên đọc tin nhắn rồi viết tin nhắn, hoặc kết hợp đọc và viết . Thứ tự của tin nhắn trong mỗi luồng được giữ nguyên.

Tạo 1 file bi_stream.go tại server , trong file này , chúng ta implement function SayHelloClientBidirectionalStreaming được define trong file proto

package main

import (
    "fmt"
    pb "greet/proto"
    "io"
    "log"
)

func (s *Server) SayHelloClientBidirectionalStreaming(stream pb.GreetService_SayHelloClientBidirectionalStreamingServer) error {
    for {
       msg, err := stream.Recv()
       if err == io.EOF {
          return nil
       }
       if err != nil {
          log.Fatalf("Unary calling error %v", err)
       }
       log.Printf("Server receive %s", msg.Msg)
       if err := stream.Send(&pb.HelloResponse{Msg: fmt.Sprintf("Hello %s", msg.Msg)}); err != nil {
          return err
       }
    }
}

Tại client , chúng ta gọi đến server đang chạy ở port 8080 bằng cách tạo 1 file main.go tại folder client với nội dung:

package main

import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    pb "greet/proto"
    "io"
    "log"
    "time"
)

const port = "8080"

func main() {
    conn, err := grpc.Dial("localhost:"+port, grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
       log.Fatalf("Cannot connect with error %v", err)
    }
    defer conn.Close()

    client := pb.NewGreetServiceClient(conn)

    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    //BidirectionalStreaming
    stream, err := client.SayHelloClientBidirectionalStreaming(ctx)
    waitc := make(chan struct{})
    go func() {
       for {
          msg, err := stream.Recv()
          if err == io.EOF {
             break
          }
          if err != nil {
             log.Printf("Error %v", err)
          }
          log.Println(msg.Msg)
       }
       close(waitc)
    }()
    greets := []string{"Cuong", "Nam", "Quan"}
    for _, greet := range greets {
       if err := stream.Send(&pb.HelloRequest{Msg: greet}); err != nil {
          log.Printf("Error %v", err)
       }
       time.Sleep(time.Second)
    }

    stream.CloseSend()
    <-waitc
}

Chạy file main.go trên và quan sát kết quả

Bạn thấy bài này thế nào?