I'm working on a silent disco prototype and it's crucial that clients be as close to perfectly in sync as possible
I'm approaching the problem by making use of websockets.. although I'm not yet sure if this is the best solution
Currently I have a test where I trigger a broadcast from a laravel back-end and up to 5 clients that are subscribed to a public channel (using this package) will receive the instruction to play the song
I'm noticing that the 5 clients start to play the song with a latency of 1 - 2 seconds
In the Dashboard, I can only see that there is one event going out. I kind of understand the flow.. you have 5 subscribers, you push an event on a channel and all subscribers are broadcasted the message
But is this broadcast done one-after-the-other ? Or is it all at once? If the former.. how can I make it all at once? Is it a matter of increasing the number of workers in the queue config of wherever laravel-websockets is installed? If not.. would you mind explaining how I might make it possible for lots of people to receive the broadcast all at once or as close to all at once as possible?
Many thanks!
Hey @vesper8,
This specific case is worth to be deeply analyzed and fixed, at least for the 2.0+ version (ETA 1-2 weeks from now on). I'd like to know if the version you tested on is 1.x or 2.x, since 2.x received major improvements over 1.x, such as event dispatching for actions, Async Redis queues, and horizontal scalability.
The way WS works is based on the multicast protocol, meaning that one message gets delivered to multiple clients, and the backend will show it only once. In 2.x we removed the "SENT" logs and focused only on "RECEIVED" logs for the horizontal scalability's sake.
For your use case, backend messaging is not necessarily needed. You can enable client messaging protocol and use the .whisper() method (if you are using Echo) to broadcast client-to-client messaging telling other uses to play that specific song, reducing the need for a backend server, that might cause this latency. I mentioned this because the flow might be: you play a song, send a backend HTTP request that dispatches an event, the event gets dispatched immediately (or sent into a queue, that may cause the delay), and then the users receive the message.
Please let me know further if this is the actual flow. If everything seems to be in order, then a demo app should be created at a separate repo so that we can identify and live-test it properly.
Thank you for the detailed reply @rennokki, some good points you're bringing up.
For your first question, I am using the 2.x-dev branch so I'm on the very latest.
The queue is quite possibly the major cause for the latency. I have to do some more tests to try to identify where the latency occurs.
But I want to make sure I understand.. my laravel-websockets server I don't think uses queuing? The back-end does, which is a separate laravel installation. Once it sends its single request to the laravel-websockets server, then it's up to that server to broadcast to all listeners.. but this doesn't use a queue does it?
Using whisper is probably wise, but I also wanted the song broadcast to be triggerable from the back-end.. but perhaps it's not necessary, or perhaps I can trigger a whisper from the back-end?
Indeed, the WebSockets Server does not use the queue, it just acts like Pusher itself. To get the message and broadcast it accordingly, its HTTP API endpoint /app/{appId}/events gets triggered automatically by the pusher broadcasting driver when you run broadcast(new MyEvent).
I am assuming that the queue might add delay, not latency, because of the ShouldBroadcast interface applied on the event, that should be ShouldBroadcastNow to make sure it gets queued with the sync driver (basically, it runs it immediately): https://laravel.com/docs/8.x/broadcasting#broadcast-queue
If you are using the sync driver, then it's latency and it might be caused by the communication between the Laravel backend and the Pusher server. You might as well make sure that the HTTP calls to the server can be done in the private network (by setting the host parameter of the app to a local IP, for example), to avoid getting that latency between the Laravel backend and the WebSockets server.
Whisper is a great idea only if you know what you are sending between the users. Since you sacrifice security for speed on using whisper, you should take some steps before, like making sure what you're sending. It's not the problem that anyone might be eavesdropping (because you cannot listen to a channel unless you're authorized), but client-to-client communication can be transmuted from the final, compiled js files with a bit of hard work.
So critically-secure actions should not be taken. I think that telling other users what song they should play or broadcasting what song they are playing right now is a proper use case for whispering though.
Most helpful comment
Indeed, the WebSockets Server does not use the queue, it just acts like Pusher itself. To get the message and broadcast it accordingly, its HTTP API endpoint
/app/{appId}/eventsgets triggered automatically by thepusherbroadcasting driver when you runbroadcast(new MyEvent).I am assuming that the queue might add delay, not latency, because of the
ShouldBroadcastinterface applied on the event, that should beShouldBroadcastNowto make sure it gets queued with thesyncdriver (basically, it runs it immediately): https://laravel.com/docs/8.x/broadcasting#broadcast-queueIf you are using the
syncdriver, then it's latency and it might be caused by the communication between the Laravel backend and the Pusher server. You might as well make sure that the HTTP calls to the server can be done in the private network (by setting thehostparameter of the app to a local IP, for example), to avoid getting that latency between the Laravel backend and the WebSockets server.Whisper is a great idea only if you know what you are sending between the users. Since you sacrifice security for speed on using whisper, you should take some steps before, like making sure what you're sending. It's not the problem that anyone might be eavesdropping (because you cannot listen to a channel unless you're authorized), but client-to-client communication can be transmuted from the final, compiled js files with a bit of hard work.
So critically-secure actions should not be taken. I think that telling other users what song they should play or broadcasting what song they are playing right now is a proper use case for whispering though.