[HN Gopher] WebSockets vs. Server-Sent-Events vs. Long-Polling v...
___________________________________________________________________
WebSockets vs. Server-Sent-Events vs. Long-Polling vs. WebRTC vs.
WebTransport
Author : bubblehack3r
Score : 152 points
Date : 2024-03-18 15:36 UTC (7 hours ago)
(HTM) web link (rxdb.info)
(TXT) w3m dump (rxdb.info)
| kevmo314 wrote:
| 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.
| mmis1000 wrote:
| SSE 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 wrote:
| Agreed - I see SSE as basically a standardized approach to
| modern long polling
| jallmann wrote:
| Long 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 wrote:
| Well 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 wrote:
| One 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.
| ramesh31 wrote:
| >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 wrote:
| Oh, 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 wrote:
| My 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.
| mjevans wrote:
| I've seen a bunch of timeouts / heartbeat / keep alive
| durations. I think it might have been Wireguard, but _25
| seconds_ seems like a good number. Usefully long, most
| things that break are more likely to do it at ~30 seconds,
| and if there 's an active activity push at 15 or 20 seconds
| with device wakeup then the keep alive / connection kill
| might not even happen.
|
| Full Refresh; yes please, in the protocol, with a user
| button, with local client state cached client code and
| reloaded state on reconnect. Maybe even a configurable
| polling period; some services might offer shorter poll as a
| reason to pay for a higher tier account.
| kellengreen wrote:
| I've always had a bit of a soft spot for Server Sent Events. Just
| simple and easy to use/implement.
| djbusby wrote:
| Works with bog-standard Apache prefork and PHP.
| marban wrote:
| Absolutely underrated.
| ajvpot wrote:
| I 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
| TheP1000 wrote:
| Is above still an issue with http2/3?
|
| edit: From the article: To workaround the limitation you have
| to use HTTP/2 or HTTP/3 with which the browser will only open
| a single connection per domain and then use multiplexing to
| run all data through a single connection.
| ravxx wrote:
| just use a service worker to share state, you would be much
| better off doing this anyways. saves a ton and is performant.
| simonw wrote:
| I think you need a SharedWorker for that rather than a
| service worker https://developer.mozilla.org/en-
| US/docs/Web/API/SharedWorke...
| simonw wrote:
| Is that true if you are using HTTP/2?
| andrewmutz wrote:
| You can get around that limit using domain sharding, although
| it feels a bit hacky.
| nine_k wrote:
| Can the tabs share a background worker that would handle
| that?
| merb wrote:
| You can use https://www.npmjs.com/package/broadcast-channel
| which creates a tab leader, no need for a background worker
|
| Edit: of course you could use:
| https://caniuse.com/sharedworkers but android does not
| support it. We migrated to the lib because safari took its
| time... so mobile was/is not a thing for us
| shams93 wrote:
| With ipv6 they can now be fully scaled easily but they are
| absolutely awesome, much easier to scale because you can give
| your client a simple list of sse services and its essentially
| stateless if done right.
|
| Websockets get really complex to scale past a certain level of
| use.
| apitman wrote:
| > With ipv6 they can now be fully scaled easily
|
| Any day now:
| https://www.google.com/intl/en/ipv6/statistics.html
| spintin wrote:
| SSE are really a subset of Comet-Stream (eternal HTTP response
| with Transfer-Encoding: chunked) only they use a header
| (Accept: text/event-stream) and wraps the chunks with "data:"
| and "\n\n".
|
| But yes it's the superior (simplest, most robust, most
| performant and scalable) way to do real-time for eternity.
|
| The browser is dead, but SSE will keep on doing work for native
| apps.
| bterlson wrote:
| Great 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 wrote:
| Server send event IS http response streaming. It is a
| standardized way to implement response streaming.
| bterlson wrote:
| I 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 wrote:
| I'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?
| bterlson wrote:
| If you use the fetch API you can get a readable stream
| and party on without too much difficulty. You can also
| implement a transform stream in ~10SLOC that will make
| the reader vend parsed JSON objects and can be reused
| easily.
| rvanmil wrote:
| Or, 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 wrote:
| My browser has a refresh button. Alas your application likely
| breaks when I use it.
| rvanmil wrote:
| Not entirely sure why it would break...?
| klysm wrote:
| client side state that isn't in the URL or local storage
| chgs wrote:
| Clearly 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.
| cbsmith wrote:
| Honestly, all the techniques for this stuff have their
| problems, including the refresh button.
| rvanmil wrote:
| True, though when carefully implemented it's the most
| reliable option I guess.
| cbsmith wrote:
| I've switched to using SSE to get around problems with the
| refresh button. It's pretty simple and reliable.
| rvanmil wrote:
| That's great. Unfortunately I've seen SSE fail quite a
| few times in the scenario I described.
| ravxx wrote:
| Whoever made this article is pretty clueless. The article states
| using WebRTC would be pointless since you need to run it over
| websockets, sse, or webtransport, but forgets to mention the main
| benefit of WebRTC is that it can be done with UDP. Which is why I
| expect it was faster in the results... I am shocked to not even
| see UDP mentioned in this article.
| realPubkey wrote:
| Author 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 wrote:
| I 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 wrote:
| The 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 wrote:
| > Whoever made this article is pretty clueless
|
| This genre of HN comment irks me. Technical writing is an
| exercise in taking a lot of material and distilling it down to
| an audience. Writing that does a good job this will often look
| basic to someone with a deep understanding of the tech. It
| doesn't mean the author is clueless, it just means they decided
| they made different decisions on what to cut than you would
| have.
| kordlessagain wrote:
| That the author didn't mention UDP "leaves out" the vs.
| objective, however. If it were a fair contest, the article
| would mention the use of WebRTC over UDP, which isn't just
| for streaming media (an assumption I had before doing a bit
| more research on it).
|
| > This article aims to delve into these technologies,
| comparing their performance, highlighting their benefits and
| limitations, and offering recommendations for various use
| cases to help developers make informed decisions when
| building real-time web applications.
|
| So, the article's _intent_ was to help others. When we do
| things like this, we should ensure all technologies being
| evaluated will be covered exhaustively. Otherwise, you risk
| leaving out an important part of the puzzle and then
| assumptions kick in which ignore a possible better solution
| for a given use case.
|
| It looks like UDP use is possible between a browser and a
| server, and that connection has to have components that deal
| with dropout, given it's UDP. There is a LOT to consider and
| deal with implementing UDP over WebRTC, so I put a dump of
| this up here: https://pastebin.com/xgA78dky
| mirekrusin wrote:
| Jsonrpc 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
| cbsmith wrote:
| It'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 wrote:
| Must have been time when spec wasn't stabilized and browsers
| have been introducing it. Those times are long gone.
| cbsmith wrote:
| I don't know about long gone. I still support a websocket
| solution that needs to have server-push as a fallback
| because of browser incompatibility issues.
| apitman wrote:
| Do you have some specific examples?
| cbsmith wrote:
| Old Android handsets seem to be the big ones.
| mirekrusin wrote:
| It shouldn't be a problem for about a decade [0]?
|
| What's your hit rate for the fallback?
|
| [0] https://developer.mozilla.org/en-
| US/docs/Web/API/WebSocket
| cbsmith wrote:
| The hit rate for fallback is pretty low. It was less than
| 5% the last I checked.
| cbsmith wrote:
| I 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 wrote:
| I'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 wrote:
| Hello 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 wrote:
| Actually what he meant is not supported anymore: https://en.m
| .wikipedia.org/wiki/Push_technology#HTTP_server_...
|
| Comet/sse/chunked transfer needs xhr to work. x-mixed-replace
| was wurd 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 wrote:
| Chunked 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.
| merb wrote:
| x-mixed-replace Was the only mechanism that did that and
| chrome removed it and it is not standard and never was
| contravariant wrote:
| I'm so confused. Was x-mixed-replace the only way to use
| chunked transfer encoding (which _is_ part of the HTTP
| standard) or are you talking about something else
| entirely?
| merb wrote:
| actually you can use transfer encoding chunked to stream
| data , but it will get appended and the page would never
| finish loading, that worked back than it works today but
| that is not useful for several reasons and wasn't back
| than.
|
| with x-mixed-replace (as the name implies x-:
| experimentell) you can stream the page over and over
| again and the browser would change to the new version.
| (chrome still supports that for images, cheap webcams)
|
| Tbf without frames neither mechanism made much sense,
| (even back than) because it would be horrible to use with
| form fields.
|
| I started to play with the web in the early 2000s where
| xhr/long-polling/comet(via iframes, later it used xhr
| onreadystatechange with chuncked encoding, without sse,
| which basically was created because of that) started to
| gain traction and x-mixed-replace was extremely niche
| even back than because of the limitations it had on the
| page
|
| Edit: comet (streaming script tags, inside an iframe) of
| course worked, back then. But I never heard of an
| implementation before 2006 (maybe a few years earlier
| like 2-3)or so, would've been worth a Wikipedia change if
| you would have old entries. Also http/1.1 was 97
| cbsmith wrote:
| > actually you can use transfer encoding chunked to
| stream data , but it will get appended and the page would
| never finish loading, that worked back than it works
| today but that is not useful for several reasons and
| wasn't back than.
|
| Oh Server Push has all kinds of issues with it. There are
| lots of good reasons to prefer the newer protocols for a
| lot of use cases.
| arendtio wrote:
| I 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 wrote:
| Aren't mobile push notifications an _entirely_ different tech,
| one that significantly uses the capabilities of mobile
| carriers?
| slt2021 wrote:
| iOS and android push does not rely on mobile carrier
| capability afaik, it has its own service
| psnehanshu wrote:
| Yes, 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 wrote:
| You 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 wrote:
| SSE 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
| cbsmith wrote:
| I thought it was more that the Document object had to
| stay alive. ...although, these days a lot of mobile
| browsers will kill that thing off if the page is not in
| the background, so yeah...
| arendtio wrote:
| I don't know about the implementation details, but even the
| use case is slightly different, as the discussed techs are
| also meant to transfer larger amounts of data. At the same
| time, mobile push is more about triggering synchronization
| than transferring large amounts of data.
|
| However, since the discussed techs all have major problems
| with mobile connections, I still think it should have been
| discussed in more depth.
| skybrian wrote:
| This 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 wrote:
| This presumes the majority of your use case is server-client,
| but otherwise yes.
| apitman wrote:
| One limitation is SSE is text-only, so you can't efficiently
| send binary data. You have to encode it as base64 or similar.
| Fabricio20 wrote:
| To 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 wrote:
| Wait, what?? Been using these for years. Am I missing
| something?
| apitman wrote:
| They're probably referring to browsers specifically. The
| WebSocket constructor doesn't allow for headers
| tytho wrote:
| The 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 wrote:
| Well, 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 wrote:
| > 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.
| michaelt wrote:
| _> To this day I still dont know why WebSockets and SSE dont
| support sending headers on the initial request_
|
| Doesn't the initial request get to send a full set of standard
| HTTP headers, cookies and all?
| paulgb wrote:
| It does, but if you're calling it from the browser you can't
| add arbitrary data to them (the way you can in e.g. a
| `fetch`)
| makkesk8 wrote:
| Someone at Azure thought of this[1]
|
| [1] https://github.com/Azure/fetch-event-source
| pier25 wrote:
| > _you can 't add arbitrary data to them_
|
| What about intercepting the request with a service worker?
| dist-epoch wrote:
| They do send cookies.
| cbsmith wrote:
| There's always TLS certificates... ;-)
| paol wrote:
| Oooh boy you touched a pet peeve. I mean who needs
| authentication on the modern Web right? /s
|
| The even more irritating thing is that there is nothing
| preventing this, and every server I've tried supports it. It's
| only the _browser_ WebSocket API that was designed without
| this. Cookies are the only thing browsers will deign to send in
| the initial request.
| EGreg wrote:
| What 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 wrote:
| Don't assume reliability
| apitman wrote:
| A 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 wrote:
| > 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 wrote:
| > 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.
| 0x457 wrote:
| HTTP/2 traffic was looking essentially the same as HTTP/1.1
| + TLS.
|
| It wasn't particularly interesting to block to begin with.
| UDP if blocked, then it's blocked in a name of Security.
| cbsmith wrote:
| > 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.
|
| Before you were saying, "WebSockets lack flow control
| (backpressure) and multiplexing, so if you need them you
| either roll your own or use something similar to RSocket.",
| and now you're saying you can't roll your own? ;-)
|
| > 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.
|
| Erm, HTTP2 & HTTP 1.1 have their own problems, some of
| which you yourself have identified. We actually rolled back
| from HTTP2 to HTTP 1.1 because of problems with HTTP2,
| particularly with mobile performance.
|
| Our migration to HTTP3 has been all win so far. While UDP
| might be blocked for security reasons, there are security
| reasons to move to HTTP3.
|
| That said, there are cases where only HTTP/1.0 is
| supported.
|
| > 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.
|
| I feel your pain. I've been using WebRTC, and the vast
| majority of the time UDP doesn't seem to be blocked
| anymore. That said, adoption of HTTP3 seems to be about
| half that of HTTP2 right now. Not bad for a brand new
| protocol, but I'd say we still have a significant amount of
| time to go before HTTP3 is the dominant protocol. I think
| the path forward is going to require some toil by the likes
| of you to support both, but no reason you can't support
| HTTP3 better! ;-)
| 0x457 wrote:
| > As long as browsers still work with TCP, some networks will
| continue to block UDP (and thus HTTP3/WebTransport) outright.
|
| I keep hearing it, but I've never actually seen such a network.
| There are many things that run on UDP. I can see it being
| closed in some tiny offices (but those usually lack brain power
| to accomplish it) or some dystopian corporate offices you can
| only see in a movie.
|
| I really don't see how the fact that some networks might ban
| UDP has anything to do with it. Some networks ban google.com
| and wikipedia.com, you don't see them failing.
| apitman wrote:
| In their excellent article on NAT traversal[0], Tailscale
| mentions that the UC Berkeley guest wifi blocks all outbound
| UDP except DNS.
|
| EDIT: According to this[1] issue, Berkeley guest wifi allows
| port 443, which would solve HTTP3/WebTransport. That's
| certainly hopeful, and I hope all networks are like this in
| the future. It's just not a forgone conclusion yet.
|
| [0]: https://tailscale.com/blog/how-nat-traversal-works#have-
| you-...
|
| [1]: https://github.com/danderson/natlab/issues/1
| CodesInChaos wrote:
| Not a traditional network, but Tor doesn't support UDP.
| laurencerowe wrote:
| > As long as browsers still work with TCP, some networks will
| continue to block UDP (and thus HTTP3/WebTransport) outright.
|
| HTTP2 should still work in that scenario then you don't need to
| worry about multiplexing.
| btown wrote:
| Is 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 and
| https://centrifugal.dev/ but not sure if there are more battle-
| tested solutions.
| roopakv wrote:
| Another one to check out 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 wrote:
| There's also Pushpin, if you want the API to blend with your
| existing app.
|
| Disclosure: Pushpin lead dev.
| eightnoteight wrote:
| websockets 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 wrote:
| I 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.
| ascii78 wrote:
| I'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 wrote:
| Works 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/#webr...
| jallmann wrote:
| Browser 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 wrote:
| This is one of my favorite articles along these lines:
|
| https://blog.sequin.io/events-not-webhooks/
| jallmann wrote:
| Yeah 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.
| akira2501 wrote:
| > 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.
| jallmann wrote:
| All that speaks to the point that the underlying protocol
| does not matter that much. The larger design is a more
| important consideration than the specific push tech.
|
| None of this favors SSE, or anything else for that matter.
| You still have to think about bursting / thundering herd
| behavior after server restarts, which would affect any
| protocol. The browser auto reconnecting doesn't mean you can
| assume the connection remains alive indefinitely if a
| reconnect hasn't happened; you may want periodic
| notifications as a keepalive to enable more immediate
| recovery. Long-lived server state introduces its own
| distributed coordination and cleanup problems, which strict
| request-reply polling sidesteps entirely. Etc.
|
| There is no silver bullet, only tradeoffs in the design space
| that need to be matched to your application's requirements.
| akira2501 wrote:
| > the underlying protocol does not matter that much
|
| Then why is long polling the "clear winner?"
| jallmann wrote:
| For interoperability with HTTP tooling (eg, curl) it is
| the clear winner
| tschellenbach wrote:
| (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 wrote:
| I'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 wrote:
| Note 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-t...
| atum47 wrote:
| I 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 wrote:
| I love how SSE is just a "don't close the connection and just
| keep flushing data". I bet IE6 supports this.
___________________________________________________________________
(page generated 2024-03-18 23:01 UTC)