ASP.NET MVC में थ्रॉटलिंग के अनुरोध को लागू करने का सबसे अच्छा तरीका?


212

हम एक निश्चित समय अवधि में उपयोगकर्ता के कार्यों को विफल करने के विभिन्न तरीकों के साथ प्रयोग कर रहे हैं :

  • प्रश्न / उत्तर पोस्ट को सीमित करें
  • सीमा संपादित करें
  • फ़ीड पुनर्प्राप्ति को सीमित करें

कुछ समय के लिए, हम Cache का उपयोग केवल उपयोगकर्ता गतिविधि का रिकॉर्ड सम्मिलित करने के लिए कर रहे हैं - यदि वह रिकॉर्ड मौजूद है / यदि उपयोगकर्ता एक ही गतिविधि करता है, तो हम थ्रॉटल करते हैं।

कैश का उपयोग करने से स्वचालित रूप से हमें उपयोगकर्ताओं की बासी डेटा सफाई और स्लाइडिंग गतिविधि विंडो मिल जाती है, लेकिन यह कैसे पैमाना होगा यह एक समस्या हो सकती है।

यह सुनिश्चित करने के कुछ अन्य तरीके हैं कि अनुरोधों / उपयोगकर्ता कार्यों को प्रभावी ढंग से थ्रॉटल किया जा सकता है (स्थिरता पर जोर)?


क्या आप प्रति उपयोगकर्ता या प्रति प्रश्न सीमित करने की कोशिश कर रहे हैं? यदि प्रति उपयोगकर्ता, सत्र का उपयोग कर सकता है, जो एक छोटा सेट होगा।
ग्रेग ओगल

1
यह प्रति उपयोगकर्ता है, लेकिन हम सत्र का उपयोग नहीं कर सकते, क्योंकि इसके लिए कुकीज़ की आवश्यकता होती है - हम वर्तमान में आईपी पते के आधार पर सीमित कर रहे हैं।
जारोड डिक्सन

1
आजकल, nuget संकुल पर विचार github.com/stefanprodan/MvcThrottle MVC पृष्ठों और के लिए github.com/stefanprodan/WebApiThrottle वेब API अनुरोध के लिए
एंडी

जवाबों:


240

यहां पिछले एक वर्ष के लिए स्टैक ओवरफ्लो पर हम जो उपयोग कर रहे हैं उसका एक सामान्य संस्करण है:

/// <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 कैश यहाँ एक विजेता की तरह काम करता है - इसका उपयोग करके, आप अपने थ्रॉटल प्रविष्टियों का स्वत: क्लीन-अप प्राप्त करते हैं। और हमारे बढ़ते ट्रैफ़िक के साथ, हम यह नहीं देख रहे हैं कि यह सर्वर पर एक समस्या है।

इस पद्धति पर प्रतिक्रिया देने के लिए स्वतंत्र महसूस करें; जब हम स्टैक ओवरफ्लो को बेहतर बनाते हैं, तो आप अपना इवोक फिक्स और भी तेज कर लेते हैं :)


5
त्वरित प्रश्न - आप कुंजी के भाग के रूप में c.ttpContext.Request.UserHostAddress मान का उपयोग कर रहे हैं। क्या वह मूल्य संभव है खाली या अशक्त या सभी समान मूल्य? (यानी, अगर आप एक लोड बैलेंसर का उपयोग कर रहे हैं और यह उस मशीन का आईपी है .. असली क्लाइंट नहीं) तो, प्रॉक्सी का या लोड बैलेंसर करें (यानी एक BIG IP F5) उसी डेटा को वहां रखें और आपको चेक करना होगा एक्स फॉरवर्डेड के लिए भी या कुछ और के लिए?
शुद्ध। क्रोम

7
@ Pure.Krome - हां, यह हो सकता है। क्लाइंट IP प्राप्त करते समय, हम एक सहायक फ़ंक्शन का उपयोग करते हैं जो दोनों REMOTE_ADDRऔर HTTP_X_FORWARDED_FORसर्वर चर की जांच करता है और उचित रूप से साफ करता है।
जारोड डिक्सन

