Add the protocol-comparison module
This commit is contained in:
63
protocol-comparison/docs/05-choosing.md
Normal file
63
protocol-comparison/docs/05-choosing.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# 5. Choosing
|
||||
|
||||
Previous: [4. Back-pressure](04-backpressure.md)
|
||||
|
||||
---
|
||||
|
||||
## The decision table
|
||||
|
||||
| If | Pick | Because |
|
||||
|---|---|---|
|
||||
| Service-to-service RPC, polyglot team, you want a schema | **gRPC** | The `.proto` is a contract other languages generate from. Deadlines are absolute and propagate. Boot 4 makes it a first-class starter. |
|
||||
| A stream whose consumer can fall behind | **RSocket** | `request(n)` is the only demand signal that crosses the wire. 100 vs 1.3 million is not a tuning difference. |
|
||||
| A browser is one of the peers | **WebSocket**, with STOMP on it | gRPC needs grpc-web and a proxy. RSocket over WebSocket works but the client ecosystem is thin. |
|
||||
| Server pushes, client never speaks | **none of these** — use SSE | See [`../sse-websocket`](../../sse-websocket/README.md). |
|
||||
| You want the lowest possible median latency and control both ends | **raw WebSocket** | It is fastest here because it does the least. Read the p99 before deciding that is what you want. |
|
||||
| Long-lived bidirectional exchange with independent streams | **RSocket channel** or **gRPC bidi** | Both give you two independent streams; only RSocket gives each of them demand. |
|
||||
|
||||
## What each one really costs
|
||||
|
||||
**gRPC** costs a build step, a schema you must version, and an operational story for HTTP/2 through
|
||||
your proxies. In exchange you get the best-supported cross-language RPC there is, and deadlines
|
||||
— which is a bigger deal than it sounds, because an absolute deadline that propagates across
|
||||
hops is the single most effective defence against one slow dependency taking down a system.
|
||||
|
||||
**RSocket** costs ecosystem. It is the least deployed of the three, the client libraries outside
|
||||
Java and JavaScript are thin, and if you are not already reactive, `Mono` and `Flux` in your
|
||||
service signatures is a real commitment. In exchange you get the only demand signalling in the
|
||||
list, plus resumption and leasing.
|
||||
|
||||
**Raw WebSocket** costs everything you then invent: routing, correlation, error shape, versioning,
|
||||
and the demand mechanism you will eventually need. That is the cost STOMP exists to prevent, and
|
||||
if you find yourself designing a text protocol with a command word at the front — as
|
||||
[`WebSocketQuoteHandler`](../src/main/java/com/ankurm/protocols/WebSocketQuoteHandler.java)
|
||||
deliberately does — that is the signal to stop and use one.
|
||||
|
||||
## Should you use any of them?
|
||||
|
||||
Three cases where the answer is no:
|
||||
|
||||
- **Request/response between two services that both speak HTTP already.** A REST endpoint with a
|
||||
`RestClient` and a timeout is fine, and everything in your organisation already knows how to
|
||||
observe, cache, proxy and debug it. Reach for gRPC when the schema or the deadline propagation
|
||||
is the thing you need, not because it benchmarks faster.
|
||||
- **Streaming that is really batching.** If the consumer processes a page at a time anyway,
|
||||
paginated HTTP has back-pressure for free: the consumer asks for the next page when it is ready.
|
||||
That is `request(n)` with a URL.
|
||||
- **Events that outlive the connection.** None of these three persist anything. A dropped
|
||||
connection loses the messages in flight. If that matters, the answer is a broker —
|
||||
[`../kafka-basics`](../../kafka-basics/README.md),
|
||||
[`../rabbitmq`](../../rabbitmq/README.md), and the comparison in
|
||||
[`../broker-comparison`](../../broker-comparison/README.md).
|
||||
|
||||
## And the benchmark caveat, one more time
|
||||
|
||||
Every number in this module was measured with client and server in one JVM on one machine. That
|
||||
deletes the network, which is where protobuf's 35 bytes would pay and where the tail latencies
|
||||
would look completely different. The measurement that does transfer is
|
||||
[chapter 4](04-backpressure.md), because "how many did the server produce for a consumer that
|
||||
wanted a hundred" is a property of the protocol and not of the link.
|
||||
|
||||
---
|
||||
|
||||
Previous: [4. Back-pressure](04-backpressure.md)
|
||||
Reference in New Issue
Block a user