Hacker News new | ask | show | jobs
by remram 1418 days ago
> As an aside, HTTP/2 is technically superior to WebSockets. HTTP/2 keeps the semantics of the web, while WS does not.

WTF is this? Those are different layer protocols. WebSocket can run on top of HTTP/2.

It's like saying TLS is technically superior to TCP, or IP is superior to copper cables.

Reference: https://www.rfc-editor.org/rfc/rfc8441.html

6 comments

The idea here is that http provides something like request/response semantics, methods, path, status code, etc - which are all also useful for gRPC. Websockets provide none of that - they are just message streams.

Websockets over http/2 are a new thing, and haven’t even been available at the time gRPC incepted.

I'm not sure if websockets over HTTP/2 are actually a new thing. Firefox implemented support years ago but it was disabled almost immediately afterwards because it doesn't work with proxies and has been disabled still. I think the only engine implementing it is Chrome.

As far as I know for HTTP/3 there is no way to use websockets yet.

That is their whole point. That is why they exist. Dumb reliable pipe, please keep your silly semantics away.
Hardly dumb. They include a variable length, payload masking, their own layer of fragmentation, different message type, validation (txt vs bin) and an extension framework.
For sure there are good reasons to abandon or find alternative resourceful protocols!

But in general, http is & could be the de-facto really good resourceful protocol. It's already 90% there.

Alas, the browser has been a major point of obstruction & difficulty & tension in making the most obvious most successful most clearly winning resourceful protocol at all better. The browser has sat on it's haunches & pissed around & prevented obvious & straightforward incremental growth that has happened everywhere else except the browser, such as with http trailers, such as with http2+ push. The browser has kept the de-facto resouceful protocol from developing.

You dont have to believe in http as the way to see what an oppressive & stupid shitshow this is. Being able to enhance the de-facto protocol of the web better should be in everyones interest, in a way that doesnt prevent alternatives/offshoots. But right now only alternatives & offshoots have any traction, because the browsers have all shot doen & rejected doing anything to support modern http 2+ in any real capacity. Their http inplementations are all frozen in time.

HTTP/2 provides features that websockets don't. Even if you were to use websockets over HTTP/2, you'd lose features like being able to multiplex requests _because_ it's a higher level protocol. Why is it wrong to say its better to use a more feature full and lower level protocol?
They provide different APIs. Websockets provide a bidirectional stream of messages. The messages in a given direction are always delivered in order. If they were to be suddenly reordered that would cause a lot of headaches.

While the individual messages can't be multiplexed, different websocket streams over a single HTTP/2 connection can be multiplexed.

I think websockets also provides a feature that HTTP/2 doesn't: the ability to easily push data from the server to browser javascript.

> I think websockets also provides a feature that HTTP/2 doesn't: the ability to easily push data from the server to browser javascript.

I will never stop beating this drum: Server-Sent Events and EventSource! Simple to implement, scale, support.

https://developer.mozilla.org/en-US/docs/Web/API/Server-sent... https://developer.mozilla.org/en-US/docs/Web/API/EventSource

I've used SSE and websockets a lot. I like SSE. But it has two key weaknesses compared to websockets.

