Go gRPCチュートリアル-クライアントフローRPC(4)
5163 ワード
前言
前回は
シナリオシミュレーション:クライアントの大量のデータがサービス側にアップロードされます.
新規protoファイル
新規クライアント_stream.protoファイル
1.送信情報の定義
2.受信情報の定義
3.サービスメソッドを定義するRouteList
クライアントストリームrpcは、要求されたパラメータの前にstreamを追加すればよい
4.protoファイルのコンパイル
クライアントへstream.protoが存在するディレクトリ、実行命令:
Serverエンドの作成
1.当社のサービスを定義し、RouteList方法を実現する
2.gRPCサーバーの起動
サービス・エンドの実行
Clientエンドの作成
1.呼び出しサービス側RouteListメソッドの作成
2.gRPCクライアントの起動
クライアントの実行
サービス側はクライアントからデータを取得し続ける
考える
サービス側はメッセージを受信していないときにデータの受信を自発的に停止することができますか(このようなシーンはめったにありません).
答え:いいですが、クライアントコードはEOF判断に注意する必要があります.
1.サービス側のRouteListメソッドを少し修正し、データを受信するとすぐにSendAndClose()を呼び出してstreamを閉じる.
2.クライアント呼び出しRouteListメソッドの実装を少し変更する
クライアントSend()は、サービス側がメッセージが受信されない前にSendAndClose()をアクティブに呼び出してstreamを閉じるため、errがEOFであるかどうかを検出する必要がある.クライアントがSend()を実行し続けると、EOFエラーが返される.
まとめ
本編では
チュートリアルのソースアドレス:https://github.com/Bingjian-Zhu/go-grpc-example参考:gRPC公式ドキュメント中国語版
前回は
RPC
について説明しましたが、クライアントはサーバに要求を送信し、ストリームを取得して戻ってきたメッセージシーケンスを読み出します.クライアントは、返されたストリームのデータを読み出します.本編では RPC
について説明します. RPC
: RPC
とは対照的に、クライアントは絶えずサービス側にデータストリームを送信し、送信が終了した後、サービス側から応答を返す.シナリオシミュレーション:クライアントの大量のデータがサービス側にアップロードされます.
新規protoファイル
新規クライアント_stream.protoファイル
1.送信情報の定義
//
message StreamRequest{
//
string stream_data = 1;
}
2.受信情報の定義
//
message SimpleResponse{
//
int32 code = 1;
//
string value = 2;
}
3.サービスメソッドを定義するRouteList
クライアントストリームrpcは、要求されたパラメータの前にstreamを追加すればよい
service StreamClient{
// rpc, stream
rpc RouteList (stream StreamRequest) returns (SimpleResponse){};
}
4.protoファイルのコンパイル
クライアントへstream.protoが存在するディレクトリ、実行命令:
protoc --go_out=plugins=grpc:./ ./client_stream.proto
Serverエンドの作成
1.当社のサービスを定義し、RouteList方法を実現する
// SimpleService
type SimpleService struct{}
// RouteList RouteList
func (s *SimpleService) RouteList(srv pb.StreamClient_RouteListServer) error {
for {
//
res, err := srv.Recv()
if err == io.EOF {
// ,
return srv.SendAndClose(&pb.SimpleResponse{Value: "ok"})
}
if err != nil {
return err
}
log.Println(res.StreamData)
}
}
2.gRPCサーバーの起動
const (
// Address
Address string = ":8000"
// Network
Network string = "tcp"
)
func main() {
//
listener, err := net.Listen(Network, Address)
if err != nil {
log.Fatalf("net.Listen err: %v", err)
}
log.Println(Address + " net.Listing...")
// gRPC
grpcServer := grpc.NewServer()
// gRPC
pb.RegisterStreamClientServer(grpcServer, &SimpleService{})
// Serve() , Stop()
err = grpcServer.Serve(listener)
if err != nil {
log.Fatalf("grpcServer.Serve err: %v", err)
}
}
サービス・エンドの実行
go run server.go
:8000 net.Listing...
Clientエンドの作成
1.呼び出しサービス側RouteListメソッドの作成
// routeList RouteList
func routeList() {
// RouteList ,
stream, err := streamClient.RouteList(context.Background())
if err != nil {
log.Fatalf("Upload list err: %v", err)
}
for n := 0; n < 5; n++ {
//
err := stream.Send(&pb.StreamRequest{StreamData: "stream client rpc " + strconv.Itoa(n)})
if err != nil {
log.Fatalf("stream request err: %v", err)
}
}
//
res, err := stream.CloseAndRecv()
if err != nil {
log.Fatalf("RouteList get response err: %v", err)
}
log.Println(res)
}
2.gRPCクライアントの起動
// Address
const Address string = ":8000"
var streamClient pb.StreamClientClient
func main() {
//
conn, err := grpc.Dial(Address, grpc.WithInsecure())
if err != nil {
log.Fatalf("net.Connect err: %v", err)
}
defer conn.Close()
// gRPC
streamClient = pb.NewStreamClientClient(conn)
routeList()
}
クライアントの実行
go run client.go
code:200 value:"hello grpc"
value:"ok"
サービス側はクライアントからデータを取得し続ける
stream client rpc 0
stream client rpc 1
stream client rpc 2
stream client rpc 3
stream client rpc 4
考える
サービス側はメッセージを受信していないときにデータの受信を自発的に停止することができますか(このようなシーンはめったにありません).
答え:いいですが、クライアントコードはEOF判断に注意する必要があります.
1.サービス側のRouteListメソッドを少し修正し、データを受信するとすぐにSendAndClose()を呼び出してstreamを閉じる.
// RouteList RouteList
func (s *SimpleService) RouteList(srv pb.StreamClient_RouteListServer) error {
for {
//
res, err := srv.Recv()
if err == io.EOF {
// ,
return srv.SendAndClose(&pb.SimpleResponse{Value: "ok"})
}
if err != nil {
return err
}
log.Println(res.StreamData)
return srv.SendAndClose(&pb.SimpleResponse{Value: "ok"})
}
}
2.クライアント呼び出しRouteListメソッドの実装を少し変更する
// routeList RouteList
func routeList() {
// RouteList ,
stream, err := streamClient.RouteList(context.Background())
if err != nil {
log.Fatalf("Upload list err: %v", err)
}
for n := 0; n < 5; n++ {
//
err := stream.Send(&pb.StreamRequest{StreamData: "stream client rpc " + strconv.Itoa(n)})
// EOF, SendAndClose() stream, Send(), EOF , io.EOF
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("stream request err: %v", err)
}
}
//
res, err := stream.CloseAndRecv()
if err != nil {
log.Fatalf("RouteList get response err: %v", err)
}
log.Println(res)
}
クライアントSend()は、サービス側がメッセージが受信されない前にSendAndClose()をアクティブに呼び出してstreamを閉じるため、errがEOFであるかどうかを検出する必要がある.クライアントがSend()を実行し続けると、EOFエラーが返される.
まとめ
本編では
RPC
の簡単な使い方を紹介し、下編では RPC
を紹介します.チュートリアルのソースアドレス:https://github.com/Bingjian-Zhu/go-grpc-example参考:gRPC公式ドキュメント中国語版