222

We're experimenting with various ways to throttle user actions in a given time period:

  • Limit question/answer posts
  • Limit edits
  • Limit feed retrievals

For the time being, we're using the Cache to simply insert a record of user activity - if that record exists if/when the user does the same activity, we throttle.

Using the Cache automatically gives us stale data cleaning and sliding activity windows of users, but how it will scale could be a problem.

What are some other ways of ensuring that requests/user actions can be effectively throttled (emphasis on stability)?

4

3 に答える 3

253

これは、過去1年間にStackOverflowで使用してきたものの一般的なバージョンです。

/// <summary>
/// Decorates any MVC route that needs to have client requests limited by time.
/// </summary>
/// <remarks>
/// Uses the current System.Web.Caching.Cache to store each client request to the decorated route.
/// </remarks>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ThrottleAttribute : ActionFilterAttribute
{
    /// <summary>
    /// A unique name for this Throttle.
    /// </summary>
    /// <remarks>
    /// We'll be inserting a Cache record based on this name and client IP, e.g. "Name-192.168.0.1"
    /// </remarks>
    public string Name { get; set; }

    /// <summary>
    /// The number of seconds clients must wait before executing this decorated route again.
    /// </summary>
    public int Seconds { get; set; }

    /// <summary>
    /// A text message that will be sent to the client upon throttling.  You can include the token {n} to
    /// show this.Seconds in the message, e.g. "Wait {n} seconds before trying again".
    /// </summary>
    public string Message { get; set; }

    public override void OnActionExecuting(ActionExecutingContext c)
    {
        var key = string.Concat(Name, "-", c.HttpContext.Request.UserHostAddress);
        var allowExecute = false;

        if (HttpRuntime.Cache[key] == null)
        {
            HttpRuntime.Cache.Add(key,
                true, // is this the smallest data we can have?
                null, // no dependencies
                DateTime.Now.AddSeconds(Seconds), // absolute expiration
                Cache.NoSlidingExpiration,
                CacheItemPriority.Low,
                null); // no callback

            allowExecute = true;
        }

        if (!allowExecute)
        {
            if (String.IsNullOrEmpty(Message))
                Message = "You may only perform this action every {n} seconds.";

            c.Result = new ContentResult { Content = Message.Replace("{n}", Seconds.ToString()) };
            // see 409 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
            c.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
        }
    }
}

使用例:

[Throttle(Name="TestThrottle", Message = "You must wait {n} seconds before accessing this url again.", Seconds = 5)]
public ActionResult TestThrottle()
{
    return Content("TestThrottle executed");
}

ASP.NETキャッシュは、ここではチャンピオンのように機能します。ASP.NETキャッシュを使用すると、スロットルエントリが自動的にクリーンアップされます。また、トラフィックが増加しているため、これがサーバーの問題であるとは考えていません。

この方法についてフィードバックをお寄せください。Stack Overflowを改善すると、Ewokの修正がさらに速くなります:)

于 2009-08-23T08:21:56.053 に答える
69

Microsoft には、IIS 7.0 の動的 IP 制限拡張機能 - ベータ版と呼ばれる IIS 7 の新しい拡張機能があります。

「IIS 7.0 の動的 IP 制限は、Web サーバーおよび Web サイトに対するサービス不能攻撃およびブルート フォース攻撃に対する保護を提供するモジュールです。このような保護は、異常に多数の同時要求を行う HTTP クライアントの IP アドレスを一時的にブロックすることによって提供されます。または短期間に大量のリクエストを行う人。」 http://learn.iis.net/page.aspx/548/using-dynamic-ip-restrictions/

例:

後でブロックする基準を設定した場合、X requests in Y millisecondsまたはX concurrent connections in Y millisecondsIP アドレスがブロックされるY milliseconds場合、リクエストは再び許可されます。

于 2009-02-25T04:10:51.770 に答える
11

この URL http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspxから借用した手法を使用しますが、スロットリングではなく、貧弱な人のサービス拒否 (DOS) のために使用します。これもキャッシュベースであり、あなたがやっていることと似ているかもしれません。DOS 攻撃を防ぐために調整していますか? ルーターは確かに DOS を減らすために使用できます。ルーターが必要なスロットリングを処理できると思いますか?

于 2008-11-14T20:59:30.623 に答える