78 ms·
WebSockets vs. Server-Sent-Events vs. Long-Polling vs. WebRTC vs. WebTransport
- kevmo314 3y agoI kind of miss long polling. It was so stupidly simple compared to newer tech, and that's coming from someone who thinks WebRTC is the best thing since sliced bread.
- mmis1000 3y agoSSE isn't really more complex than long polling. The only difference is the server don't close the connection immediately after sent the response. Instead, it wait for data again and send more response using the same stream.
- jacobr1 3y agoAgreed - I see SSE as basically a standardized approach to modern long polling
- jallmann 3y agoLong polling is more amenable than SSE for most HTTP tools out of the box, eg curl. The SSE message body is notably different from plain HTTP responses. To the OP, you can still build APIs with long polling. They are uncommon because push patterns are difficult to design well, regardless of protocol (whether long-polling, SSE, websockets, etc). Whiteboarding a push API is a good exercise. There is a lot of nuance that gets overlooked in discussions whenever these patterns come up.
- kevmo314 3y agoWell I know I can write applications use it, but I don't often write code outside the context of a team that has other opinions anymore :)
- apitman 3y agoOne limitation of SSE compared to long polling (and WebSockets etc) is you can't efficiently send binary data such as cbor, protobuf, etc. Though if your long polling is chatty enough eventually the HTTP overhead will kill your efficiency too.
- niutech 3y agoYou can use binary-sse (https://github.com/luciopaiva/binary-sse https://github.com/luciopaiva/binary-sse) with minimal overhead.
- ramesh31 3y ago>I kind of miss long polling. It was so stupidly simple compared to newer tech, and that's coming from someone who thinks WebRTC is the best thing since sliced bread. I still use it all the time. There are plenty of applications where the request overhead is reasonable in exchange for keeping everything within the context of an existing HTTP API.
- Animats 3y agoOh, if only it were that simple. The networking that makes Second Life go uses long polling HTTPS for an "event channel", over which the server can send event messages to the clients. Most messages go over UDP, but a few that need encryption or are large go over the HTTPS/TCP event channel. At the client end, C++ clients use "libcurl". Its default timeout settings are not compatible with long polling. Libcurl will break connections and make another request. This can result in lost or duplicated messages. At the server end, Apache front-ends the actual simulation servers, to filter out irrelevant connection attempts (Random HTTP attacks that try any open port, probably). Apache has its own timeouts, and will abort connections, forcing the client to retry. There's a message serial number to try to prevent this mechanism from losing messages. The Second Life servers ignore the serial number the client sends back as a check. Some supposedly compatible servers from Open Simulator skip sequential numbers. The end result is an HTTPS based system which can both lose and duplicate what were supposed to be reliable messages. Some of those messages, if lost, will stall out the user's activity in the game. The people who designed this are long gone. The current staff was unaware of how bad the mess is. Outside users had to find the problem and document it. The company staff has been trying to fix this for months. It seems to be difficult enough to fix that the current action is to defer work on the problem. So, no, long polling is not "stupidly simple". The right way to do this is probably to send a keep-alive message frequently enough that the TCP and HTTPS levels never time out. This keeps Apache and libcurl on their "happy paths", which work.
- jallmann 3y agoMy solution to broken connections has actually been to have relatively short timeouts by default, eg 10 seconds. That guarantees we have a fresh connection every so often without any assumptions about liveness. You can even overlap the reconnects a bit (eg 10 second request timeouts, but reconnect every 8 seconds) as long as the application can reconcile duplicated messages - which it should be able to do anyway, for robustness reasons. Really, anytime there is any form of push (whether SSE, long polling, etc) then you need another way to re-hydrate to the full state. In which case you are nearly at the point of doing plain old polling to sidestep the complexity of server-driven incremental updates and all the state coordination problems that entails. Of course with polling, you lose responsiveness. For latency-sensitive applications (like an interactive mmorpg!) then HTTP is probably not the correct protocol to use. It does sound like Second Life has its own special blend of weirdness on top of all that. Condolences to the engineers maintaining their systems.
- niutech 3y agoYou can still use long polling with HTTP/2 nowadays, it isn't going nowhere.
- kellengreen 3y agoI've always had a bit of a soft spot for Server Sent Events. Just simple and easy to use/implement.
- djbusby 3y agoWorks with bog-standard Apache prefork and PHP.
- marban 3y agoAbsolutely underrated.
- ajvpot 3y agoI agree. Unfortunately you can only have 6 SSE streams per origin per browser instance, so you may be limited to 6 tabs without adding extra complexity on the client side. https://crbug.com/275955 https://crbug.com/275955
- ravxx 3y agojust use a service worker to share state, you would be much better off doing this anyways. saves a ton and is performant.
- simonw 3y agoI think you need a SharedWorker for that rather than a service worker https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker https://developer.mozilla.org/en-US/docs/Web/API/SharedWorke...
- jedschmidt 3y agoA service worker would work fine; the connection would be instantiated from the SW and each window/worker could communicate with it via navigator.serviceWorker.
- 3y ago
- bterlson 3y agoGreat comparison. Would love to see http response streaming added to the mix. I think a lot of use cases involving finite streams sent from server to client can be handled by the server streaming JSONL in the response. I tend to prefer this over SSE for finite data streams.
- mmis1000 3y agoServer send event IS http response streaming. It is a standardized way to implement response streaming.
- bterlson 3y agoI agree, but SSE is a more complex protocol that requires additional handling on both client and server, with capabilities that may not be relevant for your use case (multiple event types, event id). For JS clients and JS servers it is not particularly onerous to implement, but for other ecosystems can require a fair bit of code. JSONL streaming is very easy to implement on both ends, so all else aside I think would be preferred if all you really want to do is stream JSON values.
- apitman 3y agoI've implemented SSE from scratch on the server and XHR streaming/parsing from scratch on the client side (which would be necessary for JSONL), and SSE was way simpler. Unless there's another way to do JSONL in a browser that I'm not aware of?
- rvanmil 3y agoOr, if you’re building for clients with a traditional “enterprise” and “secure” IT infrastructure: add refresh buttons and call it a day. If there’s one thing in my experience that consistently fails in these environments and cannot be fixed due to endless red tape, it’s trying to make real-time work for these type of clients.
- chgs 3y agoMy browser has a refresh button. Alas your application likely breaks when I use it.
- rvanmil 3y agoNot entirely sure why it would break…?
- klysm 3y agoclient side state that isn't in the URL or local storage
- chgs 3y agoClearly I don’t know what your application is, but many heavyweight “web apps” don’t cope with a simple refresh, kicking back to a default screen or even login screen in some cases.
- hobobaggins 3y agoSometimes this is to scope logins to single tabs for security reasons (I think that's why Userify does it that way). It's annoying but for infrequently used apps, no worse than getting logged out every three minutes.
- wruza 3y agoAlso some apps ignore simple refresh and only react to hard refresh (ctrl-f5 and alikes). Refresh is as unreliable as other methods from user pov.
- ravxx 3y ago[flagged]
- realPubkey 3y agoAuthor here. The article is mostly about web apps. How would your signaling server emit new connection updates to clients in the scenario you describe?
- andreigheorghe 3y agoI think what they mean is that yes, the signalling needs to be done over "traditional" web APIs (websockets, etc), but that's just for discovering/negotiating the p2p connections. The actual data transfer between the peers then happens over UDP which can have a bunch of advantages over TCP for some scenarios.
- cbsmith 3y agoThe WebRTC section of the article seemed weird in general. The reason WebRTC doesn't specify signaling requirements is that clients can use any communications mechanism they'd like for signaling, and in the case where you are using WebRTC as sever-push mechanism, the "signaling" server and the server you want to receive pushes from could be the same server, allowing the use of "regular" HTTP as the transport for your "signaling" data. With QUIC & HTTP/3, and things like RFC 8441 & 9220, you could well be using UDP with non-WebRTC protocols, and TCP stacks & routers tend to be pretty well tuned these days, so UDP doesn't necessarily have much of an advantage in this kind of use case. If you check out the benchmark the article uses, it specifically breaks out using "unreliable WebRTC/WebTransport". The "unreliable" looks to be referring to UDP (I despise how people misleadingly associate UDP with "unreliable"). They also have "reliable WebRTC/WebTransport", which appears to be using TCP. In the latter case, they actually found in some cases WebTransport doing a tad better in the face of packet loss, which is interesting. I haven't looked at the details of the tests, but in my experience benchmarching WebRTC is not as straightforward as one might expect; it's entirely possible the nature of the benchmark itself is leading to WebRTC's better & worse performance.
- paulgb 3y ago
- mirekrusin 3y agoJsonrpc over websockets is underrated tech. Simple, easy to implement, maps to programming language constructs (async functions, events, errors) which means code looks natural as any library/package/module usage devs are used to, can be easily decorated with type safety, easy to debug, log, optimize etc, works on current browsers and can be used for internal service to service comms, it's fast (ie. nodejs is using simdjson [0]), can be compressed if needed (rarely the need), we built several things on top of it ie. async generators (avoids head of line blocking, maps naturally to typescript/js async generators). [0] https://github.com/simdjson/simdjson https://github.com/simdjson/simdjson
- cbsmith 3y agoIt's been a while since I've used websockets, but at least the last time I did, "simple" wouldn't be the word I'd have used. All kinds of annoying issues between different browsers. SSE was generally much simpler.
- mirekrusin 3y agoMust have been time when spec wasn't stabilized and browsers have been introducing it. Those times are long gone.
- cbsmith 3y agoI always find articles like this amusing, because I designed an online auction system back in the late 90's. No XHR requests at all. Real-time updates were all handled with server-push/HTTP streaming. It wasn't easy to handle all the open connections at the time, but it could be done to an acceptable scale with the right architecture.
- switchbak 3y agoI've spent so many hours trying to communicate to folks the importance of HTTP streaming ... it's an uphill challenge for sure. Yes, all the benefits of http/2 (or 3) are great, but we should also be aware of what we can take advantage of in http 1.1, especially since it's effectively universally supported.
- cbsmith 3y agoHello fellow traveler. ;-) Nobody reads the specs anymore, and to a certain degree I can't blame them, as the protocols/standards have become quite complicated.
- merb 3y agoActually what he meant is not supported anymore: https://en.m.wikipedia.org/wiki/Push_technology#HTTP_server_push https://en.m.wikipedia.org/wiki/Push_technology#HTTP_server_... Comet/sse/chunked transfer needs xhr to work. x-mixed-replace was würd back in the days and still is. Edit: maybe you could also use an iframe/frame which holds a chunked connection but that will only give you text.
- cbsmith 3y agoChunked transfer encoding (which is indeed the underlying mechanism behind server-push) predates XHR, and AFAIK is still supported and will continue to be as long as HTTP/1.1 is still supported. You can use a frame/iframes, but you can also just have content that is updated with multi-part MIME that doesn't cause the page layout to be redone.
- arendtio 3y agoI wonder why mobile push notifications are just a side-note in this article as mobile clients are responsible for a large part of the global traffic.
- nine_k 3y agoAren't mobile push notifications an entirely different tech, one that significantly uses the capabilities of mobile carriers?
- slt2021 3y agoiOS and android push does not rely on mobile carrier capability afaik, it has its own service
- psnehanshu 3y agoYes, iOS has APNS and Android has FCM. One can use FCM for both Android and iOS as FCM is capable of abstracting away APNS. If you are building on React Native with Expo, you can also use Expo Push, which abstracts away both APNS and FCM, albeit it is not fully featured.
- cbsmith 3y agoYou can do mobile push notifications to a phone even if they aren't connected to a mobile carrier. That said, I'd argue SSE is the browser equivalent of mobile push notifications.
- jallmann 3y agoSSE generally requires the page to be active in the foreground, which is not a viable solution for mobile. Web Push is a distinct API for browsers to emulate native push notifications via service workers. https://developer.mozilla.org/en-US/docs/Web/API/Push_API https://developer.mozilla.org/en-US/docs/Web/API/Push_API
- 3y ago
- skybrian 3y agoThis is probably naive, but it seems like assuming HTTP/2 or better, an EventSource combined with fetch() for sending messages should be just as good as any other protocol that uses a single TCP connection? And HTTP/3 uses UDP, so even better. (This all assumes you only care about maintaining a connection when the tab is in the foreground.) I’m wondering what problems people have run into when they tried this.
- jacobr1 3y agoThis presumes the majority of your use case is server-client, but otherwise yes.
- apitman 3y agoOne limitation is SSE is text-only, so you can't efficiently send binary data. You have to encode it as base64 or similar.
- niutech 3y agoThere is another alternative to base64: https://github.com/luciopaiva/binary-sse https://github.com/luciopaiva/binary-sse
- ksec 3y agoWas thinking exactly the same thing. H2 with SSE solves 99% of problems? I was wondering if we could push SSE even further along with lower latency, memory usage and CPU resources than doing something completely different.
- nchmy 3y agoThis library does what you are looking for https://www.npmjs.com/package/@microsoft/fetch-event-source https://www.npmjs.com/package/@microsoft/fetch-event-source
- Fabricio20 3y agoTo this day I still dont know why WebSockets and SSE dont support sending headers on the initial request, such as Authorization. Leaving authentication on realtime services entirely up to whoever is implementing the service. I may be wrong here and the spec suggests a good way to do it, but i've seen so many different approaches that at this point might as well say there's none.
- omgtehlion 3y agoWait, what?? Been using these for years. Am I missing something?
- apitman 3y agoThey're probably referring to browsers specifically. The WebSocket constructor doesn't allow for headers
- tytho 3y agoThe browser EventSource constructor does not have options to pass in your own headers. You can pass an option to have it use the cookies for the domain you’re using. There are libraries that allow you to pass in additional HTTP options, but they essentially reimplement the built-in EventSource object in order to do so. Not terribly difficult, fairly simple spec.
- omgtehlion 3y agoWell, that constructor by default sends all the headers you have for your own domain and auth you are entitled to. This is how all other APIs in browsers work due to security and privacy concerns. If you call to other domains, then this problem is no different to what we had with CORS years ago.
- apitman 3y ago> This is how all other APIs in browsers work due to security and privacy concerns They're probably comparing it to the fetch and XHR APIs, which both allow custom headers.
- EGreg 3y agoWhat I want to know is, on iOS can we have Web Workers running for a few hours when the browser is in the background, with setInterval communicating w the network or will they get suspended?
- psnehanshu 3y agoDon't assume reliability
- jamil7 3y agoiOS apps can't really do this so I'd assume browser apps can't either. There are specific background scheduler APIs you need to go through on iOS to do this in which the OS decides when to run these tasks and you have very little control.
- nchmy 3y agoThe article is from rxdb, which has various mechanisms to handle such considerations
- EGreg 3y agoLike what ?
- JimothyQing 3y ago[dead]
- apitman 3y agoA few additional cons to be aware of: WebSockets lack flow control (backpressure) and multiplexing, so if you need them you either roll your own or use something similar to RSocket. Also SSE can't send binary data directly. You have to base64 encode it or similar. WebTransport addresses these and also solves head of line blocking. But I'm concerned that we might run into a similar problem as we had with going from Python2 to Python3 and IPv6. Too easy for people to keep using the old version, and too little (perceived) benefit to upgrading. As long as browsers still work with TCP, some networks will continue to block UDP (and thus HTTP3/WebTransport) outright.
- cbsmith 3y ago> WebSockets lack flow control (backpressure) and multiplexing, so if you need them you either roll your own or use something similar to RSocket. Yes, head of line blocking is an issue, but TCP provides flow control, and if you're not using that, you're going over HTTP3. > WebTransport addresses these and also solves head of line blocking. But I'm concerned that we might run into a similar problem as we had with going from Python2 to Python3 and IPv6. Too easy for people to keep using the old version, and too little (perceived) benefit to upgrading. At one time or another, one could have said the same thing about TLS transport, HTTP3, or XHR itself. Because of the comparatively huge domination of a few key browser engines, it's much easier to roll out new browser capabilities & protocols. > As long as browsers still work with TCP, some networks will continue to block UDP (and thus HTTP3/WebTransport) outright. By that logic, as long as browsers still work with HTTP 1.1 without TLS, some networks will continue to block HTTP 2 and TLS. While that's not entirely incorrect, the broad adoption of HTTP2 and TLS in particular suggests it's less of a problem than you think.
- apitman 3y ago> Yes, head of line blocking is an issue, but TCP provides flow control Unfortunately, the way browsers implement WebSocket it undermines TCP's flow control. It's trivial to crash a browser tab by opening a (larger than RAM) file and trying to stream it to a server using a tight loop sending on a WebSocket. WebSocket.bufferedAmount exists, but as of 2019 I failed to use it to solve this problem and had to implement application-level backpressure. > At one time or another, one could have said the same thing about TLS transport, HTTP3, or XHR itself. Because of the comparatively huge domination of a few key browser engines, it's much easier to roll out new browser capabilities & protocols. > By that logic, as long as browsers still work with HTTP 1.1 without TLS, some networks will continue to block HTTP 2 and TLS. While that's not entirely incorrect, the broad adoption of HTTP2 and TLS in particular suggests it's less of a problem than you think. HTTP3 actually falls under my concern. There are still networks that block HTTP3, because it has really nice fallback to HTTP2/1.1, so there's no obvious impact on users. So I guess the real question is will QUIC be an HTTP/2 or an IPv6, or something in between? Was HTTP/2 ever actively blocked the way UDP is? If so that certainly gives us hope. The reason I care is that I'm currently developing a protocol that WebTransport is an excellent fit for. But I can't assume WebTransport will work because UDP might be blocked, so I'm having to implement WebSocket support as well, which is a lot more work.
- btown 3y agoIs there a modern open-source solution for bridging a traditional stateless web application to real-time notifications - one that's implemented all the best practices from the OP? Something like pusher.com but on self-hosted infrastructure/k8s, where messages from clients are turned into webhooks to an arbitrary server, and the server can HTTP POST to a public/private channel that clients can subscribe to if they know the channel secret. I've come across https://github.com/soketi/soketi https://github.com/soketi/soketi and https://centrifugal.dev/ https://centrifugal.dev/ but not sure if there are more battle-tested solutions.
- roopakv 3y agoAnother one to check out https://partykit.io https://partykit.io They are building on top of Cloudflare, and getting started is a breeze. That being said they are also fairly new, but based on everything I have seen, I am a fan
- jkarneges 3y agoThere's also Pushpin, if you want the API to blend with your existing app. Disclosure: Pushpin lead dev.
- kdunglas 3y agoI maintain the Mercure protocol (built on SSE) and the reference implementation (written in Go, available as a standalone binary and a Caddy module) which does exactly that: https://mercure.rocks https://mercure.rocks In addition to the free and open source server, we also provide a cloud offering and on-premises versions that support clustering using Redis Streams, Kafka, Pulsar or Postgres LISTEN/NOTIFY as backends. The solution is used by many big actors in production for years: How Raven Controls uses Mercure to power big events such as Cop 21 and Euro 2020: https://api-platform.com/con/2022/conferences/real-time-and-beyond-with-mercure/ https://api-platform.com/con/2022/conferences/real-time-and-... Pushing 8 million Mercure notifications per day to run mail.tm: https://les-tilleuls.coop/en/blog/mail-tm-mercure-rocks-and-api-platform https://les-tilleuls.coop/en/blog/mail-tm-mercure-rocks-and-... 100,000 simultaneous Mercure users to power iGraal: https://speakerdeck.com/dunglas/mercure-real-time-for-php-made-easy https://speakerdeck.com/dunglas/mercure-real-time-for-php-ma...
- eightnoteight 3y agowebsockets and sse are a big headache to manage at scale, especially backend, requires special observability, if not implemented really carefully on mobile devices its a nightmare to debug on frontend side devices switch off network or slow down etc,... for battery conservation, or when you don't explicitly do the I/O using a dedicated API for it. new connection setup is a costly operation, the server has to store the state somewhere and when this stateful layer faces any issue, clients keep retrying and timing out. forever stuck on performing this costly operation. it's not like there is an easy way to control the throughput and slowly put the load on database reliability wise long polling is the best one IME, if event based flow is really important, even then its better to have a 2 layer backend, where frontend does long polling on the 1st layer which then subscribes to websockets to the 2nd layer backend. much better control in terms of reliability
- debarshri 3y agoI cannot agree more with you. I have seen people shot themselves on foot with Websockets and SSE. Long Polling even though is expensive, is it most explainable and scalable approach in my opinion.
- pornel 3y agoSSE supports long polling. You can make the server close the connection whenever you want. SSE supports automatic reconnection, and will even include the last ID seen to let the server continue seamlessly.
- hobobaggins 3y agoIt's important to remember that SSE won't automatically reconnect for quite a few HTTP status codes (i.e., upstream proxy outages like 50x error codes)
- nchmy 3y agoA lot of this was addressed in the linked article - rxdb has mechanisms to mitigate many of your concerns...
- ascii78 3y agoI've been reading about WebRTC, does anyone actually know if browser to browser communication actually works reliably in practice ? Specifically NAT traversal, been hesitant to research it further because of this issue, seems that most of the connection parts seem to be legacy voip related protocols.
- Sean-Der 3y agoWorks well! Lots of developers/companies use WebRTC with NAT Traversal. You can also use it in a client/server setup. Check out 'WebRTC SFU' I wrote a little bit about the different topologies in [0] [0] https://webrtcforthecurious.com/docs/08-applied-webrtc/#webrtc-topologies https://webrtcforthecurious.com/docs/08-applied-webrtc/#webr...
- jallmann 3y agoBrowser push APIs are hard to design well regardless of the underlying protocol (SSE, Long Polling, Websockets, etc). There are a bunch of things to consider: - Is this a full or partial state update? - What if the client misses an update? - What if the client loses connectivity? - How can the server detect and clean up clients that have disappeared? How those are answered in turn raise more questions. SSE or long polling or even WebSockets is a relatively unimportant implementation detail. IMO the bigger consideration should probably be ease-of-use and tooling interoperability. For that, I would say that long polling (or even just polling) is the clear winner.
- apitman 3y agoThis is one of my favorite articles along these lines: https://blog.sequin.io/events-not-webhooks/ https://blog.sequin.io/events-not-webhooks/
- jallmann 3y agoYeah that is a great article, and I agree that long polling an events endpoint along with a cursor gets you most of the way there for browser clients. At that point, things start to resemble the Kafka protocol.
- nchmy 3y agoGreat article, thanks for sharing. NATS is an excellent option along these lines, particularly with their nats.ws library https://nats.io/ https://nats.io/
- akira2501 3y ago> Is this a full or partial state update? It's a message. Mapping protocol units to messages was always your business. > What if the client misses an update? Sequence numbers on updates combined with a "fill in" mechanism through a separate request. > What if the client loses connectivity? Then more important things won't work either. > How can the server detect and clean up clients that have disappeared? The SSE client will restart dropped connections. You can have the server opportunistically close connections that haven't received messages recently. The browser will automatically reconnect if the object is still alive on the client side. > For that, I would say that long polling (or even just polling) is the clear winner. Coordinating polling intervals while simultaneously avoiding strong bursting behavior is genuinely not fun.
- tschellenbach 3y ago(I work at Stream, we power activity feeds, chat and video calling/streaming for some very large apps) You should in most cases just use websockets with a keep-alive ping every 30 seconds or so. It's not common anymore to block websockets on firewalls, so fallback solutions like Faye/Socket.io are typically not needed anymore. WebTransport can have lower latency. If you're sending voice data (outside of regular webrtc), or have a realtime game its something to consider.
- ambigious7777 3y agoI'm making a WASM browser dungeon crawler game using WebTransport. It currently does not have great support -- namely Safari -- but because of other API incompatibilities I'm not planning on supporting Safari :P WebTransport is a bit more work than other ones, like SSE, but the flexibility and performance make it work it IMO.
- cookiengineer 3y agoNote that the author misses an essential point: custom compression dictionaries, which can only be used by WebSockets (WS13) and hardly by the others, as that would break compatibility. I'd argue that you can push websocket data usage way lower than the other protocols, if you use a binary compression based on a predefined schema. In WebSockets, you can use plug&play extensions which can modify the payload on both the client and the server, which make them also ideal for tunneling and peer-to-peer applications. I've written an article from an implementer's perspective a while ago, in case you are interested [1] [1] https://cookie.engineer/weblog/articles/implementers-guide-to-websockets.html https://cookie.engineer/weblog/articles/implementers-guide-t...
- nchmy 3y agoWill this still be the case now that Shared Dictionary support is being rolled out in Chromium? https://developer.chrome.com/blog/shared-dictionary-compression https://developer.chrome.com/blog/shared-dictionary-compress...
- atum47 3y agoI did some testing with using SSE to send push notifications to my phone if someone set off a sensor, worked kinda good, but the browser had to be running in the background in order for it to work. After that i implemented a chat for a meme app that I've created to share memes with my friends, using websocket (Open Swoole) it is working nicely also. Never tested to see how many clients it can handle at once, but i guess the bottleneck would be in my server, not the software. Open Swoole is very easy to setup and there's lots of tutorials online. Got my ass kicked a little bit trying to making my websocket secure (wss) but I'm the end it worked fine.
- lxe 3y agoI love how SSE is just a "don't close the connection and just keep flushing data". I bet IE6 supports this.
- hobobaggins 3y agoThere are at least two polyfills for it, but I think most of them require at least IE10. (but IE6 has so many other issues that probably 90% of your other JS won't work anyway... so glad it's gone!)
- lgrapenthin 3y ago> Long-Polling: The least scalable due to the high server load generated by frequent connection establishment, making it suitable only as a fallback mechanism. That makes no sense. Long-polling scales linearly like all the other ones as well.
- hnav 3y agothere are a few ways that long-polling is "least scalable" - other approaches give you locality without sticky load-balancing: let's say your application server needs to subscribe to a topic once a connection is established, with long polling you need to setup and teardown that subscription every time, other approaches let you keep that HTTP stream alive and periodically send some stuff on it resulting in mostly just memory overhead. - each returned payload will result in at least 1 extra packet (the initial request headers, assuming the response headers and the payload fit into a packet) and at least 1/2 RTT delay.
- londons_explore 3y agoA decent number of corporate firewalls still don't support web sockets... That means if you build something that requires web sockets, prepare to have a deluge of support/refund requests from the most valuable clients who think your site is broken. I suggest just having a once-per-second polling fallback, perhaps with an info bar saying 'the network you are connected to is degrading your experience'.
- cpursley 3y agoCertainty this can’t be true? I believe you but do you have any actual examples?
- londons_explore 3y agoAll UK government offices doesn't seem to allow it... That's a couple of million potential users right away.
- HackerThemAll 3y agoJust use SignalR. It'll automatically choose whatever comes through.
- paddybyers 3y agoYes it's true. At Ably we support websockets, SSE and comet fallbacks (simple long-polling and streamed long-polling). It's less and less common but there are firewalls that fail to handle websockets correctly, or simply block them. I can't name specific companies/examples, but call centers are one example - the network and desktop environments are fully locked down. We also see in these cases that streamed HTTP can also be broken by the firewall - for example a chunked response can be held back by the firewall and only forwarded to the client when the request ends, as a fixed-length response. Obviously that breaks SSE and means you can't just use streamed comet as a fallback when websockets don't work.
- cpursley 3y ago
- lakomen 3y agoSSE in gin (go) is broken and has been for years. No one uses it and no one bothers to fix it.
- hobobaggins 3y agor3labs/sse seems pretty good, but doesn't seem to handle backpressure or defend against slow-client attacks. (actually, I haven't seen any libs that do.. maybe this isn't a problem for anyone?) You could roll your own, since the protocol is extremely simple.
- nchmy 3y agoGood thing there's other ways to implement SSE - be it in Go or many other servers and languages...
- WuxiFingerHold 3y agoThat's a really small data point. I bet there're many projects using Go with SSE.
- elwell 3y agoMan... I was trying to use WebRTC over ten years ago to implement livestreaming from your phone's camera *within a PhoneGap app*! Didn't work too well.
- tdudhhu 3y agoNot in the article by also relevant is short polling. While this does not send messages from a server to a client it can still be useful when all other options are not available (on shared hosting for example). In my experience it even works great when the poll interval is long (for example 20 seconds) but when you also include the message list in each response. That way the client will be up to date when it interacts with the server: user presses a button -> the client sends a request to the server -> the server reponds with data and also a list of the latest messages.
- kybernetikos 3y agoIt's also applicable for fast changing data where the proportion of polls that gets an update is high too.
- T3RMINATED 3y ago[dead]
- Zekio 3y agoNever had a good experience with anything using Server-Sent-Events, this especially goes for TFS, open a tab too many and all your TFS tabs just freeze
- dustedcodes 3y agoHTTP (POST) AJAX calls + SSE is one of the simplest ways to implement bi-directional real time functionality. IMHO this is a much more robust and nicer way than web sockets for a huge amount of applications which use web sockets today.
- pthatcherg 3y agoThe article's information about WebRTC is not accurate. You can do client/server WebRTC without a "signaling server". Just make the server do the signaling. It takes a few extra round trips, but it doesn't need to be an extra server. And WebRTC data channels work quite well as a replacement for WebSockets or SSE, especially if you want to avoid head-of-line blocking. And there are many libraries that will do pretty much all of the work for you, like Pion or str0m. I also think calling the WebTransport API complex is overblown. If you don't want the more advanced things, you can ignore them. If you want to use it like a WebSocket, just open one bidirectional stream and you're basically done. If you want to avoid head-of-line blocking, just open a stream for every message. It's a little more complex, but it's not the kind of thing you need a library for. Github Copilot will probably write the code for you. It's true there aren't as many server libraries out there yet, since WebTransport is still maturing. And we're waiting for Safari to add support.
- cyanydeez 3y ago> You can do client/server WebRTC without a "signaling server" Huh. The signalling server is implemented in websocket, typically. It cant be implemented in webrtc unless you propose a existing decentralization of existing clients to boostrap'
- FZambia 3y agoHello, I am author of https://github.com/centrifugal/centrifugo https://github.com/centrifugal/centrifugo. Our users can choose from WebSocket, EventSource, WebTransport (experimental for now, but will definitely stabilize in the future). WebRTC is out of scope as the main purpose is central server based real-time json/binary messaging, and WebRTC makes things much more complex since it shines for peer-to-peer and rich media communications. What I'd like to add is that Centrifugo also supports HTTP-streaming – not mentioned by the OP – but this is a transport which has advantages over Eventsource - like possibility to send POST body on initial request from web browser (with SSE you can not), it supports binary, and with Readable Streams browser API it's widely supported by modern browsers. Another thing I'd like to mention about Centrifugo - it supports bidirectional WebSocket fallbacks with EventSource and HTTP-streaming, and does this without sticky sessions requirement in distributed scenario. I guess nobody else have this at this point. See https://centrifugal.dev/blog/2022/07/19/centrifugo-v4-released#modern-websocket-emulation-in-javascript https://centrifugal.dev/blog/2022/07/19/centrifugo-v4-releas.... Which solves one more practical concern. Sticky sessions is an optimization in Centrifugo case, not a requirement. If you are interested in topic, we also have a post about WebSocket scalability - https://centrifugal.dev/blog/2020/11/12/scaling-websocket https://centrifugal.dev/blog/2020/11/12/scaling-websocket - it covers some design decisions made in Centrifugo.