3

I have a server receiving many objects from many clients and that fires ObjectReceived event each time it receives an object, including in the arguments who sent what.

Problem: There is a client annoying my server with requests but my server always responds.

I'd like to throttle requests based on who made it. For example, if I receive 100 requests in 1 second from 100 different clients and each client have made different request, I respond to every client who has made a request; but if I receive 100 requests in 1 second from 2 clients and each clients have done the same request 50 times, I only respond two times, one time to client A and one time to client B.

Is it possible in Rx?

James World
  • 29,019
  • 9
  • 86
  • 120
Mauro Sampietro
  • 2,739
  • 1
  • 24
  • 50
  • 1
    May be. There is some information we are missing. Lets say you want to respond to 1 req/sec but the annoying client is sending them at 100/sec. What do you do with the other 99? Queue them? What happens when the queue is 1,000,000 entries long? Run out of memory? Reject them? Reject them how? – vcsjones Sep 22 '14 at 15:08
  • You are right, edited – Mauro Sampietro Sep 22 '14 at 15:13
  • 1
    The scenario you are facing is known as DOS attack. Security is an aspect of your application, in my opinion you should fix it in the lowest tier possible. Look at this [Prevent Malicious Requests - DOS Attacks](http://stackoverflow.com/questions/14706188/prevent-malicious-requests-dos-attacks) and [Block DoS attacks easily in ASP.NET](http://madskristensen.net/post/Block-DoS-attacks-easily-in-ASPNET). Also checkout comments of the last link for there are couple of improvements suggested. – Marco Medrano Sep 22 '14 at 15:40
  • I certainly agree with the lowest-level sentiment - that said, I've had to put in policies against non-malicious overuse of APIs with complex business domain rules. These days though, that sort of thing is increasingly available through API hosting products like apigee, 3scale etc. Even Azure has one now. – James World Sep 22 '14 at 16:10

2 Answers2

2

Yes, one way is to group the requests by client id and selectively apply a throttle.

Say you had an event like this:

public class MyEvent
{
    public int ClientId { get; set; }

    public override string ToString()
    {
        return ClientId.ToString();
    }
}

Lets set up slow and fast clients:

var slow = Observable.Interval(TimeSpan.FromSeconds(2))
                     .Select(_ => new MyEvent { ClientId = 1 });

var fast = Observable.Interval(TimeSpan.FromSeconds(0.5))
                     .Select(_ => new MyEvent { ClientId = 2 });    

var all = slow.Merge(fast);

Now throttle selectively like this:

var throttled = all.GroupBy(x => x.ClientId).Select(
    // apply the throttle here, this could even test the key
    // property to apply different throttles to different clients
    x => x.Throttle(TimeSpan.FromSeconds(1)))
    .SelectMany(x => x);

And test it:

throttled.Subscribe(x => Console.WriteLine(x.ToString())); 

With this throttle the fast client will never get a response - Throttle will suppress his requests indefinitely because they are less than a second apart. You can use other operators to suppress in different ways - e.g. Sample can pick out a single request over a given time interval.

After your question edit

You can apply different rules than by ClientId and use of Throttle - you can use DistinctUntilChanged() on a client stream to weed out duplicate requests, for example.

James World
  • 29,019
  • 9
  • 86
  • 120
  • Hi, Throttle and Sample actually delay the execution on my subscription. is there a way to respond immediately to the first request and do not accept the same kind of request for a certain amount of time? – Mauro Sampietro Nov 26 '14 at 14:32
  • 1
    @sam Try this. I added a new answer to this old question, that I think addresses all the issues reasonably well: http://stackoverflow.com/questions/7999503/rx-how-can-i-respond-immediately-and-throttle-subsequent-requests/27160392#27160392 – James World Nov 26 '14 at 23:06
0

Slightly different question : Best way to implement request throttling in ASP.NET MVC?

In any case typical algorithm that performs really well would be : Hierarchical Token bucket.

The hierarchical token bucket (HTB) is a faster replacement for the class-based queueing (CBQ) queuing discipline in Linux.

HTBs help in controlling the use of the outbound bandwidth on a given link. HTB allows using one single physical link to simulate multiple slower links and to send different kinds of traffic on different simulated links. In both cases, one has to specify how to divide the physical link into simulated links and how to decide which simulated link a given packet is to be sent across.

In other words, HTB is very useful to limit a client's download/upload rate. Thus, the limited client cannot saturate the total bandwidth.

Community
  • 1
  • 1
Margus
  • 19,694
  • 14
  • 55
  • 103