8 ms·
The WebSocket Handbook
- iratewizard 5y agoHN is generally reserved for interesting articles. Not self promoting your services with a cookie cutter email harvester for your drip campaign.
- aparsons 5y agoI bit and got the book, hoping for something interesting. It’s more or less the documentation on MDN or a WS library docs rephrased. Finally, after 60 pages of docs I can Google, there’s a section called “Scaling Websockets”, which is an interesting and challenging topic. Turns out it’s one paragraph long, saying - “Yeah it’s hard. You should consider using Ably. Next book will cover it.” Shameful.
- AlexTDiaconu 5y agoHey Aparsons, thanks for your feedback. As mentioned in the post, the Handbook is not finished and we'll continue to evolve, adding more chapters, meat to the current chapters, and we have other ideas like exercises. It's good that you are interested in Scaling WebSockets, because that is the chapter I am writing now! I hope to get it live in a couple of weeks, once it is I can send you the new version.
- Raminj95 5y agoThank you for taking the time to confirm my suspicion, greatly appreciated!
- PaulDavisThe1st 5y agoCan anyone explain why using websockets with anything other than a webstack is so much hard than using regular ol' POSIX sockets, given that at some level websockets live right alongside a UDP or TCP socket? When we looked around for a library to use in Ardour to add websocket support, the choices were slim and none of them provided an API as simple as the one for UDP/TCP sockets.
- keithwinstein 5y agoI think it mostly has to do with: 1) the large "implementation surface" of three components (TLS+HTTP+WebSocket), each of which by itself requires an API more complicated, if provided by a userspace library, than a kernel-provided TCP socket, and maybe 2) the fact that non-Web servers are rare enough, and WebSockets are still recent enough, that no "standard" library has emerged and had its edges honed down over time to support multiple applications, especially when the current era and funders of open source are probably less incentivized to create application-independent libraries than in earlier eras where "let's work together to create a free OS with minimal effort" was a larger share of the driving forces. - With TLS you can certainly link with OpenSSL, but the API is more complicated than a kernel-provided TCP socket, and async/nonblocking TLS requires an API much more complicated. TLS sometimes requires a write in response to a read, and to do that in an apparently nonblocking fashion either (a) the application needs to include callsites back into library in its event loop to tell the library when the underlying socket is writeable just in case the library had something buffered it was hoping to write, (b) the library needs to run its own thread that blocks on the underlying socket, or (c) the library can only be used with languages that support async behavior in a more composable way, which is not C. None of those are good options. - Parsing the incoming HTTP request is tricky and there's no "standard choice" for this either, e.g. a library that's been distributed in Debian/RedHat/Homebrew for >10 years and is depended-on by a bunch of applications. - The WebSocket protocol requires that a server write a pong in response to an incoming ping. As with TLS, this means a nonblocking implementation requires a thread or integration with the application's event loop, but it's arguably even worse because WebSocket wants the server to respond soon to a ping. (By contrast, TLS-on-TCP is mostly designed so that an app can ignore the read or write direction as long as it wants.) So you don't just need to possibly queue up that pong and later call into the library when the socket becomes writeable; you need to make sure no other event is going to run or block for a long time in the meantime. So I think the comparison here may not be, "Why isn't there a library that provides an API for WebSockets that's almost as simple as a kernel-provided TCP socket?" (where the kernel basically runs its own thread and does the async work behind the scenes), but maybe more like, "Why isn't there a user-space library that implements QUIC [or nonblocking TLS, or user-space TCP] with a simple API?" We have implemented a nonblocking C++ WebSocket/TLS server in the cleanest fashion we could (https://github.com/stanford-stagecast/audio/tree/main/src/http https://github.com/stanford-stagecast/audio/tree/main/src/ht...), also for a low-latency audio project, but it's still a ton of code and has to make its own assumptions/demands on how it gets invoked. If you wanted to adopt a WebSocket implementation into Ardour, I'd be happy to help you make that happen, but it sounds like you very reasonably were looking to outsource this to a library where your application isn't the only user.
- nly 5y agoAnyone considering augmenting an existing web service with Websockets should take look at the Nchan nginx plugin. https://nchan.io/ https://nchan.io/
- AlexTDiaconu 5y agoHi HN! I'm Alex, and I've been researching and writing about WebSockets for a while now. I'm the author of the recently released WebSocket Handbook. AMA about the WebSocket tech, the realtime web, Ably or anything related to Liverpool FC.
- lelanthran 5y ago> or anything related to Liverpool FC. Do people still watch football? What are the viewership numbers for Liverpool FC? Does Man United still matter? :-)
- stichers 5y agoMan Utd never mattered. Source: City supporter.
- Ostrogodsky 5y agoWhy does Klopp love to abuse referees and then play dumb?
- mathgladiator 5y agoIt's a good introduction, and it's a good document to introduce the problems induced by WebSockets (which Ably can come in an solve at scale). I recently wrote about the Woes of Websocket: http://www.adama-lang.org/blog/woe-of-websocket http://www.adama-lang.org/blog/woe-of-websocket with an errata based on HN feedback: http://www.adama-lang.org/blog/more-websocket-woe http://www.adama-lang.org/blog/more-websocket-woe The depth of this topic is very interesting, and I'm excited as I'm building some of the final pieces for my SaaS (which could compete with Ably).
- mobilio 5y agoYNWA!
- friendlydog 5y agoWhat is the right way to handle authentication over web sockets?
- e1g 5y agoIn case the email collection form gets hugged to death, here's a mirror https://web.archive.org/web/20220111162712/https://files.ably.com/website/documents/ebook/the-websocket-handbook.pdf https://web.archive.org/web/20220111162712/https://files.abl... In our experience, many enterprise networks/vpns/firewalls still break websocket connections even when using wss, and it should not be used as the only communication channel even if you target evergreen browsers.
- paddybyers 5y agoDisclaimer: I work for Ably. I agree in principle, so the libraries that handle websockets and also fallback transports using comet (eg SocketIO) are still widely used for that reason, and the commercial pub/sub service providers generally also support comet fallbacks. However, we now find that it is really very rare that clients are unable to use wss.
- e1g 5y agoWSS breaking is surprisingly common for clusters of our enterprise users, to the order of 5-10%. Specifically, when business users connect through security networks like Zscaler, often their employers will MITM all connections (similar to how AdGuard works) but in a way that breaks WSS. We have rigorous monitoring for both frontend and backend, and can trace these failures with accuracy - consistently, both the frontend and the ingress firewall think that the other one cancelled the connection attempt, so some network hop in-between did that. Every other network connection during that time works as expected (long polling/SSE over H2), but WSS get interrupted and sometimes can't reconnect. We still love the aliveness of web sockets, but have to architect data fetching in a way that doesn't depend on them working.
- matt_oriordan 5y agoThat's surprising to hear, we definitely don't see anywhere near the order of 5-10%, at best on order of magnitude less. Out of interest, what geography and industries are you operating in where you see such a high rate of incompatibiltiy? Matt, Ably co-founder
- clone1018 5y agoWe use WebSockets in two regards: handling live page updates via Phoenix Live View for users (eg: real time chat messages, viewer count, etc) and as a transport medium for our real time API. The former is very easy to handle because for the most part users are navigating around pages which can terminate the ws connection and creates a new one (though most of the times not). The advantages Live View provides us is not having to write duplicated logic in the client & server, and instead just push data to users and their browser automatically reflects the changes. However the latter use offers very powerful benefits with some difficult downsides. On the positives side you get a "real time" API to work with, and you can handle events as they happen and send updates back to them. In some cases our API users can even respond to a chat message faster than we can! Since WebSockets are virtually just a transport, it's up to you to write a protocol for handling heartbeats, authentication, and communication. In addition when you have a horizontally scaled service it can make balancing the WebSocket connections a bit more challenging since they are long lived. Deployments are even more inconvenient since (in our case) we disconnect the WebSocket consumers whenever a server is restarted for the update. It can also be difficult to fully measure and understand how many WebSocket connections you have open, and how many resources they are consuming. It's important to really push down the number of computations you are doing for users who are subscribed to the same topics so that when you send out 10,000 updates with the same message it's just the text being sent, not 10,000 DB queries :D.
- lvass 5y ago>we disconnect the WebSocket consumers whenever a server is restarted for the update Isn't avoiding this the main selling point for BEAM? As in Erlang: the movie. Can't that be done with websockets?
- sb8244 5y agoYou could totally do this with BEAM, via hot swapping. The WebSocket processes don't really change, it's the implementation of what happens when messages comes in that changes. So you'd setup your hot swap with this in mind. (The connection processes stay connected and the behavior module is swapped out?) However, hot swapping is not super common in practice. Mainly because it's added complexity that most people can live without.
- smaddock 5y agoIt's probably worth mentioning that WebTransport just shipped in Chrome 97 (2022-01-04), which seems to be a worthy successor to WebSockets [0]. It allows for reliable and unreliable modes which is a problem for games using WebSockets, among other things. [0] https://web.dev/webtransport/ https://web.dev/webtransport/
- capableweb 5y agoOnly Chrome so far it seems. Firefox's position: > We are generally in support of a mechanism that addresses the use cases implied by this solution document. While major questions remain open at this time -- notably, multiplexing, the API surface, and available statistics -- we think that prototyping the proposed solution as details become more firm would be worthwhile. We would like see the new WebSocketStream and WebTransport stream APIs to be developed in concert with each other, so as to share as much design as possible. https://mozilla.github.io/standards-positions/ https://mozilla.github.io/standards-positions/ Unclear what the WebKit (Safari) folks think, based on https://lists.webkit.org/pipermail/webkit-dev/2021-September/031980.html https://lists.webkit.org/pipermail/webkit-dev/2021-September... that has no replies. Microsoft is just doing whatever Chrome is doing with Edge, so I guess it'll appear there sooner or later, but can't find any public information. Bit early to start using WebTransport seems to be the conclusion.
- travisd 5y agoI skimmed the page, but couldn’t quite tell: is this what the WHATWG Streams API is becoming? (ie streams with back-pressure?)
- matt_oriordan 5y agoI know, we're very excited about WebTransport and what it can offer. As you say, on the surface it seems to provide both a more performant and reliable transport for realtime communications. Once it hits mainstream, we'll be certainly adding it as another transport we support in our stack (currently websockets, HTTP, SSE, MQTT etc) Matt, co-founder of Ably
- matsemann 5y agoIs this a new standard, or yet another thing Google is pushing and everyone else have to implement?
- bullen 5y agoIf you want something simpler for real-time communication you can use comet-stream. It goes through all firewalls and scales better than most single threaded websocket servers: https://github.com/tinspin/rupy/wiki/Comet-Stream https://github.com/tinspin/rupy/wiki/Comet-Stream
- capableweb 5y agoHow does that work in the browser context? Just one long-living HTTP request that the server streams messages too? How does the browser reply? It's hard to understand how it's duplex and real-time over just HTTP without making more than one HTTP request.
- bullen 5y agoYou have two sockets, one eternal response with transfer-encoding: chunked, which is basically <hex_length>\r\n<data>\r\n\r\n over and over again, so very compact. On the browser to server it gets a bit heavier because you need GET /path?data=<message> HTTP/1.1\r\nHost: kinda.verbose.com\r\n\r\n and then each request gets a response that can be either zero so 200 OK\r\nContent-Length: 0\r\n\r\n or contain a sync. response. It looks bad but trust me that verbosity is a rounding error when it comes to the real bottleneck which is CPU concurrent atomic parallelism, and for that you basically need to use Java: https://github.com/tinspin/rupy/wiki https://github.com/tinspin/rupy/wiki (Most people disagree but the VM + GC and Javas memory model allows for atomic shared memory like none other, not even C/C++ can compete because you need a VM with GC to make that memory model work, they tried to copy it into C++11 and that was a faceplant of epic proportions that is still C++ memory model).
- hwers 5y agoAnyone know of any examples of cool cases where websockets have been used? (Maybe other than games.) I feel like in most cases I see them used the latency gained is basically added back with bloat in other parts.
- paxys 5y agoPretty much every app that has a real-time communication component relies heavily on websockets. Slack and other messaging apps, document editors, financial tickers, sports sites.
- pcthrowaway 5y agoCrypto exchanges almost exclusively use websockets for pushing out real-time price and orderbook changes. They provide rest apis also, but with limits that prevent bots from keeping the data as close to in sync as possible, which is important for algorithmic trading. Whether this qualifies as a 'cool' case is probably subjective, but it is important in practice. I'm not sure if it's as widespread, but many exchanges use websockets in the front-end to make the same data available to the site users without frequent polling.
- anderspitman 5y agoI'll throw my hat in the ring: https://iobio.io/2019/06/12/introducing-fibridge/ https://iobio.io/2019/06/12/introducing-fibridge/
- JSdev1 5y agoI just launched this site with websockets: https://hackernews.pro https://hackernews.pro Websockets used for updating Story/Comment data, and User presence
- matt_oriordan 5y agoFeel free to sign up for an Ably account and we'll help support your project with a community package, we love what you're doing!
- deleted 5y ago[deleted]
- paxys 5y agoBefore going all-in on websockets I'd like to caution people to thoroughly consider the server-side scaling challenges that come with it. HTTP servers have already solved traffic management, load balancing, scaling up and down, zero downtime deployments, A/B tests and experimentation and lots more to such a degree that we don't have to even think about them anymore. All of these problems come to the forefront again when you have to scale websocket connections beyond a single server.
- rglover 5y agoThere's a (relatively) easy trick for this: Redis pubsub. When a message comes into an instance, you push it to Redis and have all of your other instances subscribed to it. Messages sync in real-time and the experience is transparent. I teach the technique here: https://cheatcode.co/courses/how-to-implement-real-time-data-with-websockets https://cheatcode.co/courses/how-to-implement-real-time-data...
- Supermancho 5y agoTo be a bit clearer, you don't want to push websocket messages per se; eg auth negotiation or info requests. You do want to pubsub out conditioned messages that are generated by any given instance for the purpose of broadcast; eg "userX connected" or "userX said Y".
- mathgladiator 5y agoI'm going all-in on WebSockets, but I've also seen how to solve all those problems at massive scale. You're right that these challenges are hard, and I don't believe we have an ideal shared offering yet. We have a cultural challenge of how to manifest the opportunity and benefits presented by context rich communication over the entrenched ideology of statelessness and HTTP.
- latch 5y agoDiving a little deeper down: 1 - A websocket "frame" has a variable-length header. Client->Server the header can be 6, 8 or 14 bytes. Server->Client it can be 2, 4 or 10. This is to support payloads < 125 bytes, < 2^16 and up to 2^64. I wish it was just a fixed 4-byte length. 2 - Frames can be fragmented to support streaming (where the sender or possibly a proxy doesn't know/want to buffer the entire response ahead of time). I feel like this is unnecessary in 99% of the cases. It wouldn't be so annoying..except control frames can be interspersed within fragmented frames. This is so that you can send a "ping" while streaming a large message over multiple fragments. Why didn't they just use one of those reserved bits for this? 3 - Client->Server payload is masked with 4 bytes (bitwise xor) so every message your server gets has to be unmasked.
- austincheney 5y agoI wrote a document explaining how to implement your own web socket service: https://github.com/prettydiff/wisdom/blob/master/websocket_server.md https://github.com/prettydiff/wisdom/blob/master/websocket_s... Implementing your own service logic is incredibly helpful in the cases where you have multiple sockets to manage and custom logic associated with identity, reestablishment, custom data handling, and so forth. There are features in the protocol that aren't used in the browser, for example, and allow for custom scaling. Here are my learnings about web sockets: * They are session oriented so that means both end points have to agree to connect. That mitigates many security risks associated with HTTP traffic. * Web socket messages cannot be interleaved. In 99% of cases this isn't an issue, because control frames unrelated to a web socket message can occur anywhere without interruption. This becomes a problem if you are transfer a large file that takes a substantial amount of transfer time. All other messages must wait in a queue, which means long delayed microservice status updates or you just break things. * Web sockets are so much faster to process than HTTP. A web socket is primitive. There is no roundtrip (request/response), no headers, and no additional negotiation. I reduced some test automation in my personal application from 45 seconds to 7 seconds by fully converting from HTTP to web sockets for messaging. * Reliance on web sockets simplifies so much of a service oriented application. I used to rely upon callbacks to HTTP responses to verify message completion and perform next step actions in an application. Instead I am switching to specific messaging for everything. A response is a specific message when the responding machine is ready. This eliminates response timeouts, flattens the architecture, and eases service testing by moving all messaging concerns to a single listener as opposed to listening for responses versus requests from other machines. * Since web sockets are session oriented they are potentially more fragile than HTTP. If the pipe drops you have to reestablish the connection before sending/receiving service messages.
- chalas_r 5y agoMercure is an alternative to WebSocket that is especially useful for REST/GraphQL APIs. It's a protocol that builds on HTTP and Server-Sent Events thus is supported out of the box by browsers, mobile apps and IoT clients, and it doesn't suffer from most WebSocket limitations (e.g. header/cookie based authorization works): https://mercure.rocks https://mercure.rocks
- crummy 5y ago> it doesn't suffer from most WebSocket limitations (e.g. header/cookie based authorization works) Don't WS connections send headers? What's the limitation here?
- chalas_r 5y agoActually neither the WebSocket nor the SSE browser APIs allow to send custom headers (see https://stackoverflow.com/q/4361173/4363634 https://stackoverflow.com/q/4361173/4363634, https://stackoverflow.com/q/36201347/4363634 https://stackoverflow.com/q/36201347/4363634). Point is that the Mercure protocol specifies the authorization part deeply so it's handled out of the box. With WebSocket you are on your own.
- anderspitman 5y agoI love Server-Sent Events, but just as a heads up in case anyone doesn't know there are some limitations to SSE: * Doesn't natively support binary data. * If you're using HTTP/1.1 in the browser, you'll be severely limited in the number of SSE connections you can have going at a time. If you're on HTTP/2 then it's not a problem.
- arendtio 5y agoDoes someone know, why Websockets are sometimes considered a security risk and blocked by corporate firewalls, even when the rest of the website is considered to be trustworthy?
- deleted 5y ago[deleted]
- twic 5y agoI use websockets quite a lot, for real-time dashboard kind of purposes. The one thing i really wish websockets had is some kind of application-level acknowledgement or backpressure. At the server end, you're blasting out messages to the client, but you have no idea if it is keeping up with them. Most of the time, it will be, but if there is a sudden spike of activity, suddenly all your dashboards are going wild, and the client may start to struggle. At that point, you want to be able to shed some load - delay messages a bit, then drop any message which gets superseded (eg if "reactor core temperature is 1050K" is buffered and you get "reactor core temperature is 1100K", you can drop the former). To do that, you need feedback about how far the client has got with processing messages. You can build a feedback mechanism like this into your application protocol on top of websockets easily enough. But you probably want to do that from the start, or else you will, like me, one day look around and realise that retrofitting it to all your dashboards is a monumental effort. The RSocket protocol might be a good start - it provides reactive streams semantics, and has a binding to websockets: https://rsocket.io/guides/rsocket-js https://rsocket.io/guides/rsocket-js
- anderspitman 5y agoI built omnistreams[0] primarily because of the lack of backpressure in browser WebSockets (lots of background information and references in that README). It's what fibridge[1] is built on. We've been using it in production for over 2 years, but I never ended up trying to push omnistreams as a thing. I believe the Rust implementation is actually behind the spec a bit, and the spec itself probably needs some work. At the end of the day I think RSocket is probably the way to go for most people, though the simplicity of omnistreams is still appealing to me. EDIT: I just learned about WebSocketStreams[2] from another comment[3] and sounds like they may solve the backpressure issue natively. [0]: https://github.com/omnistreams/omnistreams-spec https://github.com/omnistreams/omnistreams-spec [1]: https://iobio.io/2019/06/12/introducing-fibridge/ https://iobio.io/2019/06/12/introducing-fibridge/ [2]: https://web.dev/websocketstream/ https://web.dev/websocketstream/ [3]: https://news.ycombinator.com/item?id=29894938 https://news.ycombinator.com/item?id=29894938
- twic 5y ago
- gfd 5y agoDoes anyone know when to choose http2 vs websockets?
- anderspitman 5y agoI'm assuming you mean HTTP/2 with Server-Sent Events, since raw HTTP/2 frames aren't exposed in the browser? My answer would be use HTTP/2 + SSE whenever you can get away with it. The primary limitation of SSE in this case is you can't natively send binary data (you would have to base64 encode it or something). If you're just using JSON or another text format anyway this isn't an issue.
- 62951413 5y agoWouldn't HTTP2 imply https://github.com/grpc/grpc-web https://github.com/grpc/grpc-web instead?
- anderspitman 5y agoMaybe. I've never seriously considered grpc-web since it requires a special proxy (Envoy) to work. Seems like too many layers of complexity at that point.
- cookiengineer 5y agoA couple months ago I posted the "Implementer's guide to WebSockets" that I wrote, but it seemingly got shadowbanned. [1] I wrote the guide with example code for people wanting to know how to implement the complete WS13 protocol from scratch, so you can try it out, fiddle around and modify it to your needs. The guide is more in-depth and assumes that the reader is willing to read the RFC when they're stuck :) [1] https://cookie.engineer/weblog/articles/implementers-guide-to-websockets.html https://cookie.engineer/weblog/articles/implementers-guide-t...
- throwaway81523 5y agoThis looks nice. I think I'll start with it instead of the OP ebook. Thanks for writing and posting it.
- SLWW 5y agoThis is pretty excellent. I'll hold on to both of these resources as I think websockets would be just wonderful for the work I'm doing right now. > willing to read the RFC when they're stuck :) I owe RFCs for just about everything I do, they play a small but necessary role, I can't imagine not wanting to dip into one of them even if you aren't stuck.
- throwaway81523 5y agoAnyone looked at the book? I feel a little bit spammed by this post. The linked page is a pitch for an ebook that is a free download, but you have to sign up for promotional mailings in order to get it, and they want your first and last name. Yes you can unsubscribe but this is still obnoxious. A direct link to a pdf would be much more attractive. I haven't programmed anything with websockets yet, but I read the wikipedia page about them recently and found it sufficient to understand what they were. The rest is a matter of javascript programming that I've avoided messing with so far.
- SLWW 5y agoI just provide a spam email account for things like this. I have yet to read through it much, but it is interesting. https://files.ably.com/website/documents/ebook/the-websocket-handbook.pdf https://files.ably.com/website/documents/ebook/the-websocket...