3
@BrettRobi, मुझे पूरा यकीन है कि उनके पास उपयोगकर्ताओं के आईपी पते के आधार पर सर्वर आत्मीयता है। तो वे संभवतः अभी भी एक ही सर्वर मार रहे होंगे।
mmcdole

4
आप में से जो लोग देखभाल करते हैं और इस टिप्पणी अनुभाग में दूर तक पढ़ चुके हैं ... हमने अपने स्वयं के रीडायरेक्ट को समाप्त करना समाप्त कर दिया है जो कि पुनर्निर्देशन से पहले थ्रॉटल कैश कुंजी को साफ़ करते हैं। इस तरह सभी पुनर्निर्देश कुंजी को हटाने के लिए कोड से गुजरते हैं और उनमें से कोई भी थ्रॉटल विशेषता को ट्रिगर नहीं करता है।
SLoret

4
यदि आप इसका वेब एपीआई संस्करण देख रहे हैं, तो यहां देखें: stackoverflow.com/questions/20817300/…
पापा बरगंडी

68

Microsoft में IIS 7 के लिए एक नया एक्सटेंशन है जिसे IIS 7.0 के लिए डायनामिक आईपी प्रतिबंध एक्सटेंशन कहा जाता है - बीटा।

"IIS 7.0 के लिए डायनामिक आईपी प्रतिबंध एक ऐसा मॉड्यूल है जो वेब और वेब साइटों पर सेवा से इनकार करने के लिए सुरक्षा और क्रूर बल के हमलों से सुरक्षा प्रदान करता है। ऐसी सुरक्षा HTTP क्लाइंट के आईपी पते को अस्थायी रूप से अवरुद्ध करके प्रदान की जाती है जो समवर्ती अनुरोधों की असामान्य रूप से उच्च संख्या बनाते हैं। या जो छोटी अवधि में बड़ी संख्या में अनुरोध करते हैं। " http://learn.iis.net/page.aspx/548/using-dynamic-ip-restrictions/

उदाहरण:

यदि आप मानदंड निर्धारित करने के बाद X requests in Y millisecondsया X concurrent connections in Y millisecondsआईपी ​​पते को अवरुद्ध कर देंगे, Y millisecondsतो अनुरोधों को फिर से अनुमति दी जाएगी।


1
क्या आप जानते हैं कि अगर यह Googlebot जैसे क्रॉलर के साथ कोई समस्या पैदा करता है?
हेलेहट


1
अब इसे जारी किया गया है और आईआईएस के साथ बंडल किया गया है संस्करण 8 के रूप में - iis.net/learn/get-started/whats-new-in-iis-8/…
मैथ्यू स्टीवंस

मैं इसका उपयोग करना पसंद करूंगा, लेकिन यह आपको थ्रॉटल करने की अनुमति नहीं देता है <location>। यह एप्लिकेशन या कोई नहीं के लिए हर अनुरोध है।
कासे स्पीकमैन

यदि आपके वेब सर्वर एक लोड बैलेंसर के पीछे हैं, तो यह उपयोगी नहीं लगता, क्योंकि सभी ट्रैफ़िक एक ही आईपी पते से प्रतीत होंगे। जब तक मैं कुछ स्पष्ट याद कर रहा हूँ ...
Dscoduc

11

हम इस URL से उधार ली गई तकनीक का उपयोग करते हैं http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx , थ्रॉटलिंग के लिए नहीं, बल्कि एक गरीब आदमी की सेवा से इनकार (DOS) के लिए। यह भी कैश-आधारित है, और जैसा आप कर रहे हैं वैसा ही हो सकता है। क्या आप डॉस के हमलों को रोकने के लिए थ्रॉटलिंग कर रहे हैं? राउटर निश्चित रूप से डॉस को कम करने के लिए इस्तेमाल किया जा सकता है; क्या आपको लगता है कि एक राउटर को आपके लिए आवश्यक थ्रॉटलिंग को संभाल सकता है?


1
यही कारण है कि काफी क्या हम पहले से ही कर रहे हैं - लेकिन यह महान काम कर रहा है :)
जारोड डिक्सन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.