Firstly, it's unidirectional. The server sends a stream of events to the client, but the client can't send anything back. That might not be a problem at a purely semantic level (maybe the client doesn't have anything to send back), but it means you can't implement application-level heartbeating or flow control in-band; there is no way for a server to know if a client is reading messages, and if it is, whether it is keeping up with the stream. You can use TCP-level state management and flow control for this, which is inadequate, because there are all sorts of failure modes it doesn't catch, or doesn't catch quickly. Or you can implement the back-channel via separate HTTP requests, which is pretty ugly.

Secondly, SSE connections are subject to the browser's HTTP connection limit - i think most browsers these days have a limit of six connections to any given origin. If you have one connection per page, the user can open six tabs, and then any further attempts to access your site, using SSE or not, will mysteriously fail, because they can't open a connection. Websockets are not subject to this limit; they have a separate per-origin limit, which is usually much larger - 200 for Firefox, 255 for Chrome (although Chrome also has a global limit of 255 websockets?). For SSE, you may be able to work around this by port or hostname sharding, or sharing a single connection using a web worker, but all of these are complicated and intrusive. Now, this conversation started with talking about HTTP/2, and HTTP/2 does solve this, because it can multiplex many SSE connections over a single TCP connection (at the cost of head-of-line blocking on packet drops). But now you're making HTTP/2 a hard requirement for deployment - fallback to HTTP/1.1 just won't work reliably.

Valid points, the request limit in particular. On the other hand, there is some smart resource management in the user agent for EventSource, IIRC, which I'm not sure exists for websockets. I feel HTTP/2 as a requirement is acceptable but that obviously depends on the use case.

That said, I still feel SSE is both underutilized and sadly unknown.

Both downsides are fixed by using http/2, right? Heartbeat seems trivial to implement using HTTP/2 PING frame. And you already mentioned the stream sharing, which IMO is much better than the state of each tab on the same website opening its own TCP socket, pretty much a resource exhaustion hell (browsers didn't implement websockets on top of h2 last time I checked).

Websockets do have an advantage over SSE: they get binary streams instead of text.

HTTP/2 doesn't fix the former downside. It doesn't give you a general bidirectional stream, so you can't implement flow control. I'm not aware of a browser API for sending (or inhibiting) HTTP/2 pings - is there one? In the absence of one, you also can't use HTTP/2 to implement an application-level heartbeat.

To expand on this a bit, a problem i have run into with SSE is that the socket is open, some part of the client (the browser or HTTP client) is reading data, but it is not being processed, because the actual application code on the client is stuck or broken or something. To deal with that, you have to be able to drive feedback from the application code on the client to the server.

Pardon my ignorance: Are messages sent through this guaranteed to arrive in order?
Yes. SSEs are just an infinite-length HTTP body formatted in a particular way. And like all HTTP bodies, they are guaranteed to arrive in the same order the bytes were sent.
Server-to-client, yes. The moment you write a little chat app that sends every line you type as separate POSTs -- which can be reordered -- you get to keep both pieces.

I wish browsers would support streaming request bodies in the fetch API. That would obsolete WebSockets practically immediately.

TCP can't multiplex. HTTP/2 runs over TCP and does multiplexing.

WebSocket can't multiplex. Nothing prevents gRPC over WebSocket implement multiplexing itself.

Except it wouldn't work with a gRPC agnostic proxy. HTTP/2 can be split up by, say, nginx and requests can be handled separately. Any custom protocol probably won't have that level of support.
Again, you're saying fiber optics provides features that telephony doesn't. The fact that telephony usually runs over copper cables, and telephony over fiber optics is a recent thing, doesn't change the fact that the comparison makes no sense.

Telephony (websockets) runs over the copper cables or fiber optics (HTTP/1 or HTTP/2).

I’m not a web developer, but that RFC, which talks about bootstrapping, talks about using the CONNECT method to “transition” to the WebSockets protocol. Which matches what I thought the CONNECT method does: Switch to a protocol that is not HTTP?

But I only skimmed the introduction, did I miss something?

normally uses GET and the Upgrade header, not CONNECT
That’s for HTTP/1.1, where WebSockets are really a completely different protocol which “hijacks” the underlying TCP or TCP+TLS stream from HTTP via the Upgrade request.

HTTP/2 has its own concept of streams, so WebSockets can run over a single HTTP/2 stream, and the linked RFC describes extending the CONNECT method to take over a single stream.

That's in a section specifically about picking the right transport. Per your example, it's like saying "TLS is technically superior to TCP, because it means our protocol can offload encryption and authentication to it".
> WebSocket can run on top of HTTP/2

Isn't "websocket" just a standard tcp socket, whose specification to instantiate it was born in a comparatively ephemeral HTTP (of whatever version) request, and which outlives the request, so isn't on top of anything other than tcp?

No, despite the name WebSockets are not plain TCP.
They're an http protocol for setting one up, you mean?

First sentence at this article:

https://en.wikipedia.org/wiki/WebSocket

No, they're more than that. After you upgrade to WebSocket you still have to speak the WebSocket protocol over TCP. It includes message framing — with different defined message types, masking, ping/pong, an extension system (including for example optional per-message compression), ...
TCP is a stream of bytes. WebSockets are message-based.