dsuryd / dotNetify

Simple, lightweight, yet powerful way to build real-time web apps.
https://dotnetify.net
Other
1.17k stars 164 forks source link

WebSocket server-side management #39

Closed tw-bert closed 7 years ago

tw-bert commented 7 years ago

@dsuryd: Thank you for all of your excellent work.

We are working on chat-like funtionality (actually: sending transaction states and other business events to clients). Before stumbling upon dotNetify, I was exploring https://chsakell.com/2016/10/10/real-time-applications-using-asp-net-core-signalr-angular/ , which has a Chat example. The source and blog of chsakell is very good and also usable as a starting point for us, but your dotNetify architecture has an ever greater appeal to me. Especially the React integration, but also the end product: the Angular example of chsakell has to be optimized to be usable from mobile (mainly angular4 seems to make the UX feel very bloated and slow, although I didn't try minimizing/uglifying yet), and your examples work amazingly smooth.

You advice please: When implementing a chat example in dotNetify, should I dive into dotNetify's internals, or should I setup a concurrent websocket route, separate from dotNetify with more control over what happens?

dsuryd commented 7 years ago

Thank you for considering this project! I wasn't clear on the question. What sort of control you'd expect from a separate websocket route, and how do you see it interacting with dotNetify?

Taking a step back, if I were to use dotNetify to implement a scalable chat-like application, this would be my architecture: image

The most important piece would be that backplane object, a long-running instance that manages communication over multiple clients and provides persistence if needed.

For a very simple use case, it would be just an inproc singleton POCO object that the view models subscribe events with. In fact, I have a demo implementation with knockout front-end here.

For a much more scalable and resilient solution, separate the backplane to another server and perhaps use a heavy-duty message broker like RabbitMQ. In this scenario, the weak link would be the client-server communication since signalR doesn't guarantee message delivery. If there is much demand for this in dotNetify, then this is where potentially dotNetify needs to decouple from signalR and implements a more robust protocol.

tw-bert commented 7 years ago

Thank you for your elaborate reply.

The architecture you depict makes sense, and is similar to what I had in mind. At the backplane, we have several systems on different operating systems. For guaranteed message delivery (and order) we have set up a Kafka cluster. We also use RabbitMQ (but migrating to Kafka) and Redis pub/sub + pipelining. It's fine that SignalR doesn't guarantee message delivery. We follow an "eventually consistent" model, in which we combine event driven reactive routes with automatic failover routes.

About the technical implementation of the dotNetify server VM's: I was wondering if dotNetify offered functionality to iterate through all other VM's, and send websocket data to them. By looking at your Bunny Pen example, I can see you have already answered that question too (use your own singleton).


[dsuryd] What sort of control you'd expect from a separate websocket route, and how do you see it interacting with dotNetify?

Thanks again, in a few days I'll start working on a POC. Do you want me to close this issue?

dsuryd commented 7 years ago

It seems you just need a signalR client for Python (quick google says there's one) making calls to dotNetify Hub. Good luck! Let's keep this issue open for a few weeks, others may find the discussion interesting.

tw-bert commented 7 years ago

Yes, I did find that one earlier on. It is however alpha stage, and gevent based which we can't get working on AIX (then again - someone made a PR which strips this dependency). I might start with ws4py, a websocket module I've used before and is solid and mature.

tw-bert commented 7 years ago

After some looking around, I decided that polyglotting with SignalR is too early for production use. Especially when I have to deal with AIX (in)compatibilities, I feel that route is a can of worms. I'll implement a secondary Kestrel instance with "raw" websocket communication on a different non-public port in the dotNetify server process. WAMP might be an alternative to "raw" but that could be implemented in a later stage.