We 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.
> 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
May I suggest that the solution could be to design your WS protocol to be reconnect-friendly, like the Phoenix LiveView protocol?
Maybe make a protocol which assumes and expects that a connection may be dropped by any side at any time, with robust context-restoration API such as “full snapshot” or “all updates since event ID”
I think your last paragraph is a good point for using services like the OP. All three of the examples you mentioned are already solved. Granted, you're buying into their paradigm particularly regarding communication model but that's a small price to pay for the upsides.
Disclaimer: we've been using Ably for years and their service and reliability has been outstanding, and we have worked closely with their engineers and I've found their expertise to be above what you may expect from experience with other company's support personnel.
I 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:
There should be a law for message passing systems, which says that everyone will eventually want ordered delivery, multiplexing (with priorities), exactly-once semantics, acknowledgements and backpressure. (Maybe more?)
I'm pretty convinced all these popular features could be layered in a reasonable way that could be implemented in most messaging systems, and have standardized semantics and conventions. It seems like every time, we're reinventing the wheel, and half the time people talk over one-another because we're using inexact language.
Basically, what I want is a "message passing a la carte" paper.
I 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.
If it's streaming data like dashboard statistics then going forward the new WebTransport API might be a much better base: https://github.com/w3c/webtransport/blob/main/explainer.md At this instant it's hot off the assembly line though having just shipped in Chrome 97, Firefox is still working on it.
I don't know anything about websockets, but isn't it over tcp? Meaning if the client isn't keeping up, their buffer should be full and the server should be blocked from sending more until it drains (unless it's queuing the messages somewhere else?). Or is that not how tcp backpressure works?
It is better to implement it at front end. Actually it is not better it is kinda has to be that way. Because page will be already lagging and if you implement it at front at there won't be any lags.
And it is better to have limits about update frequency at the back-end. If reactor temperature already announced 100 ms ago and it went to 1051K from 1050K maybe it is better to delay it for a second.
It'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.
> 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.
I 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)
A 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 :)
This 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.
Hi 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.
Hi! I want to create a web app like Google docs where multiple users can collaborate in real time to edit the document together (using a special link like gdocs generate). I want to save the docs in a MySQL db (no firebase)
My questions are:
1) Since multiple people are working together how does one manage conflicts, i.e. 2 people sending different edits simultaneously.
2) If one clients gets disconnected (4g) and then reconnects later how does it sync the changes it made during it was offline?
I recently watched this RAFT presentation (1) and I think I would need to use something like this?
What other alternatives are viable?
Also can I make it happen using just PHP, Javascript and MySQL?
Before 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.
There'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'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.
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.
Disclaimer: 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.
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.
Mercure 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):
I 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.
Can 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.
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/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.
websockets unfortunately have to start at the HTTP layer and negotiate down to the TCP wrapper layer, so you need at least a partial HTTP stack and everything else that involves to get there. This complicates things a lot. It's like stuffing a turkey, cooking it, then throwing away the meat to just eat the stuffing.
In my experience, Boost Beast[1] is the easiest library to just get going with but you have to deal with all the Boost-isms that comes with. libwebsockets is the 'standard' C implementation but unless you know the websocket RFC front to back it's quite difficult to work with and has a lot of foot-guns.
It's related to what you can buy versus build. When you use a WebSocket, there may not be a great solution that fits your need. If you use just HTTP, then there is a wealth of options available to you.
Fundamentally, there is nothing special about a WebSocket over a socket rather than a special handshake, some framing, and the layering within an existing HTTP server. The problem is that the market of developers is vastly different. If you are a systems person, then chances are good you know sockets decently. If you are a typical web-dev, then the chances are not so great and its easy to make a mess that is then exposed to the world.
I've mentored teams, and the key challenge isn't technical but education on all the gotchas.
Anyone 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.
If 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
How 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.
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.
Does 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?
I'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.
Anyone 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.
My use case was I wanted to transfer a PDF to an Android-based tablet but in the moment didn't want to log into my email. I couldn't think of any quick, easy, and cross-platform solutions so I decided to write the service.
It's built on socket.io which is a godsend for websockets because it automatically handles so much grunt work and your app just works.
We use them for a variety of intranet realtime dashboard type things. Both user-facing production UI, where users are looking at screens covered with dozens of dashboards all updating several times a second, and developer-facing monitoring.
The client-side code is generally very simple. A dashboard opens a websocket and attaches a handler which parses the message (all our payloads are JSON), then routes the update to the right bit of the UI. We wrote a thin wrapper round the browser websocket API to handle disconnections. We wrote server-side libraries to support our patterns of use.
I initially did a bunch of developer-facing dashboards using server-sent events, because they're slightly easier to work with. However, websockets have a significant advantage over SSE: you can have a lot more of them open at once. Browsers will limit you to a few (six?) connections per origin, including long-lived SSE connections, whereas you can have dozens or hundreds of websockets open [1]. If you are serving lots of different dashboards off a single server, you rapidly get to the point where this matters!
Crypto 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.
Pretty 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.
wrt gaming, there was a websocket game of spaceships flying around posted to HN a few times where the clients open two websocket connections to iirc get around tcp head of queue blocking. Maybe they were sending round robin updates across them.
Couldn't find the Show HN just now but searching "subspace" comments might reveal it ("this reminds me of subspace"). I always wanted to look more into the approach.
Our customers use Ably across such a diverse set of use cases, but here's a few:
1. Sports events streaming live updates (see https://ausopen.com/live-scores, we are streaming live scores for the Tennis Australian Open right now). Companies like Toyota even use us to facilitate engineers tweaking the performance characteristics of their cars in realtime remotely.
2. Edtech - we have numerous customers using us to drive live classroom environments, think shared white boards, collaborative tests, presence, teacher engagement. You may have used Codewars in the past, that uses Ably under the hood for example, https://www.codewars.com/.
3. Live screen sharing and collaborative applications. You may have used the amazing Tuple.app, that uses Ably under the hood https://tuple.app/.
4. Collaborative and live web and mobile SaaS applications, where changes need to occur concurrently, notifications need to be presented, and other realtime updates are needed in the interface. You've probably heard of Hubspot, they use Ably under the hood to power their collaborative and live features, https://hubspot.com
5. Developer infrastructure and platforms that need realtime capabilities at scale. You have probably come across Split, the leading feature flag company backed by Atlassian and Microsoft. They use Ably under the hood to power billions of feature flag updates in realtime each month. https://www.split.io/
6. Financial market data - typically streaming updates to thousands or millions of subscribers with very low latency, and sometimes using features like Deltas (https://ably.com/documentation/realtime/channels/channel-par...) to keep bandwidth & latency as low as possible.
I could keep going, but I hope that gives you the idea, realtime is not just for Christmas or for Games :)
I have an app based around some long running resource intensive processes that run on scalable microservices. So you click a button and may have to wait 5+ minutes before you get a response. Websockets let you do notifications and make everything async. They've served me well for request/response that might take 3-30 minutes.
A bunch of things we (Fanout) have seen as a WebSocket provider, other than games: shared document editing, field worker management, live voting, parking space tracking, feature flags, sports updates, home security, ridesharing, financial tickers, notifications, news feeds, exercise classes, realtime audio analysis, and remote controls.
clone1018|4 years ago
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.
nlitened|4 years ago
May I suggest that the solution could be to design your WS protocol to be reconnect-friendly, like the Phoenix LiveView protocol? Maybe make a protocol which assumes and expects that a connection may be dropped by any side at any time, with robust context-restoration API such as “full snapshot” or “all updates since event ID”
ddoolin|4 years ago
Disclaimer: we've been using Ably for years and their service and reliability has been outstanding, and we have worked closely with their engineers and I've found their expertise to be above what you may expect from experience with other company's support personnel.
lvass|4 years ago
Isn't avoiding this the main selling point for BEAM? As in Erlang: the movie. Can't that be done with websockets?
twic|4 years ago
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
klabb3|4 years ago
I'm pretty convinced all these popular features could be layered in a reasonable way that could be implemented in most messaging systems, and have standardized semantics and conventions. It seems like every time, we're reinventing the wheel, and half the time people talk over one-another because we're using inexact language.
Basically, what I want is a "message passing a la carte" paper.
anderspitman|4 years ago
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
[1]: https://iobio.io/2019/06/12/introducing-fibridge/
[2]: https://web.dev/websocketstream/
[3]: https://news.ycombinator.com/item?id=29894938
zamadatix|4 years ago
gfd|4 years ago
alienalp|4 years ago
smaddock|4 years ago
[0] https://web.dev/webtransport/
capableweb|4 years ago
> 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/
Unclear what the WebKit (Safari) folks think, based on 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.
matt_oriordan|4 years ago
Matt, co-founder of Ably
travisd|4 years ago
matsemann|4 years ago
cookiengineer|4 years ago
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-t...
SLWW|4 years ago
> 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|4 years ago
AlexTDiaconu|4 years ago
superasn|4 years ago
My questions are:
1) Since multiple people are working together how does one manage conflicts, i.e. 2 people sending different edits simultaneously.
2) If one clients gets disconnected (4g) and then reconnects later how does it sync the changes it made during it was offline?
I recently watched this RAFT presentation (1) and I think I would need to use something like this?
What other alternatives are viable?
Also can I make it happen using just PHP, Javascript and MySQL?
Thanks
(1) http://thesecretlivesofdata.com/raft/
friendlydog|4 years ago
mathgladiator|4 years ago
I recently wrote about the Woes 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
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).
httgp|4 years ago
Ostrogodsky|4 years ago
lelanthran|4 years ago
Do people still watch football?
What are the viewership numbers for Liverpool FC?
Does Man United still matter?
:-)
mobilio|4 years ago
paxys|4 years ago
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|4 years ago
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...
mathgladiator|4 years ago
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.
e1g|4 years ago
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|4 years ago
app4soft|4 years ago
austincheney|4 years ago
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|4 years ago
https://mercure.rocks
anderspitman|4 years ago
* 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.
crummy|4 years ago
Don't WS connections send headers? What's the limitation here?
PaulDavisThe1st|4 years ago
keithwinstein|4 years ago
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/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.
Scaless|4 years ago
In my experience, Boost Beast[1] is the easiest library to just get going with but you have to deal with all the Boost-isms that comes with. libwebsockets is the 'standard' C implementation but unless you know the websocket RFC front to back it's quite difficult to work with and has a lot of foot-guns.
[1] https://www.boost.org/doc/libs/1_78_0/libs/beast/example/web...
mathgladiator|4 years ago
Fundamentally, there is nothing special about a WebSocket over a socket rather than a special handshake, some framing, and the layering within an existing HTTP server. The problem is that the market of developers is vastly different. If you are a systems person, then chances are good you know sockets decently. If you are a typical web-dev, then the chances are not so great and its easy to make a mess that is then exposed to the world.
I've mentored teams, and the key challenge isn't technical but education on all the gotchas.
throwaway81523|4 years ago
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|4 years ago
I have yet to read through it much, but it is interesting.
https://files.ably.com/website/documents/ebook/the-websocket...
bullen|4 years ago
capableweb|4 years ago
latch|4 years ago
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.
arendtio|4 years ago
unknown|4 years ago
[deleted]
nly|4 years ago
https://nchan.io/
gfd|4 years ago
anderspitman|4 years ago
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.
hwers|4 years ago
acdibble|4 years ago
My use case was I wanted to transfer a PDF to an Android-based tablet but in the moment didn't want to log into my email. I couldn't think of any quick, easy, and cross-platform solutions so I decided to write the service.
It's built on socket.io which is a godsend for websockets because it automatically handles so much grunt work and your app just works.
JSdev1|4 years ago
twic|4 years ago
The client-side code is generally very simple. A dashboard opens a websocket and attaches a handler which parses the message (all our payloads are JSON), then routes the update to the right bit of the UI. We wrote a thin wrapper round the browser websocket API to handle disconnections. We wrote server-side libraries to support our patterns of use.
I initially did a bunch of developer-facing dashboards using server-sent events, because they're slightly easier to work with. However, websockets have a significant advantage over SSE: you can have a lot more of them open at once. Browsers will limit you to a few (six?) connections per origin, including long-lived SSE connections, whereas you can have dozens or hundreds of websockets open [1]. If you are serving lots of different dashboards off a single server, you rapidly get to the point where this matters!
[1] https://stackoverflow.com/questions/26003756/is-there-a-limi...
pcthrowaway|4 years ago
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.
paxys|4 years ago
hombre_fatal|4 years ago
Couldn't find the Show HN just now but searching "subspace" comments might reveal it ("this reminds me of subspace"). I always wanted to look more into the approach.
matt_oriordan|4 years ago
1. Sports events streaming live updates (see https://ausopen.com/live-scores, we are streaming live scores for the Tennis Australian Open right now). Companies like Toyota even use us to facilitate engineers tweaking the performance characteristics of their cars in realtime remotely.
2. Edtech - we have numerous customers using us to drive live classroom environments, think shared white boards, collaborative tests, presence, teacher engagement. You may have used Codewars in the past, that uses Ably under the hood for example, https://www.codewars.com/.
3. Live screen sharing and collaborative applications. You may have used the amazing Tuple.app, that uses Ably under the hood https://tuple.app/.
4. Collaborative and live web and mobile SaaS applications, where changes need to occur concurrently, notifications need to be presented, and other realtime updates are needed in the interface. You've probably heard of Hubspot, they use Ably under the hood to power their collaborative and live features, https://hubspot.com
5. Developer infrastructure and platforms that need realtime capabilities at scale. You have probably come across Split, the leading feature flag company backed by Atlassian and Microsoft. They use Ably under the hood to power billions of feature flag updates in realtime each month. https://www.split.io/
6. Financial market data - typically streaming updates to thousands or millions of subscribers with very low latency, and sometimes using features like Deltas (https://ably.com/documentation/realtime/channels/channel-par...) to keep bandwidth & latency as low as possible.
I could keep going, but I hope that gives you the idea, realtime is not just for Christmas or for Games :)
Matt, co-founder of ably.com
scurvy_steve|4 years ago
jkarneges|4 years ago
anderspitman|4 years ago
iratewizard|4 years ago
aparsons|4 years ago
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.