6 ms·
Mercure: A WebSocket alternative for server-sent events
- panarky 2y agoPlease explain why this is better than websockets. I read the Github readme, but it doesn't say what's better.
- gorjusborg 2y agoAlong the same lines, what is the need for an alternative to SSE? There are some issues with SSE in HTTP/1.1, but HTTP/2 pretty much fixes those. I am curious what problem(s) are being targeted with this solution.
- afavour 2y agoThe site offers a little more detail: https://mercure.rocks/ https://mercure.rocks/ Basically its server sent events with some stuff on top: https://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... One big benefit of SSE is that you can put them behind a CDN, making scaling a lot easier. No idea about what Mercure brings there, though.
- conradfr 2y agoIt's targeted at PHP apps. You can use it with Symfony's copy of Phoenix LiveView for example.
- rbrtdrmpc- 2y agoIt is targeted to the PHP community, not the language, it has no dependency on that, it is written in go and is based on caddy. (I’ve contributed with one PR in my former job)
- archerx 2y agoIt’s pretty easy to set up SSE in PHP and works very well. I don’t see how adding this helps at all…
- withinboredom 2y agoIt's really not. Not properly anyway. You'd spend a week, probably, just getting all the synchronization stuff right. Unless of course, you don't care about losing messages during a disconnection. Or you could just install this in a couple of hours and be done with it; not have to worry about security, maintaining NIH libraries, etc.
- archerx 2y agoIt is very easy, I have used it on various projects including chats, live dynamic dash boards, prompters and games. The SSE setup took less than a day, never had issues with sync. Never lost messages during disconnection or any issues. I don’t know how you’ve been using SSE, but if you’ve had all these issues you must have been doing something very wrong.
- julik 2y agoFear of long-lived processes
- archerx 2y agoIt’s not an issue, I’ve had processes running for days without issues.
- upghost 2y agoThey seem to handle a lot of nontrivial issues I have to deal with frequently like synchronization, but weirdly enough they do it with JWTs. For me the entire point of SSEs is that I can avoid using JWTs and use standard session logic which is very easy to reason about. By the way I'm sure JWTs are fine not trying to step on any toes I'm just not an expert with them and I know there are footguns so with security stuff I stick to the most boring technology I have access to.
- Timber-6539 2y agoSSE fixes some of the cargo cult practices formed around Websockets.
- whilenot-dev 2y agoCare to explain a bit more? (otherwise I'd feel like being cargo cultured into SSEs)
- Timber-6539 2y agoGoing off my personal experience I don't see SSE being mentioned anywhere at all. But I always come across some new shiny web framework/wsgi listing websockets as a feature. The reality is a lot of applications simply do not need bi-directional client-server communication but for some reason this abuse has been adopted as standard.
- gorjusborg 2y ago> The reality is a lot of applications simply do not need bi-directional client-server communication but for some reason this abuse has been adopted as standard. I suspect the treatment as 'standard' is what thread OP is talking about. See my sibling comment in the thread. Unless you absolutely need websocket, SSE is simpler, and due to that, better. I suspect the reason many select websocket over SSE is due to its limitations (connection limit under HTTP/1.1, no client->server sends), but SSE for server->client events and normal HTTP requests for state fetching is better architecturally for bog standard apps in my experience.
- gorjusborg 2y agoI have certainly seen people reach for websockets to just reverse the direction of data flow from server to client. On HTTP/1.1, the main issue people can hit is the max connection limit. This connection limit does not apply when using SSE over HTTP/2+, because server connections are multiplexed onto a single connection. I also prefer starting with SSE where possible, as it is simple conceptually, easy to implement (even from scratch), and doesn't introduce a secondary client to server path. Having that ability (even if unused) tends to create a temptation to use it, and when that happens it introduces a choice of whether to use normal HTTP requests or make an equivalent request over websocket. Using websocket for things HTTP can handle is a mistake, in my opinion, because HTTP is simpler than websocket to fetch state. Of course, if you need websocket, you need it, but there are some that just want to play with it in production or add it to their resume. I suspect that dynamic is what causes the 'cargo culting' you talk about.
- kdunglas 2y agoHi, Mercure author here. WebSockets are hard to secure (they totally bypass CORS as well as other browser built-in protections), don't work (yet) with HTTP/3 and for most use cases require to implement many features by yourself: reconnection in case of network failure, refetch of lost messages, authorization, topic mechanism… Mercure, which is built on top of SSE (it's more an extension to SSE than an alternative to it) fix these issues. However, SSE (as well as WebSockets) can be hard to use with stacks not designed to handle persistent connections such as PHP, serverless, most web servers proxying Ruby, Python etc apps. Even for languages designed to handle persistent connections, it's often more efficient and easier to manage persistent connections with ah-hoc software running on dedicated hardware. That's what Mercure allows. Mercure provides a "hub", a server that will maintain the persistent connections with the browsers, store events, and re-send them in case of network issues (or if asked for old messages by a client). To broadcast a message to all connected users, the server app (or even a client) can just send a single POST request to the hub. The hub will also check that clients are authorized to subscribe or publish to a given topic (that's why JWT is used). The reference implementation is written in Go, as a module for the Caddy web server, and his very efficient/optimized (it can handle thousands of persistent connections on very small machines). Install a Mercure hub and you have all these features available without having to write any code. Client-side, no SDK is required, you can embrace the built-in EventSource JavaScript class.
- Thorrez 2y ago> they totally bypass CORS You can reimplement the Same Origin Policy serverside by checking that the Origin header equals the Host header. Even more secure would be to check both against an allowlist (this protects against DNS rebinding, which the Same Origin Policy doesn't protect against). >as well as other browser built-in protections I'm curious what those are. >for most use cases require to implement many features by yourself: [...] authorization Isn't auth of websockets generally the same as auth of any Javascript-initiated HTTP request (e.g. fetch())? Check that the cookie looks good? Now, in the cause of OAuth tokens, websockets are more difficult than fetch(), because you cannot attach an Authorization: Bearer header to a websocket. But OAuth is less common than cookies for websites.
- weitendorf 2y agoIt took a decent amount of digging, but it seems like this is trying to be a browser-compatible pubsub system more than a direct websocket replacement. The main thing they're doing is introducing a "mercure hub" between event producers and consumers (browsers) that handles delivery through SSE in a way that tracks subscribers and handles sporadic or interrupted connection. However what confuses me is that they seem to focus mostly on the protocol, hub, and publish implementation. At least based on a quick glance at https://mercure.rocks/docs/ecosystem/awesome https://mercure.rocks/docs/ecosystem/awesome and elsewhere it seems they expect you to use raw SSE clientside according to their protocol described in eg https://mercure.rocks/spec#active-subscriptions https://mercure.rocks/spec#active-subscriptions. Most of their clientside examples look pretty simple but they don't seem like they're fully implementing the logic described in "Reconnection, State Reconciliation and Event Sourcing" which seems rather complex. Maybe I'm missing something but it seems like that logic is the entire reason to use this over SSE alone.
- kdunglas 2y agoHi, Mercure author here. Indeed that's how it works. One of the key point of the solution is that you don't need anything client-side. The native EventSource class is all you need (but you can use more advanced SSE client libraries if wanted). Reconnection and state reconciliation are achieved automatically. The hub implements all the needed features: it stores sent events and automatically resend them at reconnection time if they have been lost. It's possible to do this transparently because browsers will automatically send the ID of the last received message in a Last-Event-ID header when reconnecting. This feature is just often not implemented by SSE servers (because it’s not trivial to do). It's also possible to ask events received since a specific ID, matching one or several topics just by passing the query parameters defined in the protocol section. By the way, we are working on a new website that will make these things more clear.
- 9dev 2y agoHi Kévin! A while ago, I’ve built a hub implementation using Typescript and Deno, mainly for learning, but also to see if I could come up with a neat solution for distributed event storage in-memory, using Raft. It implements the full spec, so far, and is pretty easy to understand, if I may say so myself. Do you still accept entries for alternative hubs? It may be helpful for others to understand how the specification is supposed to work; some parts were a little opaque to me at first, and required digging into the reference implementation to fully grasp.
- tka85 2y agoDoes it play well behind a load balancer? For example Cloudflare's? And does it work well with non-browser consumers like native mobile apps?
- no_wizard 2y agoThese are the key questions. The biggest issue with SSE is that there is unfortunately alot of deployed software that will downgrade incoming connections to HTTP/1.1 so even if the client would have otherwise supported HTTP/2 or higher its not presented the ability to do so.
- kdunglas 2y agoYes, as it 's "just" SSE, this works pretty well behind Cloudflare and other similar solutions. Mercure also automatically sends the NGINX-specific headers required to allow unbuffered connections. Native mobile apps are also entirely supported. It's a very common use case. Most mobile languages have SSE client libraries.
- qwertox 2y agoReminds me of WAMP (Web Application Messaging Protocol) [0], which is a WebSocket subprotocol. I find the title odd, because, why would you want to replace server-sent events with WebSocket, if the great thing about SSE is the simplicity, both client- and server-side? [0] https://en.wikipedia.org/wiki/Web_Application_Messaging_Protocol#Comparison https://en.wikipedia.org/wiki/Web_Application_Messaging_Prot...
- h4ch1 2y agoDoes it still have the limitation of SSE ie; it'll stop working after you open 6 tabs?
- kdunglas 2y agoThis limitation is gone with HTTP/2 and HTTP/3 and the Mercure hub automatically use the most recent protocol supported by the browser.
- no_wizard 2y agoThat is if the connection isn't downgraded by some other mechanism. Lots of corporate clients downgrade connections to HTTP/1.1 due to how their network is setup. There is also an issue with SSE I've noticed that websockets doesn't seem to have as much of a prevalent issue with, and that is being blocked by corporate firewalls.
- dunglas 2y agoMost websites use TLS, HSTS and the like nowadays. It’s hard for a corporate proxy to downgrade the connection. Also, the limitation is only applied by browsers, not by (reverse) proxies and other non-browsers clients. That being said, Mercure allow to subscribe to many "topics" using a single HTTP connection. This helps mitigating the limitation with HTTP/1 (which is very uncommon these days).
- anonzzzies 2y agoI like it; too much stuff to write yourself with websockets.
- jand 2y agoWas there a specific reason to use AGPL-3.0? Not critizing, just asking. Tried to read about the license and was greeted by a tl;dr summary of the AGPL-3.0 license [1]. I am no lawyer but my gut tells me that providing such a summary is an invitation to strange disputes. Take care. [1] https://mercure.rocks/docs/hub/license https://mercure.rocks/docs/hub/license
- emacsen 2y agoAlso not a lawyer, but discussed this with multiple lawyers. As long as you make very clear that you're summarizing the legal document, but the legal document you're providing is the canonical truth, you're allowed to provide those kind of summaries. For example, Creative Commons has a visual/bullet point explanation of their licenses. That's entirely okay, as the legal text is the core license. I had a similar discussion with a lawyer once about a TOS that also included a summary. The lawyer told me that as long as you make it clear that your summary is just a summary, and is not the agreement, and you point out the actual agreement, you're okay. In this case, the OP is pointing to the legal text clearly and merely summarizing it's most salient points. Again, IANAL and this is not legal advice.
- tuptup 2y ago[dead]
- hellojebus 2y agoWe've been using Mercure for 3+ years in production. It's been pretty much set it and forget it. Maybe once a year do we have to maintain the server e.g. clear up space, but overall has been great for our use case (which does not need full pub/sub).
- bvrmn 2y agoAlso I could recommend https://github.com/slact/nchan https://github.com/slact/nchan. It has the same idea: hide and abstract pubsub complexity for a backend service. nchan is built on top of nginx and could be more convenient (existing nginx configuration knowledge) to deploy.
- dagss 2y agoThe specification appears to be very similar to FeedAPI which I have been involved with: https://github.com/vippsas/feedapi-spec https://github.com/vippsas/feedapi-spec Our focus was kind of the opposite though: Remove the event broker instead of adding one. If I understand correctly, Mercure allows you to push events to the broker and clients pull log-based events. With FeedAPI we focused instead of removing the broker (RabbitMQ/Kafka/...) and let clients pull log-based events directly from backends. Very similar protocol though.
- deleted 2y ago[deleted]
- alt227 2y agoI use PHP/Symfony/Websockets for a real time web app. I have been looking over at SSE/Mercure for a while, as Symfony recomends it for Server->Client traffic. https://symfony.com/doc/current/mercure.html https://symfony.com/doc/current/mercure.html However I am yet to see a reason to swap out my currently working websocket implementation other than SSE is the new shiny thing. Can anybody tell me any other benefits that I may get from making this switch?