3 ms·
At Proxmox we use HTTP/2 (h2) in our backup project to asynchronously stream chunked data to the server, works great for that and wouldn't be really possible wi
by tlamponi 4y ago
At Proxmox we use HTTP/2 (h2) in our backup project to asynchronously stream chunked data to the server, works great for that and wouldn't be really possible with HTTP 1.1; at least not with major headache and extra overhead.
We also plan to closer evaluate HTTP/3 (h3) soon, mainly to see how the promised improvements, like no head of line blocking, turn out in practice for our use case.
So I'd disagree that h2 or h3 is useless "unless you're a web browser"; but sure if you use HTTP only to provide a simple text (e.g., JSON) based API it might not be _that_ relevant.
But some benefits like faster TLS setup might even make a difference there, e.g., faster initial startup, fewer packets transmitted, IIRC even packet sniffing should be a bit harder to do with h3.
If those benefits are worth it on its own, depends then probably on how easy it's to integrate in your project, iow., if your framework/standard lib/ecosystem/... already supports h3 nicely.
We use the rust hyper crate for most of our HTTP* communication, and their h3 implementation is still marked as experimental; and as we're not in a rush we'll just wait until the hyper project stabilizes h3.
- mgaunard 4y agoI don't see what's preventing HTTP 1.1 to chunk your responses. What HTTP 2 does is that it makes it possible to send multiple responses in parallel instead of one after each other.
- intelVISA 4y ago[flagged]
- tlamponi 4y agoYeah as said, we chunk backup data into (64 KiB to 4 MiB) chunks and send each in (parallel) async streams.. Chunked transfer isn't the issue, I know that would be easily dooable with h1.1, but it would be one serialized & sync stream.
- mgaunard 4y agoYou do realize you're sending it over TCP? It still ends up serialized. All you're doing is reducing the latency of the first request.
- tlamponi 4y agoNo it doesn't gets serialized just by using TCP, the multiplexed streams are still handled concurrently, better utilizing the waits that come from IO heavy workloads. Doing the same on top of http 1.1 can work but it'd be just rebuilding http 2 with more overhead; or use multiple http 1.1 connections, which takes up more OS resources and still has more overhead for binary data due to being text — and encoding to base64 then gziping or using deflate to get somewhat down im size again won't make it faster or more efficient. But yeah on package loss there's head of line blocking, which http 3 solves by using UDP and handling the reliability on the higher level.
- mgaunard 4y agoTCP must send all data in order. To implement that, all data sent out gets written to a retransmit buffer (which may be dynamically sized, but only up to a maximum), and that data only gets removed once acked by the other end. Once the retransmit buffer is full, you are unable to write more data; your TCP implementation would then most likely suspend your process and wake it up once it can write again. Your thread is spending its time waiting for the other end to ack before it can send more data, delaying any other kind of work your thread has to do (such as serving other clients). The rate at which it can write doesn't magically increase by attempting to write multiple streams concurrently; quite the opposite. The rate is controlled by the other end, and what you should do if you implement a high-performance TCP service (HTTP or not) is simply disconnect clients that require you to ever block. Now you could say, "I don't care, I write the data asynchronously". Asynchronous writes are very bad and an anti-pattern, they should typically never be used because they mean you are just queueing data indefinitely until it is eventually written, wasting massive amounts of RAM (if not taking the machine down entirely). Queues in general are serious business and require a careful design to ensure the producer doesn't produce data faster than the consumer, with adequate back-pressure algorithms. It is better to keep track of when you can write and decide on how to handle not being able to write rather than block or queue like an idiot. Multiplexing with HTTP/2 logically makes the TCP stream which is logically a spsc queue into a pseudo-mpsc queue. Those are also way more difficult to reason about to guarantee fairness and back-pressure, they're pretty much a bottleneck by design. It's just a bad idea any way you look at it.
- preseinger 4y agoan http request can take an unlimited amount of time to complete the initial response headers can arrive as fast as you like, but the body can be streamed, which can have potentially infinite data, and take potentially infinite time, and it can't be interrupted without terminating the connection altogether (before you say it: streaming response bodies are in no way abnormal, and can't be dismissed as irrelevant) as http/1 serializes requests over connections (even with chunking or whatever else) clients cannot in general re-use connections for independent requests for this reason (and others) if a client makes request A at t=1 and request B at t=2, and request A creates an unbounded length SSE response that lasts until t=999, request B should not need to wait until t=1000 to begin, yet this is what http/1 requires