jchw 7 hours ago

Personally, I'd like to see more HTTP/2 support. I think HTTP/2's duplex streams would be useful, just like SSE. In theory, WebSockets do cover the same ground, and there's also a way to use WebSockets over HTTP/2 although I'm not 100% sure how that works. HTTP/2 though, elegantly handles all of it, and although it's a bit complicated compared to HTTP/1.1, it's actually simpler than WebSockets, at least in some ways, and follows the usual conventions for CORS/etc.

The problem? Well, browsers don't have a JS API for bidirectional HTTP/2 streaming, and many don't see the point, like this article expresses. NGINX doesn't support end-to-end HTTP/2. Feels like a bit of a shame, as the streaming aspect of HTTP/2 is a more natural evolution of the HTTP/1 request/response cycle versus things like WebSockets and WebRTC data channels. Oh well.

  • withinboredom 6 hours ago

    Why would you use nginx these days anyway? Caddy is ~4x the performance on proxying in my tests.

    • evalijnyi 6 hours ago

      Is it just me or did anyone else completely miss Caddy for it's opening sentence?

      >Caddy is a powerful, extensible platform to serve your sites, services, and apps, written in Go.

      To me it reads that if your application is not written in Go, don't bother

      • unification_fan 6 hours ago

        Why should a reverse proxy give a single shit about what your lang application is written in

        • evalijnyi 6 hours ago

          It shouldn't, which is why I think wording there is strange. Nginx doesen't market itself as "platform to serve your sites, services, and apps, written in C". Reading the first sentence I don't even know what Caddy is, what does a platform mean in this context? Arriving on Nginx's site the first sentence visible to me is

          >nginx ("engine x") is an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server.

          Which is perfect

          • suraci 5 hours ago

            when it says 'written in Go', the subtext is - i'm fast, i'm new, i'm modern, go buddies love me please

            the better one is 'written in rust', the subtext is - i'm fast, i'm new, i'm futurism, and i'm memory-safe, rust buddies love me please

            --- cynicism end ---

            i do think sometimes it's worth to note the underlying tech stack, for example, when a web server claims it's based on libev, i know it's non-blocking

            • jchw 3 hours ago

              Back when Caddy first came out over 10 years ago, the fact that it was written in Go was just simply more notable. For Go, it also at least tells you the software is in a memory-safe programming language. Now neither of those things is really all that notable, for new software.

treve 8 hours ago

First 80% of the article was great, but it ends a bit handwavey when it gets to its conclusion.

One thing the article gets wrong is that non-encrypted HTTP/2 exists. Not between browsers, but great between a load balancer and your application.

  • tuukkah 6 hours ago

    Do you want to risk the complexity and potential performance impact from the handshake that the HTTP/2 standard requires for non-encrypted connections? Worst case, your client and server toolings clash in a way that every request becomes two requests (before the actual h2c request, a second one for the required HTTP/1.1 upgrade, which the server closes as suggested in the HTTP/2 FAQ).

  • byroot 5 hours ago

    > One thing the article gets wrong is that non-encrypted HTTP/2 exists

    Indeed, I misread the spec, and added a small clarification to the article.

  • fragmede 8 hours ago

    Not according to Edward Snowden, if you're Yahoo and Google.

    • ChocolateGod 8 hours ago

      You can just add encryption to your backend private network (e.g. Wireguard)

      Which has the benefit of encrypting everything and avoids the overhead of starting a TLS socket for every http connection.

Animats 8 hours ago

The amusing thing is that HTTP/2 is mostly useful for sites that download vast numbers of tiny Javascript files for no really good reason. Like Google's sites.

  • paulddraper 8 hours ago

    Or small icon/image files.

    Anyone remember those sprite files?

    • cyberpunk 8 hours ago

      You ever had to host map tiles? Those are the worst!

miyuru 8 hours ago

