centrifugal / centrifugo

Scalable real-time messaging server in a language-agnostic way. Self-hosted alternative to Pubnub, Pusher, Ably. Set up once and forever.
https://centrifugal.dev
Apache License 2.0
8.28k stars 584 forks source link

[question] Support for Rate Limiting Messages Sent to Clients #806

Open sky93 opened 4 months ago

sky93 commented 4 months ago

Does Centrifugo currently support or plan to support a feature for rate limiting the number of messages sent to clients from a specific channel? For instance, if my backend sends a high volume of messages (e.g., 2000 messages per second) to Centrifugo, I would like to limit the frequency with which these messages are forwarded to clients. Specifically, I'm interested in a feature where Centrifugo would only send the most recent message from the channel to the client every 2 seconds. This would help in managing client-side message overload without implementing additional logic in the backend. Is there a built-in mechanism in Centrifugo to achieve this, or are there any workarounds you would recommend?

Show us an example of what you mean!: Consider a scenario where my backend service is publishing 2000 messages per second to a channel in Centrifugo. Instead of forwarding every single message to clients, which could overwhelm them, I want Centrifugo to throttle this down such that only the most recent message within a 2-second interval is sent to the clients subscribed to that channel.

Could you provide guidance on whether this functionality exists, or if there are any recommended configurations or practices within Centrifugo to handle such requirements?

FZambia commented 4 months ago

Hello @sky93

Centrifugo does not have sth like this available at the moment, and no plans to add it in the observable future. In general, would be nice to have built-in option to quickly configure – but need to consider how to integrate it with everything else in Centrifugo and distributed environment.

I guess the most effective solution is reducing on the layer before Centrifugo – probably add in-memory rate limiters on your publisher side.

Or add some rate limiting proxy between publisher and Centrifugo. I suppose Nginx can be such proxy - it has built-in leaky bucket limiting and I believe it's possible to configure it to take channel into account. Sth like this (did not test it):

http {
    # Define a key for rate limiting based on the 'channel' URL parameter.
    map $arg_channel $limit_key {
        default "";
        "~^(.+)$" $1;
    }

    limit_req_zone $limit_key zone=per_channel:10m rate=1r/2s;

    server {
        listen 80;
        server_name yourserver.com;

        location /api/publish {
            limit_req zone=per_channel burst=0 nodelay;
            proxy_pass http://centrifugo-upstream;
        }
    }
}

And add channel to request URL when using publish API so that proxy could extract it and rate limit based on it.

But that's just an example. I guess you may find other ways to reduce number of messages published.

What do you think? What is the use case btw where you have 2k messages in a single channel?

sky93 commented 4 months ago

Thank you very much for your detailed response. My use case involves handling market data, where we have multiple markets with frequent updates in price. Given the volume and frequency of data updates, your suggestion to implement an in-memory rate limiter on the publisher side or a rate limiting proxy like Nginx is particularly relevant.

I will look into adapting it to our needs and test its efficacy in managing the data flow to Centrifugo.

Thank you once again for your guidance.