[HN Gopher] Woe be unto you for using a WebSocket ___________________________________________________________________ Woe be unto you for using a WebSocket Author : mathgladiator Score : 133 points Date : 2021-12-22 16:28 UTC (6 hours ago) (HTM) web link (www.adama-lang.org) (TXT) w3m dump (www.adama-lang.org) | bri3d wrote: | I think this conflates a very specific paradigm for using | WebSockets (state synchronization with a stateful "server") with | WebSockets as a technology. | | At the end of the day, WebSockets are just, well, sockets, with a | goofy HTTP "upgrade" handshake and some framing on top of them. | You could implement the exact same request/response model as in | an HTTP based service over a WebSocket if you wanted to. | | Stateful services are a tradeoff whether you use a WebSocket or | not. | | Reading through here, I think what you're trying to build is a | synchronized stateful distributed system where state management | becomes more transparent to the engineer, not only across backend | services but also between the browser and the service side - this | is well tread ground and a huge problem, but an interesting one | to take on nonetheless. "WebSockets" are a red herring and just | an implementation detail. | mathgladiator wrote: | You're right. The key thing is the spectrum of freedom induced | by the library/framework. For example, if use something like | PHP then you live in a prison of the request lifecycle. | Sometimes the prison is socially enforced by not having shared | state between requests within a process. | | There is nothing special about websockets, but they do confer a | freedom and responsibility. | vikR0001 wrote: | Just use Meteor and/or Apollo. They have all this stuff figured | out. | | https://www.meteor.com/ | | https://www.apollographql.com/ | cultofmetatron wrote: | come to phoenix/elixir land. Channels are amazing and the new | views system allows you to seamlessly sync state to a frontend | using websockets with almost no javascript | mathgladiator wrote: | Perhaps I will. | | I'm thinking about how I position Adama for both Jamstack and | as a reactive data-store (which could feed phoenix/elixer | land). I intend to change my marketing away from the | "programming language" aspect and more towards "reactive data | store". | Zealotux wrote: | My side-project relies heavily on WS, I'm currently using | Node.js and it's alright but learning Elixir is my goal during | these holidays. Any resource to share to get started? I don't | know much about Elixir except it's perfect for such use-cases. | dqv wrote: | I got pretty far in the beginning just by reading the docs on | Phoenix channels [0]. I was learning Phoenix and ReactJS at | the same time and got a pretty simple Redux thunk that | interacted with Phoenix Channels in a few days. I'm not sure | if that was the optimal way to do it, but it was really cool | interacting with the application from IEx (elixir shell). | | You might find an interesting (albeit more complex) entry | point by interacting with Phoenix Channels from your Node.js | app using the Channels Node.js client [1] and within the | frontend itself. | | [0]: https://hexdocs.pm/phoenix/channels.html [1]: | https://www.npmjs.com/package/phoenix-channels | lawn wrote: | The book Real-Time Phoenix is good for designing realtime | systems. | | For a good introduction to Elixir, I loved Elixir in Action | which also covers OTP. | | If you want a good Phoenix resource, the book Programming | Phoenix is good. | | Finally, the docs in Elixir and Phoenix are great. | sb8244 wrote: | I wrote Real-Time Phoenix and it goes into pretty much | everything that I hit when shipping decently large real-time | Channel application into production. Like, the basics of "I | don't know what a Channel is" into the nuance of how it's a | PITA to deploy WS-based applications due to load balancers | and long-lived connections. | | The new LiveView book is great if you're interested in going | fully into Elixir (server/client basically). I use LiveView | for my product and it's great. | b5n wrote: | Being already familiar with FP I was able to jump right into | elixir after running through learn you some erlang. Erlang | and elixir are very similar, and you get the bonus of | learning a bit about OTP, BEAM, and the underlying | philosophy. There's a ton of resources after that, and the | docs are easy to use and understand. | | https://learnyousomeerlang.com/ | cultofmetatron wrote: | I was a nodejs programmer for almost 8 years before I hopped | to elixir. A lot of it was motivated btw elixir's realtime | system and concurrency. | | One of the issues with nodejs is that you're stuck to one | process which is single threaded. IE: you're stuck to one | core. Yes there are systems like clustering which relies on a | master process spawning slave processes and communicating | over a bridge but in my experience, its pretty janky. | | You're making a great move by trying out elixir. It solves a | lot of the issues I ran into working with nodejs. | Immutability is standard and if you compare two maps, it | automatically does a deep evaluation of all the values in | each tree. | | The killer feature however is liveview. Its what meteor | WISHES it could be. realtime server push of html to the dom | and teh ability to have the frontend trigger events on the | backend in a process thats isolated to that specific user. | Its a game changer. | | Anyways, if you're looking for resources to learn. pragprog | has a bunch of great books on elixir. Thats how I got | started. | callamdelaney wrote: | Channels are basically websockets and only supported inside | Phoenix as far as I can tell.. | cultofmetatron wrote: | its more than just webockets. Its a prototcol built on web- | sockets that also include keepalive and long-polling | fallback. | | You could in theory replicate the protocol in another stack | but its more than that. Elixir is uniquely suited to | websocket applications. Since a websocket is persistent, you | need a process on your end that handles that. Elixir is | excellent at creating lightweight threads for managing these | connections. Out of the box, you can easily support a few | thousand connections on a single server. | | I know because we did it at my startup. channels powers our | entire realtime sync system and its yet to be a bottleneck. | It more or less works out of the box without issue. Its | almost boring level reliable. | callamdelaney wrote: | Elixir inherits those properties from the Beam VM it shares | with Erlang - both languages are effectively great for this | WS/Channels use case - but Channels seems unhelpful unless | you're already using phoenix. I can't see that it can be | used in say Erlang. | sb8244 wrote: | Channels are really just a protocol, but that protocol is | implemented in Elixir (Phoenix) and so isn't available | elsewhere. | | I think that the important question is "why does this | protocol exist?" Most likely, you'll end up solving | similar problems as to why Channels exist in the first | place. So from a protocol perspective, it's nice that | some problems are solved for you. | prophesi wrote: | May not fit your use-case, but you can create an umbrella | project with both an Erlang app and an Elixir/Phoenix | app, whereby the latter's capable of calling functions in | the former. | hattmall wrote: | I've never seen websockets accomplish anything that push with | long polling didn't do more effective and efficiently. I think | they are a technology that missed their time, the CPU / power | savings are generally non-existent and the minimal bandwidth | savings are frequently negated by the need to add in redundancy | and checks. | anderspitman wrote: | If SSE supported binary data I might agree with you. I think | WebSockets have their place, but are overused. I definitely | agree long polling should be implemented first and then only | add WS if you've measured that you need it. You're probably | going to need to implement polling anyway for clients to catch | up after disconnect. | eska wrote: | I'm confused. Just because you use request response doesn't mean | you don't have state in your page. And sure, your connection can | drop, but your requests can also fail. Protocol versioning is | required, but that is true for any protocol ever, also request | response. And what's this about wanting to outsource all state | and everything requires a database as soon as it has state? Which | one does mspaint.exe use? And if using a load balancer or proxy | somehow leaks through then something really messed up is going | on. In pubsub, just like REST, one doesn't care who sent the | data. I'm confused. | mathgladiator wrote: | Sorry about that. Yes, those are required but you have more | freedom to go wrong in more severe ways. | | Mspaint uses the file system at command of the user. Something | that I didn't mention (which I will I'm a revision) I'd that | the server is being run by another person with their own | deployment schedule. So, we generally like to excise state ASAP | to a durable medium since process state is volatile. | rglover wrote: | Make sure you handle disconnects/reconnects, leverage query | params to pass state (ideally limited), sync/scale via Redis | pubsub, and assume that the websocket will fail so always have | some sort of fallback/redundacy. Ideally think of websockets like | sprinkles on ice cream. | | Shameless plug: https://cheatcode.co/courses/how-to-implement- | real-time-data... | [deleted] | halpert wrote: | pshc wrote: | On the plus side, once you get a good websocket steady state | going, the efficiency and latency benefits are nice compared to | HTTP1 polling. | | Maybe not that big of an advantage anymore with HTTP2 popping | off. | FZambia wrote: | Every time I read criticism of WebSockets it reminds me about | WebSuckets (https://speakerdeck.com/3rdeden/websuckets) | presentation :) | | I am the author of Centrifugo server | (https://github.com/centrifugal/centrifugo) - where the main | protocol is WebSocket. Agree with many points in post - and if | there is a chance to build sth without replacing stateless HTTP | to persistent WebSocket (or EventSource, HTTP-streaming, raw TCP | etc) - then definitely better to go without persistent | connections. | | But there are many tasks where WebSockets simply shine - by | providing a better UX, providing a more interactive content, | instant information/feedback. This is important to keep - even if | underlying stack is complicated enough. Not every system need to | scale to many machines (ex. multiplayer games with limited number | of players), corporate apps not really struggle from massive | reconnect scenarios (since number of concurrent users is pretty | small), and so on. So WebSockets are definitely fine for certain | scenarios IMO. | | I described some problems with WebSockets Centrifugo solves in | this blog post - https://centrifugal.dev/blog/2020/11/12/scaling- | websocket. I don't want to say there are no problems, I want to | say that WebSockets are fine in general and we can do some things | to deal with things mentioned in the OP's post. | zemo wrote: | > Not every system need to scale to many machines (ex. | multiplayer games with limited number of players) | | the author writes a websocket board game server. Most, if not | all, of these complaints read like the author isn't | partitioning the connections by game. | jeroenhd wrote: | I've only professionally used WebSockets with Spring Boot and | React and I must say: they're perfectly fine? | | That is, if you use WS to simply asynchronously communicate | events and do out-of-band message passing, they operate quickly, | easily and efficiently. I wouldn't use them to send binary blobs | back and forth or rely on them to keep a perfect state match, but | for notifications and push events they're a delight to work with. | Plus, their long-term connectivity gives them an edge above plain | HTTP because you can actually store a little state in sockets | rather than deriving state from session cookies and the like. | | Yes, WebSockets don't fit well within the traditional "one | request, one response, one operation" workflow that the web was | built upon, but that model is arguably one of the worst problems | you encounter when you use HTTP for web applications (not | websites, though; for websites, HTTP works perfectly!). Most | backend frameworks have layers upon layers of processing and | securty mitigations exactly because HTTP has no inherent state | | WebSockets aren't some magical protocol that will make all of | your problems go away but if used efficiently, they can be a huge | benefit to many web applications. I've never used (or even heard | of) Adama, so I can totally believe that websockets are a | terrible match for whatever use case this language has, but that | doesn't mean they deserve to get such a bad rep. You just have to | be aware of your limitations when you use them, the same way you | need to be aware of the limitations of HTTP. | superice wrote: | Absolutely right, until you have multiple instances of backends | you need to deal with and synchronize, which is a pain in the | behind. The OPs main issue seems to be with that problem, which | is the tough component of using something stateful like | websockets anyways. The impedance mismatch of 'something | happened in the database' to 'send event over websocket' is | painful in a multi backend instance environment. | | Case in point: dossier locking in the product we both worked | on. Hi Jeroen! Always nice to find an old colleague on here :) | jeroenhd wrote: | Ha, hey there! Nice username :) | | You're totally right, of course; for shared states between | different backend instances you'll need a different solution, | like database locking or complicated inter-backend API calls, | or even a separate (set of) microservice(s) to deal purely | with websockets while other backend operate on the database. | That way you can apply scaling without data consistency | issues, if you want to go for a _really_ (unnecessarily) | complicated solution. | | It all depends on your problem space. If you want to make a | little icon go green on a forum because someone commented on | your post, I think websockets are perfect, much better than | the long-lived HTTP polls of yore. | | I think the OP is using websockets to synchronize game state | across different clients, which can be quite tricky even | without having to deal with scaling or asynchronous | connections. You can use websockets for that, but manual HTTP | syncs/websocket reconnects after a period of radio silence | would not go amiss. Hell, if it's real-time games this is | about, you might even want a custom protocol on top of WebRTC | to get complete control over data ad state with much better | performance. | TameAntelope wrote: | I kludged together subscription support for our GraphQL stack, | and it's super scary because the product people see it working | and are like, "this is awesome!" but sometimes it doesn't totally | work, and I don't think they realize how hard it would be to, | "just make it work all the time". | | I want a "real" non-kludge solution, but it's hard to convince | someone they need to give you money to throw away something that | "works", from their perspective. | phtrivier wrote: | For all the mean things I could say about the language and it's | ecosystem, this is one area where elixir/phoenix/channels shine. | oautholaf wrote: | I worked for a while on a well-known product that used (and | perhaps still uses) WebSockets for its core feature. I very much | agree with the bulk of the arguments made in this blog post. | | In particular, I found this: | | - Our well-known cloud hosting provider's networks would | occasionally (a few times a year) disconnect all long-lived TCP | sockets in an availability zone in unison. That is, an incident | that had no SLA promise would cause a large swath of our | customers to reconnect all at once. | | - On a smaller scale, but more frequently: office networks of | large customers would do the same thing. | | - Some customers had network equipment that capped the length of | time of that a TCP connection could remain open, interfering with | the preferred operation | | - And of course, unless you do not want to upgrade your server | software, you must at some point restart your servers (and again, | your cloud hosting provider likely has no SLA on the uptime of an | individual machine) | | - As is pointed out in the article, a TCP connection can cease to | transmit data even though it has not closed. So attention must be | paid to this. | | If you use WebSockets, you must make reconnects be completely | free in the common case and you must employ people who are | willing to become deeply knowledgeable in how TCP works. | | WebSockets can be a tremendously powerful tool to help in making | a great product, but in general they are almost always will add | more complexity and toil with lower reliability. | | (edited typos) | inopinatus wrote: | None of this is particular to websockets, and in addition: | | > you must employ people who are willing to become deeply | knowledgeable in how TCP works | | You already needed that for your HTTP based application; it's a | fundamental of networked computing. Developers skipping out on | mechanical sympathy are often duds, in my experience. | vlovich123 wrote: | > - Our well-known cloud hosting provider's networks would | occasionally (a few times a year) disconnect all long-lived TCP | sockets in an availability zone in unison. That is, an incident | that had no SLA promise would cause a large swath of our | customers to reconnect all at once. | | I'm kind of surprised that it was that infrequent. I would | expect software upgrades should cause long-lived sockets to | reset... | inopinatus wrote: | or a scale-up of an ELB | xyzzy_plugh wrote: | > disconnect all long-lived TCP sockets in an availability zone | in unison | | I don't know what this means, but it sounds ridiculous. This | would cause havoc with any sort of persistent tunnel or | stateful connection, such as most database clients. Do you | perhaps mean this just happens at ingress? That is much more | believable and not as big of a deal. | | > office networks of large customers would do the same thing. | | Sounds like a personal problem. In all seriousness, your | clients should handly any sort of network disconnect | gracefully. It's foolish to assume TCP connections are durable, | or to assume that you won't be hit by a thundering herd. | | Maybe I'm old fashioned but TCP hasn't changed much over the | years, none of these problems are novel to me, it's well- | trodden ground and there are many simple techniques to building | durable clients. | | Also, all of the things you mention also affect plain old HTTP, | especially HTTP2. There shouldn't be a significant difference | in how you treat them, other than the fact you cannot assume | they're all short lived connections. | oautholaf wrote: | Most applications written using HTTP, in my experience, do | not have deep dependencies on the longevity of the HTTP2 | connection. In my experience, TCP connections for HTTP2 are | typically terminated at your load balancer or similar. So | reconnections here happen completely unseen by either the | client application in the field or the servers where the | business logic is. | | For us -- and I think this is common -- the persistent | WebSocket connection allowed a set of assumptions around the | shared state of the client and server that would have to be | re-negotiated when reconnecting. The fact that this | renegotiation was non-trivial was a major driver in selecting | WebSockets in the first place. With HTTP, regardless of HTTP2 | or QUIC, your application protocol very much is set up to re- | negotiate things on a per-request basis. And so the issues I | list don't tend to affect HTTP-based applications. | xyzzy_plugh wrote: | > the persistent WebSocket connection allowed a set of | assumptions around the shared state of the client and | server that would have to be re-negotiated when | reconnecting. The fact that this renegotiation was non- | trivial was a major driver in selecting WebSockets in the | first place. With HTTP, regardless of HTTP2 or QUIC, your | application protocol very much is set up to re-negotiate | things on a per-request basis. And so the issues I list | don't tend to affect HTTP-based applications. | | I think this describes a poor choice in technology. There's | no silver bullet here, and it sounds like you made a lot of | questionable tradeoffs. Assuming that "session" state | persists beyond the lifetime of either the client or the | server is generally problematic. It's always easier for one | party to be stateless, but you can become stateful for the | duration of the transaction. | | Shared state is best used as communications optimization, | and maybe sometimes useful for security reasons. | tyingq wrote: | >Sounds like a personal problem. In all seriousness, your | clients should handly any sort of network disconnect | gracefully | | That can be complex. Corporate MITM filtering boxes, | "intrusion detection" appliances, firewalls, etc, can just | decide to drop NAT entries, drop packets, break MTU path | discovery, etc. Yes, there are things you can do. But then | customers restart/reload when things don't happen instantly, | etc. I don't know that there's a simple playbook. | bri3d wrote: | I built several large enterprise products over WebSockets. I | didn't find it that bad. | | Office networks that either blocked or killed WebSockets were | annoying. For some customers they were a non-starter in the | early 2010s, but by 2016 or so this seemed to be resolved. | | Avoiding thundering herd on reconnect is a very explored | problem and wasn't too bad. | | We would see mass TCP issues from time to time as well, but | they were pretty much no-ops as they would just trigger a | timeout and reconnect the next time the user performed an | operation. We would send an ACK back instantly (prior to | execution) for any client requested operation, so if we didn't | see the ACK within a fairly tight window, the client could | proactively reap the WebSocket and try again - customers didn't | have to wait long to learn a connection was alive and unclosed. | | > If you use WebSockets, you must make reconnects be completely | free in the common case | | I agree with this, or at least "close to completely free." But | in a normal web application you also need to make latency and | failed requests "close to completely free" as well or your | application will also die along with the network. This is the | point I make in my sibling comment - I think distributed state | management is a hard problem, but WebSockets are just a layer | on top of that, not a solution or cause of the problem. | | > you must employ people who are willing to become deeply | knowledgeable in how TCP works. | | I think this is true insofar as you probably want a TCP expert | somewhere in your organization to start with, but we never | found this particularly complicated. Understanding that the | connection isn't trustworthy (that is, when it says it's open, | that doesn't mean it works) is the only important fundamental | for most engineers to be able to work with WebSockets. | anderspitman wrote: | > Office networks that either blocked or killed WebSockets | were annoying | | Curious how did they detect WS usage? Were you running on | HTTP or did they just kill any long-lived TCP connection? | Root certs? | bri3d wrote: | No, we always ran on TLS. There were a few classes of | these: | | * Filtering MITM application firewall solutions which | installed a new trusted root CA on employee machines and | looked at the raw traffic. These would usually be | configured to wholesale kill the connection when they saw | an UPGRADE because the filtering solutions couldn't | understand the traffic format and they were considered a | security risk. | | * Oldschool HTTP proxy based systems which would blow up | when CONNECT was kept alive for very long. | | * Firewalls which killed long-lived TCP connections just at | the TCP level. The worst here were where there was a | mismatch somewhere and we never got a FIN. But again, | because we had a rapid expectation for an acknowledgement, | we could detect and reap these pretty quickly. | | We also tried running WebSockets on a different port for | awhile, which was not a good idea as many organizations | only allowed 443. | Waterluvian wrote: | I use WebSockets for robots to communicate real-time state with a | web UI. They're the only option and they're fine. | | I get that this article is more focused on a narrow perspective | of the technology. But of course you can make silly use of any | technology. | eska wrote: | I also implemented MQTT for industrial machines to publish data | to a broker. It was trivial to create a web UI that subscribed | to that broker via MQTT over Websockets. But I noticed that | colleagues had this impression that MQTT cannot be used on the | web, so they wanted to build a conversion from MQTT to | SignalR.. a quick search would've cleared it up, but they were | so sure for some reason. After I showed them the demo they just | went with MQTT as well. | jvanderbot wrote: | Author: in this doc, headers are paragraph topic sentences, not | bookmarks for disjoint ideas. | | And they are nonsensical. "Problem: Bumps in the night#". Oh, | thanks, let me bookmark that for easy sharing. | PaulDavisThe1st wrote: | We used WebSockets to build a web-based front end for Ardour, a | native cross-platform DAW, and didn't encounter any of these | issues. Part of that is because the protocol was already defined | (Open Sound Control aka OSC) and used over non-web-sockets | already. But as others have noted, most of the problems cited in | TFA come from the design goals, not the use of websockets. | swagasaurus-rex wrote: | For the very reasons listed in the article, I built: | | https://github.com/siriusastrebe/jsynchronous | | a library for keeping a javascript variables synchronized between | Node.js servers and clients. | | Websockets work great for message passing but it struggles with | data structures more complicated than what JSON can represent. | Jsynchronous syncs any javascript object or array with | arbitrarily deep nesting and full support for circular data | structures. | | If a computer goes to sleep, or disconnects, websocket | connections (and their underlying TCP connections) get reset so | you lose any data sent while a computer is unavailable. This is | catastrophic for state-management if it's left unhandled. | Jsynchronous will re-send any data clients are missing and | reconstructs the shared state. | | There's also a history mode that lets you rewind to past states. | adamddev1 wrote: | Very, very nice! I might use that! Just gotta wrap it a nice | React hook. | anderspitman wrote: | Very cool. I tried something similar once. Have you gone down | the differential/compressed update rabbit hole yet? | swagasaurus-rex wrote: | Right now jsynchronous message passes using custom encoding | in JSON which keeps simple changes as small as an HTTP | header, but with byte level encoding I think this could be | halved. | | Some compression on top would probably do wonders for huge | volumes of changes, though more browsers are supporting | compression on the websocket level. | | I'm not familiar with the name differential update. Instead | of passing potentially large states back and forth, | Jsynchronous numbers each change to your synchronized data | and shares these changes with all connected clients. This is | called Event Sourcing, and it enables jsynchronous to rewind | to previous states by running the changes from start to any | intermediate state. | mgamache wrote: | Using Blazor (.net). It's been mostly a good experience. Fast UI | updates, good programming model. | mwattsun wrote: | I've been looking at it lately and the SignalR tech it uses. | Very nice. My cursory Google research indicates a server using | it can handle about 3000 users, which is not many, but for my | purposes is fine. Blazor makes it completely optional, which I | proved to myself by doing client side Blazor (dot net wasm) | only and using an Apache server instead of IIS with ASP.NET. | | https://en.wikipedia.org/wiki/SignalR | mgamache wrote: | Right, with .net core 6 the runtime wasm is much smaller. | SignalR can be scaled if you need to, but for most sites 3000 | concurrent users is plenty. | wvenable wrote: | We're migrating to server-side Blazor because of the good | experience yet all of the things mentioned in this article are | a concern for using this technology. A few things, especially | around deployment and maintenance, are significantly less good | when your clients are always connected. I'm currently trying to | figure out mitigations. | thisrobot wrote: | Full disclosure I work at MSFT and on the fluid framework. | | If you are interested in this you may also be interested in the | fluid framework, https://github.com/microsoft/FluidFramework | | We use websockets and solve a lot of the state management problem | called out here by keeping very little state on the server | itself. The primary thing on server is a monotonically increasing | integer we use to stamp messages, this gives us total order | broadcast which we then build upon: | https://en.m.wikipedia.org/wiki/Atomic_broadcast | | Here are some code pointers if you want to take a look: | | The map package is a decent place to look for how we leverage | total order broadcast to keep clients in sync in our distributed | data structures: | https://github.com/microsoft/FluidFramework/blob/main/packag... | | The deltamanger in the container-loader package is where we | manage the websocket. It also hits storage to give the rest of | the system a continuous, ordered stream of events: | | https://github.com/microsoft/FluidFramework/blob/main/packag... | | The main server logic is in the Alfred and Deli lambdas. Alfred | sits on the socket and dumps message into Kafka. Deli sits on the | Kafka queue, stamps messages, the puts them on another queue for | Alfred's to broadcast: | https://github.com/microsoft/FluidFramework/tree/main/server... | Philip-J-Fry wrote: | You can turn websockets into a flawless request/response with | async/await included on like 20 lines of JavaScript. I do it all | the time. | | Generate an ID, make a request, store the promise resolve/reject | in a map (js object). Your onmessage handler looks up the promise | based on the ID and resolves the promise. | | Add a few more tiny features like messaging and broadcasting | streams and you've got both request/response and push messaging | over a single websocket. | | It's pretty neat in my opinion, saves having to mix HTTP and | websockets for a lot of things. | anderspitman wrote: | It is neat. I've gone down this path[0]. But you find yourself | essentially re-implementing HTTP, and losing things like | backpressure. Sometimes it's what you need, but I try to be | cautious before jumping to WS these days. | | [0]: https://iobio.io/2019/06/12/introducing-fibridge/ | winrid wrote: | WebSockets are great when used in _addition to_ polling. This | way, you can design a system that doesn 't result in missed | events. Example: have a /events?fromTS=123 endpoint. | | At FastComments - we do both. We use WS, and then poll the event | log when required (like on reconnect, etc). | | Products that can get away with just polling should. In a lot of | scenarios you can just offload a lot of the work to companies | like OneSignal or UrbanAirship, too. | | If you're going to use WS and host the server yourself, make sure | you have plans for being able to shard or scale it horizontally | to handle herds. | | It was hard for us to not use websockets, since like 70% of our | customers pick us for being a "live" solution for live events | etc. | anderspitman wrote: | Is it really worth the extra effort for WS over long polling at | that point though? Especially if you're re-using the TCP | connection it seems like the overhead would be minimal and the | latency only slightly increased. | winrid wrote: | Sorry for the misunderstanding, but I don't mean WS over long | polling. I mean WS _in addition to_ polling, not long | polling. Use websockets, but also expose an API to get the | same events by specifying a timestamp. This way the websocket | server implementation can be much simpler, and the client | just has to call the API to "catch up" on missed events on | reconnect. | | You can also use this API for integrations, and your | clients/consumers will thank you. For example, our third | party integrations use the event log to sync back to their | own data stores. They probably call this every hour, or once | a day. You wouldn't want to use websockets with PHP apps like | WordPress. | te_chris wrote: | Worth looking at Elixir Phoenix Channels if you're wanting to use | sockets. Handle a lot of the messy stuff for you. | | https://hexdocs.pm/phoenix/channels.html | anderspitman wrote: | A few years ago I was more inclined to use WebSockets. They're | undeniably cool. But as implemented in browsers (thanks to the | asynchronous nature of JavaScript) they offer no mechanism for | backpressure, and it's pretty trivial to freeze both Chrome and | Firefox sending in a loop if you have a fast upload connection. | | I designed a small protocol[0] to solve this (and a few other | handy features) which we use at work[1]. A more robust option to | solve similar problems is RSocket[3]. | | More recently I've been working on a reverse proxy[2], and | realized how much of a special case WebSockets is to implement. | Maybe I'm just lazy and don't want to implement WS in | boringproxy, but these days I advocate using plain HTTP whenever | you can get away with it. Server Sent Events on HTTP/1.1 is | hamstrung by the browser connection limit, but HTTP/2 solves | this, and HTTP/3 solves HTTP/2's head of line blocking problems. | | Also, as mentioned in the article, I try to prefer polling. This | was discussed recently on HN[4]. | | [0]: https://github.com/omnistreams | | [1]: https://iobio.io/2019/06/12/introducing-fibridge/ | | [2]: https://boringproxy.io/ | | [3]: https://rsocket.io/ | | [4]: https://news.ycombinator.com/item?id=27823109 | loevborg wrote: | My advice: | | * Make push updates optional. If no push connection can be | established, fall back to polling. You can start by implementing | polling only and add push later. | | * Use websockets only for server-to-client communication. | Messages from the client are sent via regular HTTP requests. | | * Keep no meaningful state on the server. That includes TCP | connection state. You should be able to kill all your ec2 | instances and re-spawn them without interrupting service. | | * Use request/response for all logic on the server. All your code | should be able to run in an AWS lambda. | | * Use a channel/subscription paradigm so client can connect to | streams they're interested in | | * Instead of rolling your own websocket server, use a hosted | service like pusher.com or ably.com. They do all the heavy | lifting for you (like keeping thousands of TCP connections open) | and provide a request/response style interface for your server to | send messages to connected clients | badrabbit wrote: | There is this particular app I have to use for work which relies | heavily on web sockets. It works great so long as your latency is | good. But as soon as your latency is over some threshold the | sheer volume of websocket requests compounds and it becomes | unusable. Normal sites just load slower, they don't fail entirely | like this. | | I guess it goes without saying but devs really need to test their | apps under unfavorable conditions. | austincheney wrote: | The biggest challenge when migrating from HTTP to any kind of | stream is the loss of callback on response, because there is no | request/response. There is only push. That means your messaging | and message handling becomes far more complex to compensate. | | The article mentions that your socket could drop. This isn't | critical so long as you have HTTP as a redundancy. | | For any kind of application making use of micro services I | strongly recommend migrating to a socket first transmission | scheme because it is an insane performance improvement. Also it | means the added complexity to handle message management makes | your application more durable in the face of any type of | transmission instability. The durability means that your | application is less error prone AND it is ready for migration to | other protocols in the future with almost no refactoring. | spicybright wrote: | All of these issues could be solved well by a decent library. Or | even just basic well thought out abstractions. | | I've written a few before from "scratch" myself to decent | success. I don't think there's anything inherent with sockets | that make it impossible to use well. I mean, we've been using | sockets since the beginning of the internet. | | You can write the same article for literally any technology | that's complicated to use without abstractions. | mathgladiator wrote: | That's the core thing is the discover of well thought out | abstractions for a specific domain. I glossed over a lot of the | specific details, but I iterated the pitfalls that I have seen | and how I'm thinking about the abstractions I'm using. | tbeseda wrote: | Archive link with https https://archive.li/R8Nxi | woodruffw wrote: | Just in case the author is listening, I'll play the grammar nazi: | it's "woe unto," not "woe onto." | mathgladiator wrote: | I'll fix when I return to my computer. Thanks | dang wrote: | I was just wondering if anyone had pointed that out. Fixed | above. | | Edit: it probably should be "woe unto". From the King James | Bible: 54 woe unto 24 woe to 2 | woe be unto 1 woe be to | | but "woe be unto" is in there so I guess it's legit enough. | mmzeeman wrote: | You don't have to design a new protocol. There is an open | protocol which works nice for this use case. It can handle | dropping connections, has a nice routing mechanism, it scales | pretty well, has different QoS levels, pub/sub, request/response. | That protocol is... MQTT v5! | | Personally I'm surprised it is not used more often by web devs. | thatswrong0 wrote: | We use this at my place of employment and it's generally OK | except for dealing with reconnects. Also pub/sub | request/response was not nearly as smooth as we had hoped and | eventually we reverted back to HTTP | mmzeeman wrote: | We have build a nice support library for it. | https://github.com/cotonic/cotonic. It helps that our backend | is Erlang. https://github.com/zotonic/zotonic. | [deleted] ___________________________________________________________________ (page generated 2021-12-22 23:00 UTC)