34 ms·
Server-Sent Events: an alternative to WebSockets
- pictur 5y agoDoes SSE offer support for capturing connect/disconnect situations?
- bullen 5y agoThe TCP stack can give you that info if you are lucky in your topography but generally you cannot rely on this working 100%. The way I solve it is to send "noop" messages at regular intervals so that the socket write will return -1 and then I know something is off and reconnect.
- sysid 5y agoFor starlette/fastapi there is a battle tested lib: https://github.com/sysid/sse-starlette https://github.com/sysid/sse-starlette
- whazor 5y agoI tried out server side events, but they are still quite troubling with the lack of headers and cookies. I remember I needed some polyfill version which gave more issues.
- bullen 5y agoHow do you mean lack of headers and cookies? That is wrong. Edit: Actually it seems correct (a javascript problem, not SSE problem) but it's a non-problem if you use a parameter for that data instead and read it on the server.
- tytho 5y agoYou cannot send custom headers when using the built-in EventSource[1] constructor, however you can pass the ‘include’ value to the credentials option. Many polyfills allow custom headers. However you are correct that if you’re not using JavaScript and connecting directly to the SSE endpoint via something else besides a browser client, nothing is preventing anyone from using custom headers. [1] https://developer.mozilla.org/en-US/docs/Web/API/EventSource/EventSource https://developer.mozilla.org/en-US/docs/Web/API/EventSource...
- withinboredom 5y agoI’m pretty sure I saw him sending headers in the talk. Did you watch the talk?
- tytho 5y agoHe was likely using a polyfill. It’s definitely not in the spec and there’s an open discussion about trying to get it added: https://github.com/whatwg/html/issues/2177 https://github.com/whatwg/html/issues/2177
- bullen 5y agoAha, well why do you need to send a header when you can just put the data on the GET URL like so "blabla?cookie=erWR32" for example? In my example I use this code: var source = new EventSource('pull?name=one'); source.onmessage = function (event) { document.getElementById('events').innerHTML += event.data; };
- goodpoint 5y ago--- WebSockets cannot benefit from any HTTP feature. That is: No support for compression No support for HTTP/2 multiplexing Potential issues with proxies No protection from Cross-Site Hijacking --- Is that true? The web never cease to amaze.
- __s 5y agoWebSockets support compression (ofc, the article goes on to detail this & point out flaws. I'd argue that compression is not generally useful in web sockets in the context of many small messages, so it makes sense to be default-off for servers as it's something which should be enabled explicitly when necessary, but the client should be default-on since the server is where the resource usage decision matters) I don't see why WebSockets should benefit from HTTP. Besides the handshake to setup the bidirectional channel, they're a separate protocol. I'll agree that servers should think twice about using them: they necessitate a lack of statelessness & HTTP has plenty of benefits for most web usecases Still, this is a good article. SSE looks interesting. I host an online card game openEtG, which is far enough from real time that SSE could potentially be a way to reduce having a connection to every user on the site
- bullen 5y agoThe problem with WebSockets is that hey are: 1) More complex and binary so you cannot debug them as easily, specially on live and specially if you use HTTPS. 2) The implementations don't parallelize the processing, with Comet-Stream + SSE you just need to find a application server that has concurrency and you are set to scale on the entire machines cores. 3) WebSockets still have more problems with Firewalls.
- sb8244 5y agoI can’t find any downsides of SSE presented. My experience is that they’re nice in theory but the devils in the details. The biggest issue being that you basically need http/2 to make them practical.
- bullen 5y agoAbsolutely not, HTTP/1.1 is the way to make SSE fly: https://github.com/tinspin/rupy/wiki/Comet-Stream https://github.com/tinspin/rupy/wiki/Comet-Stream Old page, search for "event-stream"... Comet-stream is a collection of techniques of which SSE is one. My experience is that SSE goes through anti-viruses better!
- mwcampbell 5y ago> My experience is that SSE goes through anti-viruses better! Hmm, another commenter says the opposite: https://news.ycombinator.com/item?id=30313692 https://news.ycombinator.com/item?id=30313692
- bullen 5y agoHe just needs to push more data on the reply to force the anti-virus to flush the data. Easy peasy.
- anderspitman 5y agoTake this for what it's worth, but I see you share rupy on pretty much every thread that mentions WebSockets, and I click on the link pretty much every time, and I still have basically no idea what it is. Documentation probably isn't your priority at the moment, but even just a couple paragraphs could go a long way.
- ByThyGrace 5y agoI had the same impression as you. I want to learn more about fuse but even their "sales pitch" page is in the same tone of "fuse can do a lot" (and that's fine, I'm sold!) except there is very little documentation at the moment.
- beebeepka 5y agoSo, what are the downsides to using websockets? They are my go-to solution when I am doing a game, chat, or something else that needs interactivity.
- bullen 5y agoSee my comment below: https://news.ycombinator.com/item?id=30313403 https://news.ycombinator.com/item?id=30313403
- herodoturtle 5y agoBeen reading all your comments on this thread (thank you) with interest. Can you recommend some resources for learning SSE in depth?
- bullen 5y agoI would look at my own app-server: https://github.com/tinspin/rupy https://github.com/tinspin/rupy It's not the most well documented but it's the smallest implementation while still being one of the most performant so you can learn more than just SSE.
- mceachen 5y agohttps://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events https://developer.mozilla.org/en-US/docs/Web/API/Server-sent...
- herodoturtle 5y agoThis was awesome! Thanks!
- rawoke083600 5y agoI like them, they surprisingly easy to use.. One example where i found it to be not the perfect solution was with a web turn-based game. The SSE was perfect to update gamestate to all clients, but to have great latency from the players point of view whenever the player had to do something, it was via a normal ajax-http call. Eventually I had to switch to uglier websockets and keep connection open. Http-keep-alive was that reliable.
- bullen 5y agoYou just needed to send a "noop" (no operation) message at regular intervals.
- jcelerier 5y agothat puts it instantly in the "fired if you ever use it" bin
- notreallyserio 5y agoWhy's that?
- Vosporos 5y agoFired for using a keep-alive message???
- coder543 5y agoWith HTTP/2, the browser holds a TCP connection open that has various streams multiplexed on top. One of those streams would be your SSE stream. When the client makes an AJAX call to the server, it would be sent through the already-open HTTP/2 connection, so the latency is very comparable to websocket — no new connection is needed, no costly handshakes. With the downsides of HTTP/1.1 being used with SSE, websockets actually made a lot of sense, but in many ways they were a kludge that was only needed until HTTP/2 came along. As you said, communicating back to the server in response to SSE wasn’t great with HTTP/1.1. That’s before mentioning the limited number of TCP connections that a browser will allow for any site, so you couldn’t use SSE on too many tabs without running out of connections altogether, breaking things.
- lima 5y agoOne issue with SSE is that dumb enterprise middleboxes and Windows antivirus software break them :( They'll try to read the entire stream to completion and will hang forever.
- bullen 5y agoI managed to get through almost all middle men by using 2 tricks: 1) Push a large amount of data on the pull (the comet-stream SSE never ending request) response to trigger the middle thing to flush the data. 2) Using SSE instead of just Comet-Stream since they will see the header and realize this is going to be real-time data. We had 99.6% succes rate on the connection from 350.000 players from all over the world (even satellite connections in the Pacific and modems in Siberia) which is a world record for any service.
- Matheus28 5y agoWhile 350k simultaneous connections is nice, I'd be extremely skeptical of that being any kind of world record
- bullen 5y agoThe world record is not the 1.100 concurrent users per machine (T2 small then medium on AWS) we had at peak, but the 99.6% connections we managed. All other multiplayer games have ~80% if they are lucky! 350.000 was the total number of players during 6 years.
- ta-sus 5y agoTwo nines and a world record, get this man a trophy!
- deleted 5y ago[deleted]
- bullen 5y agoI made the backend for this MMO on SSE over HTTP/1.1: https://store.steampowered.com/app/486310/Meadow/ https://store.steampowered.com/app/486310/Meadow/ We have had a total of 350.000 players over 6 years and the backend out-scales all other multiplayer servers that exist and it's open source: https://github.com/tinspin/fuse https://github.com/tinspin/fuse You don't need HTTP/2 to make SSE work well. Actually the HTTP/2 TCP head-of-line issue and all the workarounds for that probably make it harder to scale without technical debt.
- stavros 5y agoProbably not the same person, but did you ever play on RoD by any chance?
- bastawhiz 5y agoCan you explain how H2 would make it harder to scale SSE?
- bullen 5y agoThe mistake they did was to assume only one TCP socket should be used; the TCP has it's own head-of-line limitations just like HTTP/1.1 has if you limit the number of sockets (HTTP/1.1 had 2 sockets allowed per client, but Chrome doesn't care...) it's easily solvable by using more sockets but then you get into concurrency problems between the sockets. That said if you, like SSE on HTTP/1.1; use 2 sockets per client (breaking the RFC, one for upstream and one for downstream) you are golden but then why use HTTP/2 in the first place? HTTP/2 creates more problems than solutions and so does HTTP/3 unfortunately until their protocol fossilizes which is the real feature of a protocol, to become stable so everyone can rely on things working. In that sense HTTP/1.1 is THE protocol of human civilization until the end of times; together with SMTP (the oldest protocol of the bunch) and DNS (which is centralized and should be replaced btw).
- llacb47 5y agoGoogle uses SSE for hangouts/gchat.
- oneweekwonder 5y agoPersonally i use mqtt over websockets, paho[0] is a good js library. It support last will for dc's and the message queue design makes it easy to think of and debug. There also a lot of mq brokers that will scale well. [0]: https://www.eclipse.org/paho/index.php?page=clients/js/index.php https://www.eclipse.org/paho/index.php?page=clients/js/index...
- dpweb 5y agoVery easy to implement - still using code I wrote 8 years ago, which is like 20 lines client and server, choosing it at the time over ws. Essentially just new EventSource(), text/event-stream header, and keep conn open. Zero dependencies in browser and nodejs. Needs no separate auth.
- samwillis 5y agoI have used SSEs extensively, I think they are brilliant and massively underused. The one thing I wish they supported was a binary event data type (mixed in with text events), effectively being able to send in my case image data as an event. The only way to do it currently is as a Base64 string.
- jtwebman 5y agoSend an event that tells the browser to request the binary image.
- samwillis 5y agoIn my case I was aiming for low latency with a dynamically generated image. To send a url to a saved image, I would have to save it first to a location for the browser to download it form. That would add at least 400ms, probably more. Ultimately what I did was run an SSE request and long polling image request in parallel, but that wasn’t ideal as I had to coordinate that on the backend.
- bckr 5y agoI'm curious if you could have kept the image in memory (or in Redis) and served it that way
- samwillis 5y agoThat’s actually not too far from what we do. The image is created by a backend service with communication (queue and responses) to the front end servers via Redis. However rather than saving the image in its entirety to Redis, it’s streamed via it in chunks using LPUSH and BLPOP. This lets us then stream the image as a steaming http response from the front end, potentially before the jpg has finished being generated on the backend. So from the SSE we know the url the image is going to be at before it’s ready, and effectively long poll with a ‘new Image()’.
- keredson 5y ago
- ravenstine 5y agoI usually use SSEs for personal projects because they are way more simple than WebSockets (not that those aren't also simple) and most of the time my web apps just need to listen for something coming from the server and not bidirectional communication.
- axiosgunnar 5y agoSo do I understand correctly that when using SSE, the login cookie of the user is not automatically sent with the SSE request like it is with all normal HTTP requests? And I have to redo auth somehow?
- bastawhiz 5y agoIt should automatically send first party cookies, though you may need to specify withCredentials.
- foxbarrington 5y agoI’m a huge fan of SSE. In the first chapter of my book Fullstack Node.js I use it for the real-time chat example because it requires almost zero setup. I’ve also been using SSE on https://rambly.app https://rambly.app to handle all the WebRTC signaling so that clients can find new peers. Works great.
- viiralvx 5y agoRambly looks sick, thanks for sharing!
- mmzeeman 5y agoDid research on SSE a short while ago. Found out that the mimetype "text/event-stream" was blocked by a couple of anti-virus products. So that was a no-go for us.
- bastawhiz 5y agoHow did you find that out?
- mmzeeman 5y agohttps://github.com/mmzeeman/mod_sse https://github.com/mmzeeman/mod_sse
- ronsor 5y agoThese days I feel like the only way to win against poorly designed antiviruses and firewalls is to—ironically enough—behave like malware and obfuscate what's going on.
- captn3m0 5y agoI was using SSE when they'd just launched (almost a decade ago now) and never faced any AV issues.
- azinman2 5y agoIs that still the case now? How big and broad an audience do you have? My experience, now a bit dated, is that long polling is the only thing that will work 100% of the time.
- bullen 5y agoThey don't block it, they cache the response until there is enough data in the buffer... just push more garbage data on the first chunks...
- pornel 5y agoIt's not blocked. It's just that some very badly written proxies can try to buffer the "whole" response, and SSE is technically a never-ending file. It's possible to detect that, and fall back to long polling. Send an event immediately after opening a new connection, and see if it arrives at the client within a short timeout. If it doesn't, make your server close the connection after every message sent (connection close will make AV let the response through). The client will reconnect automatically. Or run: while(true) alert("antivirus software is worse than malware")
- szastamasta 5y agoMy experience with sse is pretty bad. They are unreliable, don’t support headers and require keep-alive hackery. In my experience WebSockets are so much better. Also ease of use doesn’t really convince me. It’s like 5 lines of code with socket.io to have working websockets, without all the downsides of sse.
- tekknik 5y ago> Also ease of use doesn’t really convince me. It’s like 5 lines of code with socket.io to have working websockets, without all the downsides of sse. You can also implement websockets in 5 lines (less, really 1-3 for a basic implementation) without socket.ii. Why are you still using it?
- mikojan 5y agoWhat? How do they not support headers? You have to send "Content-Type: text/event-stream" just to make them work. And you keep the connection alive by sending "Connection: keep-alive" as well. I've never had any issues using SSEs.
- szastamasta 5y agoI mean you cannot send stuff from client. If you’re using tokens for auth and don’t want to use session cookies, you end with ugly polyfils.
- coder543 5y ago> If you’re using tokens for auth and don’t want to use session cookies That sounds like a self-inflicted problem. Even if you’re using tokens, why not store them in a session cookie marked with SameSite=strict, httpOnly, and secure? Seems like it would make everything simpler, unless you’re trying to build some kind of cross-site widget, I guess.
- szastamasta 5y agoI need to work with more than 1 backend :)
- kreetx 5y agoSSEs had a severe connection limit, something like 4 connections per domain per browser (IIRC), so if you had four tabs open then opening new ones would fail.
- oplav 5y ago6 connections per domain per browser: https://bugs.chromium.org/p/chromium/issues/detail?id=275955 https://bugs.chromium.org/p/chromium/issues/detail?id=275955 There are some hacks to work around it though.
- coder543 5y agoBrowsers also limit the number of websocket connections. But, if you're using HTTP/2, as you should be, then the multiplexing means that you can have effectively unlimited SSE connections through a limited number of TCP connections, and those TCP connections will be shared across tabs. (There's one person in this thread who is just ridiculously opposed to HTTP/2, but... HTTP/2 has serious benefits. It wasn't developed in a vacuum by people who had no idea what they were doing, and it wasn't developed aimlessly or without real world testing. It is used by pretty much all major websites, and they absolutely wouldn't use it if HTTP/1.1 was better... those major websites exist to serve their customers, not to conspiratorially push an agenda of broken technologies that make the customer experience worse.)
- jcheng 5y ago> Browsers also limit the number of websocket connections True but the limit for websockets these days is in the hundreds, as opposed to 6 for regular HTTP requests.
- coder543 5y agohttps://stackoverflow.com/questions/26003756/is-there-a-limit-practical-or-otherwise-to-the-number-of-web-sockets-a-page-op/26013035#26013035 https://stackoverflow.com/questions/26003756/is-there-a-limi... It appears to be 30 per domain, not “hundreds”, at least as of the time this answer was written. I didn’t see anything more recent that contradicted this. In practice, this is unlikely to be problematic unless you’re using multiple websockets per page, but the limit of 6 TCP connections is even less likely to be a problem if you’re using HTTP/2, since those will be shared across tabs, which isn’t the case for the dedicated connection used for each websocket.
- mythz 5y agoWe use SSE for our APIs Server Events feature https://docs.servicestack.net/server-events https://docs.servicestack.net/server-events with C#, JS/TypeScript and Java high-level clients. It's a beautifully simple & elegant lightweight push events option that works over standard HTTP, the main gotcha for maintaining long-lived connections is that server/clients should implement their own heartbeat to be able to detect & auto reconnect failed connections which was the only reliable way we've found to detect & resolve broken connections.
- easrng 5y agoThough in JS an EventSource does automatically try to reconnect once it notices the connection is dropped, unlike a WebSocket.
- mythz 5y agoIt's not good enough in our experience, EventSource can still think it's connected when the server can no longer push data onto it. The periodic heartbeat to verify messages can still be sent on the connection is the only reliable way we've found to detect & autoretry failed connections.
- dabeeeenster 5y ago"the main gotcha for maintaining long-lived connections is that server/clients should implement their own heartbeat to be able to detect & auto reconnect failed connections" That sounds like a total nightmare!
- ec109685 5y agoDefinitely needed. That would be true for all long lived connection protocols in order to detect connection interruptions in a timely fashion.
- captn3m0 5y agoI think SSE might make a lot of sense for Serverless workloads? You don't have to worry about running a websocket server, any serverless host with HTTP support will do. Long-polling might be costlier though?
- leeoniya 5y agothe biggest drawback with SSE, even when unidirectional comm is sufficient is > SSE is subject to limitation with regards to the maximum number of open connections. This can be especially painful when opening various tabs as the limit is per browser and set to a very low number (6). https://ably.com/blog/websockets-vs-sse https://ably.com/blog/websockets-vs-sse SharedWorker could be one way to solve this, but lack of Safari support is a blocker, as usual. https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker https://developer.mozilla.org/en-US/docs/Web/API/SharedWorke... also, for websockets, there are various libs that handle auto-reconnnects https://github.com/github/stable-socket https://github.com/github/stable-socket https://github.com/joewalnes/reconnecting-websocket https://github.com/joewalnes/reconnecting-websocket https://dev.to/jeroendk/how-to-implement-a-random-exponential-backoff-algorithm-in-javascript-18n6 https://dev.to/jeroendk/how-to-implement-a-random-exponentia...
- bullen 5y agoIt used to be 2 sockets per client, so now it's 6? Well it's a non-problem, if you need more bandwith than one socket in each direction can provide you have much bigger problems than the connection limit; which you can just ignore.
- leeoniya 5y agothe problem is multiple tabs. if you have, e.g. a bunch of Grafana dashboards open on multiple screens in different tabs (on same domain), you will exhaust your HTTP connection limit very quickly with SSE. in most cases this is not a concern, but in some cases it is.
- bullen 5y agoAha, ok yes then you would need to have many subdomains? Or make your own tab system inside one browser tab. I can see why that is a problem for some.
- coder543 5y agoThis isn’t a problem with HTTP/2. You can have as many SSE connections as you want across as many tabs as the user wants to use. Browsers multiplex the streams over a handful of shared HTTP/2 connections. If you’re still using HTTP/1.1, then yes, this would be a problem.
- quickthrower2 5y agoIs it worth upgrading a long polling solution to SSE? Would I see much benefit? What I mean by that is client sends request, server responds in up to 2 minutes with result or a try again flag. Either way client resends request and then uses response data if provided.
- bullen 5y agoYes, since IE7 is out of the game long-polling is no longer needed. Comet-stream and SSE will save you alot of bandwidth and CPU!!!
- layer8 5y agoWhat is particular about IE7? According to https://caniuse.com/eventsource https://caniuse.com/eventsource, SSE is unsupported through IE11.
- bullen 5y agoYou don't need to use Event-Source to use SSE, look at how I implemented it here: https://github.com/tinspin/fuse/blob/master/res/play.html#L160 https://github.com/tinspin/fuse/blob/master/res/play.html#L1... The XHR ready state 3 was wrongly implemented in IE7, they fixed it in IE8.
- jFriedensreich 5y agothis is what i have been telling people for years, but its hard to get the word out there. usually every dev just reflexes without thinking to websockets when anything realtime or push related comes up.
- mmcclimon 5y agoSSEs are one of the standard push mechanisms in JMAP [1], and they're part of what make the Fastmail UI so fast. They're straightforward to implement, for both server and client, and the only thing I don't like about them is that Firefox dev tools make them totally impossible to debug. 1. https://jmap.io/spec-core.html#event-source https://jmap.io/spec-core.html#event-source
- ok_dad 5y ago> the only thing I don't like about them is that Firefox dev tools make them totally impossible to debug You can't say that and not say more about it, haha. Please expand on this? Also, I'm a Fastmail customer and appreciate the nimble UI, thanks!
- coder543 5y agoI think their information could be outdated. Since Firefox 82, you can supposedly inspect the content of SSE streams: https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor/Inspecting_server-sent_events https://developer.mozilla.org/en-US/docs/Tools/Network_Monit... Before that... yeah, the Firefox dev tools were not very helpful for SSE.
- mmcclimon 5y agoHmm! You're right that I hadn't looked it a while, so I checked before making the comment above. I'm still seeing the same thing I always have, which is "No response data available for this request". Possibly something is slightly wrong somewhere (though Chrome dev tools seem fine on the same), but you've given me something to look into, thanks!
- coder543 5y agoThat is interesting. I just tested it myself, and at least for my setup (Firefox on Mac on ARM), the events only showed up in the dev tools if the server closed the SSE connection... so, maybe Firefox still hasn't fully fixed this problem.
- rcarmo 5y agoI have always preferred SSE to WebSockets. You can do a _lot_ with a minuscule amount of code, and it is great for updating charts and status UIs on the fly without hacking extra ports, server daemons and whatnot.
- havkom 5y agoThe most compatible technique is long polling (with a re-established connection after X seconds if no event). Works suprisingly well in many cases and is not blocket by any proxies.
- bullen 5y agolong-polling are blocked to almost exactly the same extent as comet-stream and SSE. The only thing you have to do is to push more data on the response so that the proxy is forced to flush the response! Since IE7 is no longer used we can bury long-polling for good.
- notreallyserio 5y agoHow much more data do you have to send? Is it small enough you aren't concerned about impacting user traffic quotas?
- The_rationalist 5y agofor bidi Rsocket is much better than wevsocket, in fact its official support is the best feature of spring boot
- nickjj 5y agoThis is why I really really like Hotwire Turbo[0] which is a back-end agnostic way to do fast and partial HTML based page updates over HTTP and it optionally supports broadcasting events with WebSockets (or SSE[1]) only when it makes sense. So many alternatives to Hotwire want to use WebSockets for everything, even for serving HTML from a page transition that's not broadcast to anyone. I share the same sentiment as the author in that WebSockets have real pitfalls and I'd go even further and say unless used tastefully and sparingly they break the whole ethos of the web. HTTP is a rock solid protocol and super optimized / well known and easy to scale since it's stateless. I hate the idea of going to a site where after it loads, every little component of the page is updated live under my feet. The web is about giving users control. I think the idea of push based updates like showing notifications and other minor updates are great when used in moderation but SSE can do this. I don't like the direction of some frameworks around wanting to broadcast everything and use WebSockets to serve HTML to 1 client. I hope in the future Hotwire Turbo alternatives seriously consider using HTTP and SSE as an official transport layer. [0]: https://hotwired.dev/ https://hotwired.dev/ [1]: https://twitter.com/dhh/status/1346095619597889536?lang=en https://twitter.com/dhh/status/1346095619597889536?lang=en
- Too 5y agoCan someone give a brief summary of how this differs from long polling. It looks very similar except it has a small layer of formalized event/data/id structure on top? Are there any differences in the lower connection layers, or any added support by browsers and proxies given some new headers? What are the benefits of SSE vs long polling?
- TimWolla 5y ago> What are the benefits of SSE vs long polling? The underlying mechanism effectively is the same: A long running HTTP response stream. However long-polling commonly is implemented by "silence" until an event comes in and then performing another request to wait for the next event, whereas SSE sends you multiple events per request.
- anderspitman 5y agoSSE doesn't support binary data. Text only.
- TimWolla 5y ago> RFC 8441, released on September 2018, tries to fix this limitation by adding support for “Bootstrapping WebSockets with HTTP/2”. It has been implemented in Firefox and Chrome. However, as far as I know, no major reverse-proxy implements it. HAProxy supports RFC 8441 automatically. It's possible to disable it, because support in clients tends to be buggy-ish: https://cbonte.github.io/haproxy-dconv/2.4/configuration.html#3.1-h2-workaround-bogus-websocket-clients https://cbonte.github.io/haproxy-dconv/2.4/configuration.htm... Generally I can second recommendation of using SSE / long running response streams over WebSockets for the same reasons as the article.
- tgv 5y agoBut SSE is a oneway street, isn’t it? The client gets one chance to send days, and that’s it? Or is there some way around it?
- jessaustin 5y agoClients can always send normal http messages to the server. Probably not ideal for "bi-directional" traffic, but it's an option in a pinch.
- steve76 5y ago
- KaoruAoiShiho 5y agoI have investigated SSE for https://fiction.live https://fiction.live a few years back but stayed with websockets. Maybe it's time for another look. I pay around $300 a month for the websocket server, it's probably not worth it yet to try to optimize that but if we keep growing at this rate it may soon be.
- waylandsmithers 5y agoI had the pleasure of being forced to use in SSE due to working with a proxy that didn't support websockets. Personally I think it's a great solution for longer running tasks like "Export your data to CSV" when the client just needs to get an update that it's done and here's the url to download it.
- julianlam 5y agoThis is really interesting! I wonder why it never really took off, whereas websockets via Socket.IO/Engine.io did. At NodeBB, we ended up relying on websockets for almost everything, which was a mistake. We were using it for simple call-and-response actions, where a proper RESTful API would've been a better (more scalable, better supported, etc.) solution. In the end, we migrated a large part of our existing socket.io implementation to use plain REST. SSE sounds like the second part of that solution, so we can ditch socket.io completely if we really wanted to. Very cool!
- shahinghasemi 5y ago> At NodeBB, we ended up relying on websockets for almost everything, which was a mistake. Would you please elaborate on the challenges/disadvantages you've encountered in comparison to REST/HTTP?
- julianlam 5y agoNothing major, just browser support at the beginning, reverse proxy support (which is no longer an issue), but the big one was extensibility. As it turns out, while almost anyone can fire off a POST request, not many people know how to wire up a socket.io client.
- wedn3sday 5y agoThis seems fairly cool, and I appreciate the write up, but god I hate it so much when people write code samples that try and be fancy and use non-code-characters in their code samples. Clarity is much more important then aesthetics when it comes to code examples, if Im trying to understand something I've never seen before, having a bunch of extra non-existant symbols does not help.
- DHowett 5y agoI’m guessing that you are referring to the “coding ligatures” in the author’s font selection for code blocks? You can likely configure your user agent to ignore site-specified fonts.
- asiachick 5y agoAgreed. I use them in my editor but I ban them from my blog posts. They aren't helpful to others
- Rebelgecko 5y agoWhich characters, the funky '≠'? I've seen those pop up a few other times recently, which makes me wonder if there's some editor extension that just came out that maps != and !==
- roywiggins 5y agoThey're ligatures. https://github.com/tonsky/FiraCode https://github.com/tonsky/FiraCode
- loh 5y agoAre you referring to the `!==` and `=>` in their code being converted to what appears to be a single symbol? Upon further inspection, it looks like the actual code on the page is `!==` and `=>` but the font ("Fira Code") seems to be somehow converting those sequences of characters into a single symbol, which is actually still the same number of characters but joined to appear as a single one. I had no idea fonts could do that.
- apitman 5y agoMy personal browser streaming TL;DR goes something like this: * Start with SSE * If you need to send binary data, use long polling or WebSockets * If you need fast bidi streaming, use WebSockets * If you need backpressure and multiplexing for WebSockets, use RSocket or omnistreams[1] (one of my projects). * Make sure you account for SSE browser connection limits, preferably by minimizing the number of streams needed, or by using HTTP/2 (mind head-of-line blocking) or splitting your HTTP/1.1 backend across multiple domains and doing round-robin on the frontend. [0]: https://rsocket.io/ https://rsocket.io/ [1]: https://github.com/omnistreams/omnistreams-spec https://github.com/omnistreams/omnistreams-spec
- rough-sea 5y agoA complete SSE example in 25 lines on Deno Deploy: https://dash.deno.com/playground/server-sent-events https://dash.deno.com/playground/server-sent-events
- gibsonf1 5y agoSolid has a great solution for this: https://solid.github.io/notifications/protocol https://solid.github.io/notifications/protocol
- njx 5y agoMy theory why SSE did not take off is because WordPress does not support it.
- laerus 5y agoWith WebTransport around the corner I don't think is worth the time investing in learning a, what seems to me, obsolete technology. I can understand it for already big projects working with SSE that don't want to pay the cost of upgrading/changing but for anything new I cannot be bothered since Websockets work good enough for my use cases. What worries me though is the trend of dismissal of newer technologies as being useless or bad and the resistance to change.
- slimsag 5y agoI'm confused, you believe that web developers have a trend of dismissing newer technologies and resistance to change? Have I missed something or..?
- coder543 5y agoWebTransport seems like it will be significantly lower level and more complex to use than SSE, both on the server and the client. To say that this "obsoletes" SSE seems like a serious stretch. SSE runs over HTTP/3 just as well as any other HTTP feature, and WebTransport is built on HTTP/3 to give you much finer grained control of the HTTP/3 streams. If your application doesn't benefit significantly from that control, then you're just adding needless complexity.
- jessaustin 5y agoAround the corner? There seems to be nothing about this in any browser. [0] That would put this what, five years out before it could be used in straightforward fashion? Please be practical. [0] https://caniuse.com/?search=webtransport https://caniuse.com/?search=webtransport
- 0xbkt 5y agoSee https://github.com/Fyrd/caniuse/issues/5707 https://github.com/Fyrd/caniuse/issues/5707 and https://chromestatus.com/feature/4854144902889472#consensus https://chromestatus.com/feature/4854144902889472#consensus.
- 5y ago
- pbowyer 5y agoThere's also the Mercure protocol, built on top of Server-Sent Events: https://mercure.rocks/ https://mercure.rocks/
- toomim 5y agoAnd the Braid protocol, using a variation on SSE: https://braid.org https://braid.org
- ponytech 5y agoOne problem I had with WebSockets is you can not set custom HTTP headers when opening the connection. I wanted to implement a JWT based authentication in my backend and had to pass the token either as a query parameter or in a cookie. Anyone knows the rationale behind this limitation?
- charlietran 5y agoThe workaround/hack is to send your token via the "Sec-WebSocket-Protocol" header, which is the one header you're allowed to set in browser when opening a connection. The catch is that your WebSocket server needs to echo this back on a successful connection.
- hishamp 5y agoWe moved away from WebSockets to SSE, realised it wasn't makings thing any better. In fact, it made things worse, so we switched back to WebSockets again and worked on scaling WebSockets. SSE will work much better for other cases, just didn't work out for our case. First reason was that it was an array of connections you loop through to broadcast some data. We had around 2000 active connections and needed a less than 1000ms latency, with WebSocket, even though we faced connections drops, client received data on time. But in SSE, it took many seconds to reach some clients, since the data was time critical, WebSocket seemed much easier to scale for our purposes. Another issue was that SSE is like an idea you get done with HTTP APIs, so it doesn't have much support around it like WS. Things like rooms, clientIds etc needed to be managed manually, which was also a quite big task by itself. And a few other minor reasons too combined made us switch back to WS. I think SSE will suit much better for connections where bulk broadcast is less, like in shared docs editing, showing stuff like "1234 users is watching this product" etc. And keep in mind that all this is coming from a mediocre full stack developer with 3 YOE only, so take it with a grain of salt.
- DaiPlusPlus 5y agoYour write-up sounds like your issues with SSE stemmed from the framework/platform/server-stack you're using rather than of any problems inherent in SSE. I haven't observed any latency or scaling issues with SSE - on the contrary: in my ASP.NET Core projects, running behind IIS (with QUIC enabled), I get better scaling and throughput with SSE compared to raw WebSockets (and still-better when compared to SignalR), though latency is already minimal so I don't think that can be improved upon. That said, I do prefer using the existing pre-built SignalR libraries (both server-side and client-side: browser and native executables) because the library's design takes away all the drudgery.
- Lorin 5y agoIsn't QUIC for IIS still being tested https://techcommunity.microsoft.com/t5/networking-blog/enabling-http-3-support-on-windows-server-2022/ba-p/2676880 https://techcommunity.microsoft.com/t5/networking-blog/enabl...
- alin23 5y agoESPHome (an easy to use firmware for ESP32 chips) uses SSE to send sensor data to subscribers. I made use of that in Lunar (https://lunar.fyi/#sensor https://lunar.fyi/#sensor) to be able to adjust monitor brightness based on ambient light readings from an external wireless sensor. At first it felt weird that I have to wait for responses instead of polling with requests myself, but the ESP is not a very powerful chip and making one HTTP request every second would have been too much. SSE also allows the sensor to compare previous readings and only send data when something changed, which removes some of the complexity with debouncing in the app code.
- U1F984 5y agoThe extra setup step for websocket should not be required: https://caddyserver.com/docs/v2-upgrade#proxy https://caddyserver.com/docs/v2-upgrade#proxy I also had no problems with HAProxy, it worked with websockets without any issues or extra handling.
- francislavoie 5y agoThat's correct, just `reverse_proxy` alone is enough. The request matcher is only needed if you want to make the same request paths get proxied to your HTTP upstream if it doesn't have those websocket connection headers. But if you're always using a path like `/ws` for websockets then you don't need to match on headers.
- jshen 5y agoQuestion for those of you who build features on web using things like SSE or web sockets, how do you build those features in native mobile apps?
- johnny22 5y agoisn't that just an event dispatcher?
- jshen 5y agoHuh? web sockets and SSE are part of the browser standards. When you build an ios or android app you aren't typically building against a browser. Do people typically build completely different solutions for ios and android compared to web?
- andrew_ 5y agoEventSource has been around for eons, and is what the precursor to webpack-dev-server used for HMR events. It had the advantage of supporting ancient browsers since the spec has been around a long time and even supported by oldIE.
- mterron 5y agoI've found hasses (https://github.com/hyper-prog/hasses https://github.com/hyper-prog/hasses) a really nice SSE server. Good performance, easy to use, easy to integrate.