gRPC には、当然ながらクライアントサイドでタイムアウトが設定できます。このとき、HTTP/2 上でどういうフレームが流れるのかを整理してみます。
タイムアウト設定
golang
Golang の場合は、 context.WithTimeout を使ってタイムアウトを指定する。
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
req := &pb.EchoRequest{Message: message}
node
node.js の場合は、CallOptions で指定することになります。
const timeout = 2000 // milliseconds client.SayHello( { name: "kiririmode" }, { deadline: Date.now() + timeout }, (err, res) => { if (err) { console.log(err) return } console.log(res) } )
HTTP/2 での挙動
WireShark でパケットキャプチャをした結果が以下になります。
[1] となっており、今回の Unary Call は stream 1 が使われていることがわかります。

まず、リクエストヘッダを覗いて見ましょう。

Header フレームの中に grpc-timeout ヘッダが存在しており、その値が 2S となっていることがわかります。このように、gRPC におけるタイムアウトは Timeout → "grpc-timeout" TimeoutValue TimeoutUnit という形のヘッダとして表現されると定義されています。詳細は grpc/PROTOCOL-HTTP2.md at master · grpc/grpc · GitHub に記載があります。
今回はタイムアウトを 2 秒としているので、当該ヘッダの値は 2S (2秒) となっています。
そしておおよそ 2 秒後に、クライアントから RST_STREAM フレームが送信されています。

これにより、今回使用した stream 1 は closed state に遷移し、完全に stream としてのライフサイクルを終えたことがわかります。
stream の状態遷移については、RFC 7540 を参照してください。
+--------+
send PP | | recv PP
,--------| idle |--------.
/ | | \
v +--------+ v
+----------+ | +----------+
| | | send H / | |
,------| reserved | | recv H | reserved |------.
| | (local) | | | (remote) | |
| +----------+ v +----------+ |
| | +--------+ | |
| | recv ES | | send ES | |
| send H | ,-------| open |-------. | recv H |
| | / | | \ | |
| v v +--------+ v v |
| +----------+ | +----------+ |
| | half | | | half | |
| | closed | | send R / | closed | |
| | (remote) | | recv R | (local) | |
| +----------+ | +----------+ |
| | | | |
| | send ES / | recv ES / | |
| | send R / v send R / | |
| | recv R +--------+ recv R | |
| send R / `----------->| |<-----------' send R / |
| recv R | closed | recv R |
`----------------------->| |<----------------------'
+--------+
send: endpoint sends this frame
recv: endpoint receives this frame
H: HEADERS frame (with implied CONTINUATIONs)
PP: PUSH_PROMISE frame (with implied CONTINUATIONs)
ES: END_STREAM flag
R: RST_STREAM frame
Figure 2: Stream States
まとめ
client で gRPC timeout を指定した場合、
- client からは
grpc-timeoutヘッダによってサーバにタイムアウト時間が通知される - 実際に client でタイムアウトすると、client から
END_STREAMframe が送出され、stream は closed 状態に遷移し終了する