One RPC, one stream, one pipe for many
HTTP/2 multiplexes many independent streams over one long-lived TCP connection, and gRPC maps exactly one RPC to one stream — so a hundred concurrent calls share a single pipe instead of a hundred sockets.
Our encoded Greeting{name="Ada"} bytes would crawl one-at-a-time over a raw socket, exactly the HTTP/1.1 trap — so gRPC rides HTTP/2, which lets a hundred calls interleave down a single connection.
Scene 04
One RPC, one stream, one pipe for many
- Watch
- Try it
- Predict
- Capture
gRPC doesn't run on raw TCP or HTTP/1.1 — it runs on HTTP/2. Here's why that matters. Picture one long-lived TCP connection (the pipe) that several calls share at once. Each call gets its own lane down that pipe: that lane is a stream. Watch three RPCs — three greet("Ada") calls — each open a stream and send their bytes down the one connection. The bytes travel in small labeled blocks called frames: a HEADERS frame opens each stream, then a DATA frame carries the payload. Notice the inset: that DATA frame still contains the scene-3 Greeting{name="Ada"} bytes, still wrapped in the scene-2 length prefix — every layer you built is nested inside this one. The streams interleave: a frame from one call, then a frame from another, all woven down the single pipe.
Highlighted lines are the ones running in the diagram right now.
def getConnection():if self.http2:# one long-lived conn, opened lazily onceif self.conn is None:self.conn = tcp.dial(self.target)return self.conn # every call shares itelse: # HTTP/1.1# an in-flight call needs its own socketsock = tcp.dial(self.target)self.sockets.append(sock)return sock
def startCall(method, message):conn = channel.getConnection()# client-initiated streams get odd ids 1,3,5,...stream = conn.openStream(id = next_odd_id())stream.send(HEADERS, {':path': method,'grpc-timeout': deadline.remaining(),})stream.send(DATA, frame(message))return stream # one call == one stream
def frame(message):payload = protobuf.encode(message)# gRPC wire prefix: 1 flag byte + 4-byte big-endian lenprefix = bytes([0]) + uint32_be(len(payload))return prefix + payload # carried inside a DATA frame
Where this sits in Build a gRPC-style RPC framework
Scene 04 of 14, in the The transport act — HTTP/2 streams and the four shapes of a call.. HTTP/2 multiplexes many independent streams over one long-lived TCP connection; gRPC maps one RPC to one stream. A hundred calls share one pipe, not a hundred sockets.
Up next. Now that an RPC is just a flow of DATA frames, the number and direction of those frames is a free design knob — which quietly gives us four different shapes of call for the price of one transport.
All 14 scenes in Build a gRPC-style RPC framework · Every curriculum