The TLS requirement from HTTP2 also hindered http2 origin uptake. The TLS handshake adds latency and is unnecessary on some instances. (This is mentioned in heading "Extra Complexity" in the article)

  • tankenmate 8 hours ago

    For HTTP/3 you get 0-RTT however which largely mitigates this.

    • stavros 7 hours ago

      0-RTT resumption (unless I'm mistaken), which doesn't help with the first connection (but that might be OK).

hiAndrewQuinn 7 hours ago

The maximum number of connections thing in HTTP/1 always makes me think of queuing theory, which gives surprising conclusions like how adding a single extra teller at a one-teller bank can cut wait times by 50 times, not just by 2.

However, I think the problem is the Poisson process isn't really the right process to assume. Most websites which would run afoul of the 2/6/8/etc connections being opened are probably trying to open up a lot of connections at the same time. That's very different from situations where only 1 new person arrives every 6 minutes on average, and 2 new people arriving within 1 second of each other is a considerably rarer event.

[1]: https://www.johndcook.com/blog/2008/10/21/what-happens-when-...

feyman_r 8 hours ago

CDNs like Akamai still don’t support H2 back to origins.

That’s likely not because of the wisdom in the article per se, but because of rising complexity in managing streams and connections downstream.

awinter-py 9 hours ago

plus in my experience some h2 features behave oddly with load balancers

I don't understand this super well, but could not get keepalives to cross the LB boundary w/ GCP

  • _ache_ 7 hours ago

    HTTP keepalive it a feature from HTTP 1.1, not HTTP2.

kam1kazer an hour ago

nah, I'm using HTTP/3 everywhere

chucky_z 9 hours ago

gRPC?

  • agf 8 hours ago

    Surprised not to see this mentioned in the article.

    Lots of places (including a former employer) have done tons of work to upgrade internal infrastructure to support HTTP/2 just so they could use gRPC. The performance difference from JSON-over-HTTP APIs was meaningful for us.

    I realize there are other solutions but this is a common one.

LAC-Tech 8 hours ago

Personally, this lack of support doesn’t bother me much, because the only use case I can see for it, is wanting to expose your Ruby HTTP directly to the internet without any sort of load balancer or reverse proxy, which I understand may seem tempting, as it’s “one less moving piece”, but not really worth the trouble in my opinion.

That seems like a massive benefit to me.

a-dub 7 hours ago

i think it probably varies from workload to workload. reducing handshake time and header compression can have substantial effects.

it's a shame server side hunting/push never caught on. that was always one of the more interesting features.

  • KingMob 6 hours ago

    It didn't catch on because it was hard to see the benefits, and if done incorrectly, could actually make things slightly slower.

    Essentially, the server had to do things like compute RTT and understand the status of the browser's cache to do optimal push.

wczekalski 8 hours ago

It is very useful for long lived (bidirectional) streams.

  • m00x 8 hours ago

    Only if you're constrained on connections. The reason that HTTP2 is much better for websites is because of the slow starts of TCP connections. If you're already connected, you don't suffer those losses, and you benefit from kernel muxing.

_ache_ 7 hours ago

I remember been bashed on HN saying that HTTP is hard. Yet, I saw non-sens here in the comment about HTTP. The whole article is good but:

> HTTP/2 is fully encrypted, so you need all your application servers to have a key and certificate

Nope. h2c is a thing and is official. But the article is right, the value HTTP/2 provides isn't for LAN, so HTTP 1.1 or HTTP/2 it doesn't matter much.

HTTP/3 however, is fully encrypted. h3c doesn't exists. So yeah, HTTP3 slower you connection, it isn't suited for LAN and should not be used.

BUT if you actually want to encrypt even in you LAN, use HTTP/3, not HTTP/2 encrypted. You will have a small but not negligible gain from 0-RTT.

  • gmokki 5 hours ago

    I would not use http/3 for lan. Even the latest Linux kernels struggle with it. Http/1 aka TCP has fully supported encryption and other offload support. UDP consumes still much more CPU for same amount of traffic.

    • _ache_ 3 hours ago

      Do you have source for that? I'm very interested. There is no technical reason for UDP to be slower than TCP (at CPU level).

      The only field that is computed in UDP is checksum and the same exists in TCP and it must be recomputed each time someone actually re-route the packet (eg: bridge to VM) since TTL is decreased.

      So I doubt your assertion.

      _____

      Writing my comment I understood what your are talking about. There is a bunch of encryption done at user mode in HTTP/3 that doesn't need to be done in user mode. In HTTP/2 it was sometime done in kernel mode (kTTL), so was quicker. The slowness comes for the CPU needed it to be copied out of kernel mode. I didn't follow the whole story so I trust you on this.

Guthur 8 hours ago

The RFC said "SHOULD not" not "MUST not" couldn't we have just ignored the 2 connection limit?

  • KingMob 6 hours ago

    That's what browsers actually did.

lmm 8 hours ago

I think this post gets the complexity situation backwards. Sure, you can use a different protocol between your load balancer and your application and it won't do too much harm. But you're adding an extra protocol that you have to understand, for no real benefit.

(Also, why do you even want a load balancer/reverse proxy, unless your application language sucks? The article says it "will also take care of serving static assets, normalize inbound requests, and also probably fend off at least some malicious actors", but frankly your HTTP library should already be doing all of those. Adding that extra piece means more points of failure, more potential security vulnerabilities, and for what benefit?)

  • harshreality 8 hours ago

    > why do you even want a load balancer/reverse proxy, unless your application language sucks?

    Most load balancer/reverse proxy applications also handle TLS. Security-conscious web application developers don't want TLS keys in their application processes. Even the varnish authors (varnish is a load balancer/caching reverse proxy) refused to integrate TLS support because of security concerns; despite being reverse-proxy authors, they didn't trust themselves to get it right.

    An application can't load-balance itself very well. Either you roll your own load balancer as a separate layer of the application, which is reinventing the wheel, or you use an existing load balancer/reverse proxy.

    Easier failover with fewer (ideally zero) dropped requests.

    If the app language isn't compiled, having it serve static resources is almost certainly much slower than having a reverse proxy do it.

    • lmm 8 hours ago

      > Security-conscious web application developers don't want TLS keys in their application processes.

      If your application is in a non-memory-safe language, sure (but why would you do that?). Otherwise I would think the risk is outweighed by the value of having your connections encrypted end-to-end. If your application process gets fully compromised then an attacker already controls it, by definition, so (given that modern TLS has perfect forward secrecy) I don't think you really gain anything by keeping the keys confidential at that point.

      • nickelpro 8 hours ago

        I write application servers for a living, mostly for Python but previously for other languages.

        Nobody, nobody, writes application servers with the intent of having them exposed to the public internet. Even if they're completely memory safe, we don't do DOS protections like checking for reasonable header lengths, rewriting invalid header fields, dropping malicious requests, etc. Most application servers will still die to slowloris attacks. [1]

        We don't do this because it's a performance hog and we assume you're already reverse proxying behind any responsible front-end server, which all implement these protections. We don't want to double up on that work. We implement the HTTP spec with as low overhead as possible, because we expect to have pipelined HTTP/1.1 connections from a load balancer or other reverse proxy.

        Your application server, Gunicorn, Twisted, Uvicorn, whatever, does not want to be exposed to the public internet. Do not expose it to the public internet.

        [1]: https://en.wikipedia.org/wiki/Slowloris_(cyber_attack)

        • mr_person 3 hours ago

          As someone who designs load-balancer solutions for a living I cannot agree with this more.

          I likewise assume that all servers are insecure, always, and we do not want them exposed without a sane load balancer layer.

          Your server was probably not made to be exposed to the public internet. Do not expose it to the public internet.

      • kreetx 7 hours ago

        You use a reverse proxy because whenever you "deploy to prod", you'll be using one anyway, thus by not having TLS in your app, you had not built something you don't actually need.

      • harshreality 7 hours ago

        Speculative execution cpu bugs. Or whatever the next class of problems is that can expose bits of process memory without software memory bugs.

        That's already a fringe case. Do you really think everyone's writing web applications in a language like rust without any unsafe (or equivalent)?

  • Galanwe 8 hours ago

    > Also, why do you even want a load balancer/reverse proxy, unless your application language sucks

    - To terminate SSL

    - To have a security layer

    - To load balance

    - To have rewrite rules

    - To have graceful updates

    - ...

    • tuukkah 8 hours ago

      - To host multiple frontends, backends and/or APIs under one domain name

    • lmm 8 hours ago

      > To terminate SSL

      To make sure that your connections can be snooped on over the LAN? Why is that a positive?

      > To have a security layer

      They usually do more harm than good in my experience.

      > To load balance

      Sure, if you're at the scale where you want/need that then you're getting some benefit from that. But that's something you can add in when it makes sense.

      > To have rewrite rules > To have graceful updates

      Again I would expect a HTTP library/framework to handle that.

      • Galanwe 7 hours ago

        > > To terminate SSL

        > To make sure that your connections can be snooped on over the LAN? Why is that a positive?

        Usually your "LAN" uses whole link encryption, so that whatever is accessed in your private infrastructure network is encrypted (being postgres, NFS, HTTP, etc). If that is not the case, then you have to configure encryption at each service level, which is both error prone, time consuming, and not always possible. If that is not case then you can have internal SSL certificates for the traffic between RP and workers, workers and postgres, etc.

        Also you don't want your SSL server key to be accessible from business logic as much as possible, having an early termination and isolated workers achieves that.

        Also, you generally have workers access private resources, which you don't want exposed on your actual termination point. It's just much better to have a public termination point RP with a private iface sending requests to workers living in a private subnet accessing private resources.

        > > To have a security layer

        > They usually do more harm than good in my experience.

        Right, maybe you should detail your experience, as your comments don't really tell much.

        > To have rewrite rules

        > To have graceful updates

        > > Again I would expect a HTTP library/framework to handle that.

        HTTP frameworks handle routing _for themselves_, this is not the same as rewrite rules which are often used to glue multiple heterogeneous parts together.

        HTTP frameworks are not handling all the possible rewriting and gluing for the very reason that it's not a good idea to do it at the logic framework level.

        As for graceful updates, there's a chicken and egg problem to solve. You want graceful update between multiple versions of your own code / framework. How could that work without a third party balancing old / new requests to the new workers one at a time.

      • harshreality 7 hours ago

        > To make sure that your connections can be snooped on over the LAN? Why is that a positive?

        No, to keep your app from having to deal with SSL. Internal network security is an issue, but sites that need multi-server architectures can't really be passing SSL traffic through to the application servers anyway, because SSL hides stuff that's needed for the load balancers to do their jobs. Many websites need load balancers for performance, but are not important enough to bother with the threat model of an internal network compromise (whether it's on the site owner's own LAN, or a bare metal or VPS hosting vlan).

        > Sure, if you're at the scale where you want/need that then you're getting some benefit from that. But that's something you can add in when it makes sense.

        So why not preface your initial claims by saying you trust the web app to be secure enough to handle SSL keys, and a single instance of the app can handle all your traffic, and you don't need high availability in failure/restart cases?

        That would be a much better claim. It's still unlikely, because you don't control the internet. Putting your website behind Cloudflare buys you some decreased vigilance. A website that isn't too popular or attention-getting also reduces the risk. However, Russia and China exist (those are examples only, not an exclusive list of places malicious clients connect from).

      • ahoka 2 hours ago

        You usually re-encrypt your traffic after the GW, either by using an internal PKI and TLS or some kind of encapsulation (IPSEC, etc).

        Security and availability requirements might vary, so much to argue about. Usually you have some kind of 3rd party service you want to hide, control CORS, Cache-Control, etc headers uniformly, etc. If you are fine with 5-30 minutes of outage (or until someone notices and manually restores service), then of course you don’t need to load balance. But you can imagine this not being the case at most companies.

      • fragmede 8 hours ago

        You terminate SSL as close to the user as possible, because that round trip time is greatly going to affect the user experience. What you do between your load balancer and application servers is up to you, (read: should still be encrypted) but terminating SSL asap is about user experience.

      • unification_fan 6 hours ago

        Tell me you never built an infrastructure without telling me you never built an infrastructure

        The point being that all the code on the stack is not necessarily yours

        • lmm 4 hours ago

          I've built infrastructure. Indeed I've built infrastructure exactly like this, precisely because maintaining encryption all the way to the application server was a security requirement (this was a system that involved credit card information). It worked well.

  • toast0 8 hours ago

    Load balancers are nice to have if you want to move traffic from one machine to another. Which sometimes needs to happen even if your application language doesn't suck and you can hotload your changes... You may still need to manage hardware changes, and a load balancer can be nice for that.

    DNS is usable, but some clients and recursive resolvers like to cache results for way beyond the TTL provided.

  • pixelesque 8 hours ago

    > Sure, you can use a different protocol between your load balancer and your application and it won't do too much harm. But you're adding an extra protocol that you have to understand, for no real benefit.

    Well, that depends...

    At a certain scale (and arguably, not too many people will ever need to think about this), using UNIX sockets (instead of HTTP TCP) between the application and load balancer can be faster in some cases, as you don't go through the TCP stack...

    > Also, why do you even want a load balancer/reverse proxy, unless your application language sucks?

    Erm... failover... ability to do upgrades without any downtime... it's extra complexity yes, but it does have some benefits...

    • lmm 8 hours ago

      > At a certain scale (and arguably, not too many people will ever need to think about this), using UNIX sockets (instead of HTTP TCP) between the application and load balancer can be faster in some cases, as you don't go through the TCP stack...

      Sure (although as far as I can see there's no reason you can't keep using HTTP for that). You can go even further and use shared memory (I work for a company that used Apache with Jk back in the day). But that's an argument for using a faster protocol because you're seeing a benefit from it, not an argument for using a slower protocol because you can't be bothered to implement the latest standard.

      • tuukkah 7 hours ago

        > using a slower protocol because you can't be bothered to implement the latest standard.

        I thought we were discussing HTTP/2 but now you seem to be invoking HTTP/3? It's even faster indeed but brings a whole lot of baggage with it. Nice comparison point though: Do you want to add the complexity of HTTP/2 or HTTP/3 in your backend? (I don't.)

  • guappa 6 hours ago

    C fast, the rest slow. You don't want to serve static assets in non-C.

  • tuukkah 8 hours ago

    Answers from the article - the "extra" protocol is just HTTP/1.1 and the reason for a load balancer is the ability to have multiple servers:

    > But also the complexity of deployment. HTTP/2 is fully encrypted, so you need all your application servers to have a key and certificate, that’s not insurmountable, but is an extra hassle compared to just using HTTP/1.1, unless of course for some reasons you are required to use only encrypted connections even over LAN.

    > So unless you are deploying to a single machine, hence don’t have a load balancer, bringing HTTP/2 all the way to the Ruby app server is significantly complexifying your infrastructure for little benefit.

    • conradludgate 8 hours ago

      I've deployed h2c (cleartext) in many applications. No tls complexity needed

      • tuukkah 7 hours ago

        Good to know - neither the parent nor the article mention this. h2c seems to have limited support by tooling (e.g. browsers, curl), which is a bit discouraging.

        EDIT: Based on the HTTP/2 FAQ, pure h2c is not allowed in the standard as it requires you to implement some HTTP/1.1 upgrade functionality: https://http2.github.io/faq/#can-i-implement-http2-without-i...

        • _ache_ 7 hours ago

          Why do you think that curl doesn't support h2c ?

          It does. Just use `--http2` or `--http2-prior-knowledge`, curl deduce the clear or not clear by `http` or `https` URL protocol prefix (clear the default).

          • tuukkah 6 hours ago

            I said limited support and gave curl as an example because curl --http2 sends a HTTP/1.1 upgrade request first so fails in a purely HTTP/2 environment.

            Thanks for bringing up --http2-prior-knowledge as a solution!