20 ms·
I’m gonna be “that jerk on HN,” but this is that idea that just keeps getting rehashed every couple of years then fizzles out. The reason that it’s so attractiv
by keithwhor 6y ago
I’m gonna be “that jerk on HN,” but this is that idea that just keeps getting rehashed every couple of years then fizzles out. The reason that it’s so attractive is because as developers we love to build and save time, and we think, “imagine what we could do if we didn’t have to ask for data from remote servers...”
The problem is that stateful connections suck and create artificial complexity when you don’t need them. Instead of managing the state of your app you’re now managing the state of your app and a connection to a remote server. HTTP is a stateless protocol on top of a stateful socket connection. It wasn’t designed this way by accident.
I’m all for new engineers building SPAs creating exciting new libraries, but HTML-over-websocket has been rehashed at least three times over my professional career so far and it’s not even that long.
Don’t get me wrong — websockets have their use cases. Multiplayer online experiences pretty much require them. It’s just that HTTP isn’t fundamentally broken, and by engineering HTML over websockets you’ll almost universally find yourself building protocols to abstract the state away... re-engineering HTTP in the process.
It’s certainly a fun project which I have personally worked on. But I’m not sure it has legs outside of that. Open to being proven wrong, the authors of HTTP aren’t infallible.
- keithwhor 6y agoAs a thought exercise; - What happens if the client’s internet connection temporarily drops? How do you handle client reconnections and retries? - What if the remote server crashes through no fault of your own (AWS server rack catches fire)? How do you ensure a consistent reconnection that preserves application state? These are just two questions that HTTP + Browsers solved decades ago. Websockets are this cool technology that seems powerful and exciting until you realize the “boring old stateless World Wide Web” was built over decades of iteration using stateful sockets as the backbone, did most of the work for you in tandem with browsers, and is ultimately a lot cooler and more sophisticated than a lot of us give it credit for.
- cogman10 6y agoHere's another one. How do you deploy a new version of your service? Imagine a few customers open up your site and leave for lunch. Or maybe just a random crawler or bot sitting watching for some piece of information they are scraping. These sorts of issues can be challenging with stateless connections. I can only imagine how daunting they are with persistent connections.
- m00dy 6y agoit is called hot-reload.
- meheleventyone 6y agoThe nice thing about persistent connections is that you know when they’ve been closed so you could literally signal that the connection was going down for a deployment and close everyone’s connection. Clients can retry the connection until it comes back up or use another service to monitor the status. Games basically do this routinely.
- rootusrootus 6y agoBut you can do that sort of communication already with existing websockets, without trying to add the complexity of pushing all your regular traffic over that link.
- bitsen 6y agoI bet your ass that at least half of the developers reading HN don’t have caching of JS fully figured out such that when the JS changes server-side and immediately needs reloading on the client side that it does then and there instead of on the next request, the next page refresh, or never because they’ve f’d it up. With server-fed, event-driven pages, you could potentially force refresh.
- lootsauce 6y agomy solution to version changes in a rest api is to sent a version header with every response, the app checks it and if it does not match reloads the page, thus loading the new js.
- mikeryan 6y agoI would not accept your wager. That being said if this was a “really big problem” I’d bet you that most developers on HN would have an idea how to address it.
- galaxyLogic 6y ago
- Graffur 6y agoWhat you mean by sockets in "exciting until you realize the “boring old stateless World Wide Web” was built over decades of iteration using stateful sockets as the backbone". I should probably already know this.
- keithwhor 6y agoHTTP is a stateless protocol built on top of TCP network sockets [0] intended to standardize transfer of hypertext. It's the backbone of the WWW. HTTP is quite literally "hypertext over sockets" so "HTML over websockets" is functionally equivalent... with a layer of abstraction added on top. If you build web software by sending HTML over websockets you're just reinventing what already exists; it's probably why it's never taken off. I think most developers realize within ~weeks to months of working on a "websocket-everything" framework that they're doing more work, not less. [0] https://en.wikipedia.org/wiki/Network_socket https://en.wikipedia.org/wiki/Network_socket
- conradfr 6y agoYou restore the state like you would on a SPA or regular server side rendered page. A crash or someone hitting refresh on his browser is not that different in this respect.
- m00x 6y agoI'm astonished that people are asking these questions while there's obvious answers like this. WSs aren't a magic wand, they just allow you to do more with the same.
- Kranar 6y agoI don't see what's astonishing about it and I'm scratching my head asking the same question. If the answer is that you handle disconnections and reconnections the same way that the HTTP protocol does it, then what's the purpose of HTML over web sockets? You basically end up with a half-assed, buggy, and potentially insecure reimplementation of HTTP running over web sockets running over HTTP at that point. Are you going to do session management and identification by issuing a unique identifier as well? Is that unique identifier going to be valid in perpetuity or have a an expiry date? Is it going to be valid and secure across all sub-domains or will it be prone to cross site scripting attacks?
- ricketycricket 6y ago> then what's the purpose of HTML over web sockets? Because you can do things stateless HTML alone cannot do. No one is trying to re-implement HTTP, or even remove it from the equation. What people are trying to reimplement (or rather, replace) is the HTML + JSON:API + React + Redux mess. Websockets is a means to that end.
- wokwokwok 6y agoHm... great intentions, but you don’t seem to have actually answered any of the questions from the parent comment. Unfortunately, great intentions alone won’t make this work; someone has to actually answer the hard questions about how it’s going to work too. All the answers I’ve seen so far trying to answer them have been vague hand waving... That doesn’t leave me with much confidence.
- coldtea 6y ago>- What if the remote server crashes through no fault of your own (AWS server rack catches fire)? How do you ensure a consistent reconnection that preserves application state? Why would you? Nobody seems to ensure that with regular SPAs anyway...
- the_gipsy 6y agoAlso I've seen request/reponse over websockets too many times.
- egfx 6y agoYou sound like someone that gets it and after reading further it appears you have built an app in this space, and this makes sense. I have too and your right, the coolness of the realtime web is also it's achilles heel. It's not that the web wouldn't be better off realtime, it's just that there is unlikely to be in most cases a time when more than one person if any at all will consume a shared resource. And now you have to account for the most sensible case being the static state of the app where you are over-engineering the realtime features that are not really going to be used that often. In my app I had a a channel state (realtime) and a snapshot state (static). Only thing that made sense in the end was the static snapshot state for content consumption. Here is a short demo of the product: https://www.youtube.com/watch?v=TwkgGBrK_tA https://www.youtube.com/watch?v=TwkgGBrK_tA
- networkimprov 6y agoI built a localhost web app, where the app runs locally and displays its UI in one or more browser tabs. [1] It uses websockets & JSON to connect the SPA UI (in Vue.js) to the app (in Go). That works well, and I can't imagine any advantages to generating HTML with Go, except perhaps less JS code :-) [1] https://github.com/networkimprov/mnm-hammer https://github.com/networkimprov/mnm-hammer
- Martinsos 6y agoDo you have any preferences regarding a direction to simplify web development, remove some of the complexity introduced with client-server separation?
- fartcannon 6y agoUse as little tech as you can. Write HTML, CSS and if you absolutely have to, javascript.
- snejad123 6y agoit's difficult to keep up with the design expectations of the modern web with just HTML and CSS. It's possible but extremely difficult to create a "modern" experience with just html. Just like how we don't build houses with mud-bricks anymore even though it's easier than steel and wood.
- lmarcos 6y agoHow so? One of the most popular (if not the most) websites for developers out there is pretty much HTML + CSS. JavaScript is used, but minimally. "Modern" experience is not necessarily the same as "good" experience. Good old server side rendered pages are fine; SPAs are being built just because "we can", not because they are actually needed (sure, in some cases,SPAs are needed, e.g., chat sites).
- IgorPartola 6y agoAre you talking about Reddit, StackOverflow, or something else? I have yet to see a proper web app (not a blog/collection of static pages, but something that does something complex like let you manage inventory, do payroll, do your taxes, monitor sensors in real time, interact with geographical maps, or edit documents) that is done without JavaScript and has even OK UX. SPAs are great because of separation of concerns. Sever takes care of the data (storing it, syncing it, authenticating your access to it, serving it, sharing it). Client takes care of presentation. I build SPAs because they are better. Imagine if all the apps on your phone or computer were effectively HTML documents rendered on the server. Emacs over HTML/CSS? Minesweeper? World of Warcraft? Would that be an OK experience? Probably not because you don’t want to wait for a page load every time you do something in your Minesweeper game or check stock prices or whatever. Why should web apps be inferior? When people complain about SPAs it’s because they don’t like web apps running in the same environment as their document-based content. I guess some people prefer the ActiveX/JavaApplet model, which to a degree I can understand. Slack is an application, not a website. But let’s not overlook the fact that implementing a Slack client with just HTML and CSS would be miserable to do and miserable to use.
- dnautics 6y ago> The problem is that stateful connections suck and create artificial complexity when you don’t need them. Instead of managing the state of your app you’re now managing the state of your app and a connection to a remote server. HTTP is a stateless protocol on top of a stateful socket connection. It wasn’t designed this way by accident. Seriously, try phoenix liveview if you haven't already. These problems of dealing with stateful connections over questionable tranport and managing them are what the Erlang vm were designed for, and phoenix was designed by rails core team members.
- cortesoft 6y agoIsn’t the issue, though, how do you scale this out? HTTP app servers are great... you can add and remove them at will, based on load, and customers never know the difference, because it only takes a few seconds after not accepting new connections for the existing ones to drain. If you instead have servers holding state, those servers become a lot less ephemeral. In addition, HTTP has built in caching, which is a HUGE benefit for scale.
- ricketycricket 6y agodnautics isn't wrong. Even the issues you bring up are addressed by Erlang/OTP. Distributed Erlang with 10K nodes, hot code reload, etc.
- querulous 6y agothe only people who think distributed erlang is good are people who have never done anything nontrivial with it
- dnautics 6y agoI work on a system with an distributed erlang service mesh.
- hydroxyethane 6y agoCould you explain why that is to someone (me) has never done anything nontrivial with it? Thanks.
- steve76 6y agoSecure cookie. Secure cookie. Secure cookie. WebSockets need the client. How do you pass a secret over WebSockets without using the client? With HTTP, you have that secure layer not accessible to client side code.
- deleted 6y ago[deleted]
- bennysonething 6y agoGenuine question: is this what Microsoft blazor is?
- kevingadd 6y agoBlazor has two modes, one is based on client-server round trips to talk with managed code on the server, the other runs everything on the client using WebAssembly
- shakow 6y ago> Instead of managing the state of your app you’re now managing the state of your app and a connection to a remote server. Wouldn't an intermediate layer such as e.g. Phoenix/LiveView (https://www.phoenixframework.org/ https://www.phoenixframework.org/) solve the problem?
- nickjj 6y ago> Wouldn't an intermediate layer such as e.g. Phoenix/LiveView (https://www.phoenixframework.org/ https://www.phoenixframework.org/) solve the problem? I don't think so but if I'm wrong please correct me. For example, imagine this simple scenario: you load the comment page for this post on HackerNews HackerNews renders an HTTP response to your browser and your browser renders the page based on that HTTP payload. You can be sitting here on the page for 10 minutes reading comments and even if HackerNews randomly went down 20 times for 10 seconds each time during those 10 minutes you would never know because your browser has everything it needed to render the page when it loaded. It's a done deal. The request was made and the response was served. But now let's say you use LiveView and you made this page an actual Live View. Let's also say you load all of the comments at once to keep the example the same. Since there's a persistent websocket connection open at all times, in all 20 cases of HackerNews going down you're going to get a visual warning that the websocket connection was dropped. You also don't want to disable this visual warning because on slower devices it might take 2 seconds to load the page which is much different than an uncontrolled disconnect. IMO this user experience is pretty bad. Why should users be concerned with the server's state after it has everything it needed to handle the request it asked for (loading the comment page). If they try to post a comment and the server is down then the user should see that error at the time of them making the comment (such as a custom 502 error page if the back-end is down). The grandfather's comment of "it wasn't designed this way by accident" is spot on. The stateless web is a happy web. Sure you can sprinkle in websockets for progressive enhancements like broadcasting new content somewhere (which is awesome when done well), but websockets shouldn't be the basis for everything. HTTP has decades of very careful thought and optimizations around its protocol.
- lostcolony 6y agoIf the connectivity state doesn't matter to the user, why would you show it?
- Joeri 6y agoNot only that. The basic problem is latency. We moved logic to the client to be able to update the screen without incurring the latency hit of a server roundtrip. Latency isn’t going down, thanks to physics, so it is going to keep making sense to run logic locally to improve apparent performance. Granted, you need data to render something useful and if an SPA does a data fetch on every click, it might as well be rendered server-side, but still, it is going to keep making sense to render on the device in many cases.
- TheRealPomax 6y agoNote that a websocket round trip is vastly shorter than an http round trip, though. If your payloads are small, 500 consecutive websocket back and forths take orders of magnitude less time than the "traditional" high level url post/fetch becauses there's none of the overhead of an http round trip.
- deleted 6y ago[deleted]
- Matthias247 6y agoA round trip is a round trip. Software can’t beat physics. If you want to do requests in parallel, http 2 and 3 can do them just fine. If it’s sequential, you won’t see a huge difference between something on websockets and http/1.1. The only thing you can save are a few header bytes. And it’s up to you how many headers you use
- hnedeotes 6y agoI'm not going to say web sockets are the silver bullet as I don't think it is, but the "only thing you can save are a few header bytes" is a bit reductionist. If you have authentication then cookies have to be going out also and any other information that has to be kept in order to provide state over a stateless connection. You still need to handshake on each connection (maybe http2/3 bring this down a bit), and you also don't have bidirectional flow, so if you need something resembling client side "real-time" functionality you now have to implement pooling, or server side events. The biggest issue is basically how to load balance/scale and that becomes a problem only given a scale that 98% (scientific) of the websites online won't ever experience.
- tshaddox 6y agoI agree that the good ole stateless HTTP protocol is great, but the thing is, as soon as your web page is simultaneously displaying content from two separate HTTP requests, your web page itself is maintaining state. That's very evident on complex single-page applications like an email, chat, or calendar app, but it's also true even if you load static HTML from a server then have a bit of client-side JavaScript that checks authentication status and shows the visitor's profile picture in the top bar if they're logged in. That's a pretty basic technique that web developers have been doing for probably 20 years, yet it already requires tooling and/or developer thought to manage what is now a stateful computing session.
- eeZah7Ux 6y ago> HTTP is a stateless protocol on top of a stateful socket connection. It wasn’t designed this way by accident. The complexity benefit of having stateless HTTP transactions is vastly offset by the statefulness of TCP, TLS states, HTTP "sessions", cookies, browser storage & so on. HTTP is hardly "designed" and plenty of its aspects were accidental.
- daotoad 6y agoThis seems like a more complicated SPFjs over websockets that is deeply wedded to a particular Ruby framework. http://youtube.github.io/spfjs/ http://youtube.github.io/spfjs/
- jimmont 6y agothe power drain alone, especially for mobile devices, makes this unrealistic
- brightball 6y agoExcept Phoenix LiveView has essentially removed the complexity. Normally I’d agree with your take entirely and I don’t actually think it’s possible to avoid the complexity issues in non-BEAM languages...but Phoenix is absolutely doing it.
- mbreese 6y agoI see websockets as the endpoint for trying to fix two problems in HTTP 1.0 that has been simmering for over two decades. For all of the stateless goodness that HTTP is, in order to have user-specific content, you need to know who you're talking to. The hack to fix this was cookies. Instead of using a traditional stateful protocol (which could have kept track of the logged in user), we had a stateless protocol where the user basically had to present credentials with each request (also, HTTP-AUTH). The second issue was so problematic that it made it into HTTP 1.1 two years later. Because a stateless protocol was used, if you wanted to download say, a document and a linked image in the document, in HTTP 1.0, you needed to make two requests. Back when each web page was predominantly text with few graphics, this was okay. When we moved to more graphical (albeit table-based) layouts, this was horrible. So, HTTP 1.1 ushered in Connection: keep-alive to allow for the same connection to be used for multiple requests. You still had to make individual requests, but at least you didn't have the overhead of setting up multiple TCP connections. HTTP isn't fundamentally broken, but it is a kludge. The most painful parts of HTTP were also the most "stateless" aspects. I agree I don't understand why HTML over Websockets is a (big) thing. It doesn't make much sense to me either. Then again, I was also doing dynamic updates (with javascript pulling in HTML, not XML) before A List Apart (hello again) coined the term AJAX. But let's not just say that HTTP is a perfect stateless protocol. It isn't. It was never "designed this way" -- it was patched up with quick fixes during the late 90's that we've been stuck with ever since. Websockets is the latest attempt to fix this problem. HTTP/2 and /3 don't really do anything to address maintaining session state, but focus on making individual request more efficient (roughly). That still leaves us with the problem of Cookies. Websockets have their own issues (scaling for one), but adopting the approach mentioned in the article doesn't mean that you have to completely abandon the rest of HTTP. But, if I could avoid having every website yelling at me about using cookies, I'd happily adopt a Websocket architecture, if that's what it took.
- thwarted 6y agoWhy isn't an identifier included in each request ("a cookie") not a valid way to track state across requests? It's the solution that makes sense with an otherwise stateless interaction. With a persistent connection, you don't need to send that with each interaction, but the RIP:RPORT:LIP:LPORT tuple becomes the "cookie" that identifies the client or session. > That still leaves us with the problem of Cookies. ... But, if I could avoid having every website yelling at me about using cookies, I'd happily adopt a Websocket architecture, if that's what it took. This is a red herring. If "the problem with cookies" is that websites yell at you about using cookies, that's a legal issue with the requirement to notify users they are being tracked. This "problem" of being yelled at didn't exist before the legal requirement. Moving the transport to websockets (layered on top of HTTP, layered on top of TCP) doesn't get rid of the legal requirement for notification or opt-out. It just buys some time until the law catches up and says that the state management you're using with websockets is also subject to tracking notification and opt-out.
- cookiengineer 6y agoAnybody remember GWT? [1] Let's not go there again. It's the definition of worse than flash. And mostly for above described reasons. Networking, Animation, Transitions, APIs, State of Data, State of Synchronization, Unpredictability and Unreliability of UI/UX States... all mixed together in a single socket. Have fun debugging this blob of autogenerated code and transactions. [1] www.gwtproject.org
- rsj_hn 6y agoAll connections are stateful the moment any kind of volatile data is added. The question is how to manage that state. Say you have a doctor that is associated to a group of patients and is allowed to update their patient's status. And if, while the doctor is filling something out for that patient, the patient changes doctors, then the current operation has to fail and the doctor needs to be notified of this change somehow. So what do you do with the stale list of patients in the browser DOM? Does the UI wait to see if the write fails, or does it increase reactivity by supporting a server push? And how do you tell the DOM to update the list of menu items so that that Patient X is removed from that list? What if half the doctor's patients have been removed? Does the UI wait for the doctor to try to make some change to all of them and one by one remove a patient or does it reload the full patient list? And if so, how often does the browser poll for the full the patient list -- during every operation involving a patient? The server push reduces the amount of time wasted by the doctor filling out stuff for a patient that will be refused by the server anyway, and it avoids costly polling, reducing bandwidth. I get that it may not be worth it, it depends on how important reactivity and bandwidth are to the app, which is why videogame makers need to do it but people writing marketing pages don't. Either way, you have a stateful connection as the set of patients available to that doctor is important connection state that can change at any time. So you are long past the idea of REST whenever you start building an interactive UI with data that must be synced from a remote server. I am not a fan of the server push, but I feel that ship has sailed and people are adding in a lot more complexity for the sake of improved reactivity. My personal rule of thumb would be to always sacrifice reactivity for simplicity, but then this is why I don't build marketing pages.
- aembleton 6y ago> So what do you do with the stale list of patients in the browser DOM? Write the front end in something like Vue. When you catch an error from an axios call, update your data model by calling the server for updates. When the data model updates, Vue will automagically update the DOM used by the browser.
- rsj_hn 6y agoRight, but you can see how in some use cases it's important for the data to be relatively fresh, then you have to choose between polling and server push.
- happyconcepts 6y agoJust sayin' ... this time around ... a) the universe of gamers is larger and b) there's a larger base of phones which can be thought of as thin clients versus a full PC and c) node.js is widespread with Deno upcoming and d) multiplayer VR is closer to reality if it only need to compute one state at the server? Multiplayer online experiences are also growing to include more than gaming, such as betting and gambling and zoom and trading crypto. Are websockets and or browsers improving to handle this server centric shift?
- coldtea 6y ago>The problem is that stateful connections suck and create artificial complexity when you don’t need them. Instead of managing the state of your app you’re now managing the state of your app and a connection to a remote server. HTTP is a stateless protocol on top of a stateful socket connection. It wasn’t designed this way by accident. Then again, it wasn't designed this way to build applications with, either. It was designed to serve documents (the HT in HTTP).
- mathgladiator 6y agoYou're not being a jerk, but you are applying wisdom. The challenge is that if we don't have the courage to be foolish, then we will not make progress. All the problems with a stateful connection are solvable, but we have yet to figure out the right way to teach the discipline of doing it right. It is an exceptionally expensive proposition to solve, so most people shouldn't solve it as they will be picking up a huge bill. The challenge is that HTTP is fundamentally broken for stateful experiences, and people are trying to build that into everything these days. They want shit to update across machines, and polling is exceptionally easy at great cost.