y-crdt / ydotnet

.NET bindings for yrs.
MIT License
35 stars 8 forks source link

Is there any way to use SignalR? #77

Closed vdurante closed 8 months ago

vdurante commented 9 months ago

I was wondering if there is a way of using SignalR instead of WebSockets.

Has anyone achieved this? Is there any example out there on how to do it?

Thanks!

SebastianStehle commented 9 months ago

We have designed the project structure to also support other protocols. But SignalR does not really solve any problem. SignalR is great because of the backplane, but the general problem is that we don't have an architecture for clustering yet.

Yjs documents are potentially big states and you might receive hundred of updates within a short time. Therefore you cannot load the state from the storage for each update. You need to keep it in memory or at least I think that this would be the best option. If you have multiple servers you also don't want to have a copy on each server because you need to synchronize them.

So I think you have a several solutions:

  1. Sticky load balancer sessions using the document ID.
  2. Use something like Microsoft Orleans to have an actor per document (then you can use SignalR) again.
  3. Use a single server.
vdurante commented 8 months ago

@SebastianStehle thanks for the response!

I ended up implementing a SignalR server to see how that would perform. It honestly performs well, but likely won't scale as good as WebSockets.

In my use case I don't see that much concurrent users, so it would work for quite some time before it really requires a refactor. But I definitely understand why it would be much better to use WebSockets in the future.

I will close this for now. Thanks!

SebastianStehle commented 8 months ago

I am not so concerned about the transport protocol. You can just embed the binary protocol in a message and go. if you want to contribute, you are more then welcome. But I don't see how SignalR helps with scaling.

We designed the library to support other protocols, so you contribution would be awesome :)

vdurante commented 8 months ago

SignalR doesn't help with scaling, but it does help if your infrastructure doesn't support websockets, etc. That was my initial problem.

We have a limitation on our infra since it runs on stateless pods and there is no way of keeping an open connection to the pods. Besides that, we also don't have a load balancer that is able to direct all websocket calls to the same pod.

I will definitely contribute once my solution is working decently hehe. Right now it is a mess of code spread everywhere.

SebastianStehle commented 8 months ago

Even if you use SignalR, you get problems, if you have more than one server. It depends on your use case, but if you use ydotnet for a text editor (like prosemirror), you handle every single key stroke. So you get a lot of messages and you cannot load the document for every single key stroke. Perhaps you can use signalr for that together with a stateful set. So you use a stable number of servers and assign the documents based on the hashset of the pod name. Then use SignalR groups and messaging to redirect the message to the correct pod. But it is also not ideal.

Btw: Even with stateless pods your web socket connection should stay open as long as no one closes it. But afaik SignalR also requires sticky sessions: https://learn.microsoft.com/en-us/aspnet/core/signalr/scale?view=aspnetcore-8.0