Server Streaming RPC 및 Redigo에 추진 알림 설치

3097 단어 GoRedisgRPCpubsubtech

Server Streaming RPC 및 Redigo에 추진 알림 설치


예를 들어'주문이 있으면 주문 목록을 실시간으로 업데이트한다'는 메커니즘을 세우고 싶을 때 이 기술을 사용한다.

구조



클라이언트(고객, 직원)와 백엔드 서버의 통신에는 Server Streaming RPC를, 백엔드 서버와 Redis의 통신에는 Redigo를 사용합니다.

Server Streaming RPC


Rest에서는 기본적으로 하나의 요청에 대한 응답을 되돌려주지만 gRPC의 서버 Streaming RPC를 사용할 때 서버 측에서 요청의 시간을 선택하면 여러 번 응답을 되돌려줍니다.이로써 실시간 업데이트, 알림 전송 등의 메커니즘을 세울 수 있다.

Redigo


추가 주문 방법을 요청할 때 반응하고, 골프장과 채널로 주문 리스트를 보내는 방법을 만드는 메커니즘은 어렵다.이 문제를 해결하기 위해 Redis의 Pub/Sub 기능을 활용했습니다.
Redigo는 Go를 사용하여 Redis를 조작하는 라이브러리입니다.

출처


Protocol Buffers
service BackendService {
  // 注文に反応して注文リストを返すメソッド。streamが付いている点が違う。
  rpc ListOrders (ListOrdersMessage) returns (stream ListOrdersMessageResponse){}
  // 注文するメソッド。
  rpc CreateOrder (CreateOrderMessage) returns (CreateOrderResponse){}
}

message ListOrdersMessage{
  // RedisのPubSubチャンネルを識別するためのid
  uint32 connection_id = 1;
}

message ListOrdersResponse {
  repeated string orders = 1;
}

message CreateOrderMessage{
  uint32 connection_id = 1;
  string order = 2;
}

message CreateOrderResponse{
  string create_order = 1;
}

Go
func (sc *SampleController) ListOrders(in *pb.ListOrdersMessage, server pb.Sample_ListOrdersServer) (err error) {
	// Redisに接続
	conn, err := redis.Dial("tcp", fmt.Sprintf("%s:%s", os.Getenv("REDIS_HOST"), os.Getenv("REDIS_PORT")))
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	psc := redis.PubSubConn{Conn: conn}
	psc.Subscribe(strconv.Itoa(int(in.ConnectionId)))

	for {
		switch psc.Receive().(type) {
		case redis.Message, redis.Subscription:
			log.Printf("responsed orders\n")
			readModel, err := (略:データベースから注文リストを取得する)
			if err != nil {
				return err
			}
			err = server.Send(&pb.ListOrdersResponse{
				Orders: readModel,
			})
			if err != nil {
				log.Printf("%s¥n", err)
			}
		case error:
			return
		}
	}
	return nil
}

func (sc *SampleController) CreateOrder(ctx context.Context, in *pb.CreateOrderMessage) (response *pb.CreateOrderResponse, err error) {
	ress, err := (略:データベースに注文を追加する)
	if err != nil {
		return
	}
	// 接続
	conn, err := redis.Dial("tcp", fmt.Sprintf("%s:%s", os.Getenv("REDIS_HOST"), os.Getenv("REDIS_PORT")))
	if err != nil {
		panic(err)
	}
	defer conn.Close()
	// パブリッシュ "hello"の部分は何でもいい
	_, err = redis.Int(conn.Do("PUBLISH", strconv.Itoa(int(in.ConnectionId)), "hello"))
	if err != nil {
		panic(err)
	}
	return &pb.CreateOrderResponse{
		CreateOrder: "successful",
	}, nil
}

참고 자료

  • gRPC의 Server-staring RPC를 사용한 PUSH 알림의 실현 사례
  • Redigo(6) 브라이시/자스크 라이브 사용
  • 좋은 웹페이지 즐겨찾기