[asp.net-mvc] ASP.NET MVC에서 요청 조절을 구현하는 가장 좋은 방법은 무엇입니까?

우리는 주어진 기간 동안 사용자 행동을 조절하는 다양한 방법을 실험하고 있습니다 .

  • 질문 / 답변 게시물 제한
  • 편집 제한
  • 피드 검색 제한

당분간은 캐시를 사용하여 단순히 사용자 활동 레코드를 삽입하고 있습니다. 사용자가 동일한 활동을 수행하는 경우 해당 레코드가 존재하는 경우 스로틀합니다.

캐시를 사용하면 자동으로 오래된 데이터 정리 및 사용자 슬라이딩 활동 창이 제공되지만 어떻게 확장되는지 문제가 될 수 있습니다.

요청 / 사용자 작업을 효과적으로 조절할 수있는 다른 방법은 무엇입니까 (안정성 강조)?



답변

지난해 Stack Overflow에서 사용한 일반적인 버전은 다음과 같습니다.

/// <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 캐시는 여기서 챔피언처럼 작동합니다.이를 사용하면 스로틀 항목을 자동으로 정리할 수 있습니다. 그리고 트래픽이 증가함에 따라 이것이 서버에서 문제가되는 것을 보지 못했습니다.

이 방법에 대한 의견을 자유롭게 보내십시오. 스택 오버플로를 개선하면 Ewok 수정이 훨씬 빨라집니다. 🙂


답변

Microsoft에는 IIS 7.0 용 동적 IP 제한 확장-베타라는 IIS 7의 새로운 확장이 있습니다.

“IIS 7.0의 동적 IP 제한은 웹 서버 및 웹 사이트에 대한 서비스 거부 및 무차별 대입 공격으로부터 보호하는 모듈입니다. 이러한 보호는 비정상적으로 많은 수의 동시 요청을하는 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되면 요청이 다시 허용됩니다.


답변

우리는이 URL http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx 에서 빌린 기술을 사용합니다. 스로틀 링이 아니라 가난한 사람의 서비스 거부 (DOS)에 사용됩니다. 이것은 또한 캐시 기반이며 수행중인 작업과 유사 할 수 있습니다. DOS 공격을 막기 위해 제한하고 있습니까? 라우터를 사용하여 DOS를 줄일 수 있습니다. 라우터가 필요한 조절을 처리 할 수 ​​있다고 생각하십니까?


답변