IIS 7 200 के बजाय 304 देता है


10

मेरे पास IIS 7 के साथ एक अजीब मुद्दा है।
कभी-कभी यह 200 के बजाय एक 304 को वापस करने के लिए लगता है।

यहां एक नमूना अनुरोध Fiddler के साथ पकड़ा गया है:
(ध्यान दें कि अनुरोध की गई फ़ाइल अभी तक मेरे ब्राउज़र कैश में स्थित नहीं है।)

GET https://[mysite]/Content/js/jquery.form.js HTTP/1.1
Accept: */*
Referer: https://[mysite]/Welcome/News
Accept-Language: sv-SE
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; .NET4.0E)
Accept-Encoding: gzip, deflate
Host: [mysite]
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: ...

ध्यान दें कि अनुरोध में कोई इफ़-मॉडिफ़ाइड-चूंकि या यदि-कोई नहीं-मैच है।
लेकिन अभी भी प्रतिक्रिया है:

HTTP/1.1 304 Not Modified
Cache-Control: public
Expires: Tue, 02 Mar 2010 06:26:08 GMT
Last-Modified: Mon, 22 Feb 2010 21:58:44 GMT
ETag: "1CAB40A337D4200"
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Mon, 01 Mar 2010 17:06:34 GMT

क्या किसी के पास इस बात का सुराग है कि यहां क्या गलत हो सकता है?

मैं Windows वेब सर्वर 2008 R2 पर IIS 7 चला रहा हूं।

संपादित करें:

मुझे वर्कअराउंड मिला है, कैशिंग सक्षम करें और फिर इसे एक एक्सटेंशन स्तर पर अक्षम करें मेरे लिए चाल चली।

<configuration>
  <system.webServer>
    <caching enabled="true" enableKernelCache="true">
      <profiles>
        <add extension=".png" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".gif" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".js" policy="DisableCache" kernelCachePolicy="DisableCache" />
        <add extension=".css" policy="DisableCache" kernelCachePolicy="DisableCache" />
      </profiles>
    </caching>
    <staticContent>
      <clientCache cacheControlMode="NoControl" />
    </staticContent>
  </system.webServer>
</configuration>

मैं एक ही समस्या है, और यह एक बहुत व्यस्त वेब सर्वर पर समस्याओं का एक बहुत कारण है। IIS 304 लौटाता है, भले ही ग्राहक के पास संसाधन की प्रतिलिपि न हो।
फिलिप लेबेर्ट

@Philippe, क्या आपने अभी तक एक समाधान पाया है? अन्यथा एक वर्कअराउंड के लिए ऊपर मेरा संपादन देखें और नीचे दिए गए नए उत्तर की जांच करें।
ओला हेरहदहल

@OlaHerrdahl, आपका समाधान सही है :) मेरे पास यह सटीक मुद्दा भी था। धन्यवाद!
आर्डी अराम

जवाबों:


3

HTTP1.1 कल्पना की धारा 14.9 के अनुसार , no-cacheकैश-कंट्रोल हेडर के लिए निर्देश केवल मूल सर्वर द्वारा असंभव है, जिसका अर्थ है कि IIS आपके अनुरोध में हेडर को अनदेखा कर रहा है।

कैश-कंट्रोल निर्देशों को इन सामान्य श्रेणियों में विभाजित किया जा सकता है:

  - Restrictions on what are cacheable; these may only be imposed

मूल सर्वर द्वारा।

धारा 14.9.1 परिभाषित करता है public, privateऔर no-cacheनिर्देशों के अनुसार जो कि उपलब्ध करने योग्य है, जो केवल सर्वर द्वारा लगाया जा सकता है।

यदि आप अपनी .js फ़ाइल को कैश नहीं करना चाहते हैं, तो आपको no-cacheनिर्देश को ऐप में सेट करना होगा (यानी- ASP.NET कोड) या आपको निर्देश Cache-Controlका उपयोग करने के अनुरोध में शीर्ष लेख को बदलना होगा no-storeके बजाय no-cache

संपादित करें:
आपकी टिप्पणी के आधार पर - हां मैंने माना कि आप फ़ाइल को कैश नहीं करना चाहते थे। 304, तब, हो सकता है कि फ़ाइल IIS के आंतरिक कैश में से किसी एक में हो। इन पर एक नजर:


मुझे लगता है कि आपने यहां मेरी समस्या को गलत समझा। फ़ाइल अभी तक मेरे कैश में स्थित नहीं है। लेकिन फिर भी सर्वर एक 304 के साथ उत्तर देता है ... ऐसा लगता है कि सभी प्रमुख ब्राउज़रों में साइट ब्राउज़ करते समय अनियमित रूप से होता है।
ओला हेरहदाल

@ ओला हेरडाहल: मेरे संपादन पर एक नज़र डालें।
स्क्विलमैन

मैंने IIS में कैशिंग को अक्षम करने का प्रयास किया है और इससे कोई फर्क नहीं पड़ता ... :(
Oerr Herrdahl

1

मैं थोड़ी देर के लिए एक ही समस्या रहा है और सभी कैशिंग बंद कर दिया है ... हालाँकि, मैंने कुछ समय पर IIS7 के लिए संपीड़न मॉड्यूल स्थापित किया था, जो डिफ़ॉल्ट रूप से मेरी मौजूदा साइटों पर स्थिर फ़ाइलों के संपीड़न को सक्षम करता था। मैंने प्रभावित स्थलों के लिए सभी संपीड़न बंद कर दिए और अब वे ठीक टच वुड का काम कर रहे हैं ।


1

हम भी इस बग का अनुभव कर रहे थे लेकिन हम एक परिसंपत्ति प्रबंधन पुस्तकालय (कैसेट) का उपयोग कर रहे थे। इस मुद्दे की व्यापक जाँच के बाद, हमने पाया है कि इस मुद्दे का मूल कारण ASP.NET, IIS और कैसेट के संयोजन से है। मुझे यकीन नहीं है कि यह आपकी समस्या है ( Headersएपीआई के बजाय एपीआई का उपयोग करके Cache), लेकिन पैटर्न समान लगता है।

बग # 1

कैसेट Vary: Accept-Encodingबंडल की अपनी प्रतिक्रिया के भाग के रूप में हेडर को सेट करता है क्योंकि यह सामग्री को gzip / deflate के साथ एन्कोड कर सकता है:

हालाँकि, ASP.NET आउटपुट कैश हमेशा उस प्रतिक्रिया को लौटाएगा जो पहले कैश की गई थी। उदाहरण के लिए, यदि पहले अनुरोध में Accept-Encoding: gzipऔर कैसेट ने gzipped सामग्री दी है, तो ASP.NET आउटपुट कैश URL को कैश कर देगा Content-Encoding: gzip। उसी URL के लिए अगला अनुरोध लेकिन एक अलग स्वीकार्य एन्कोडिंग (जैसे Accept-Encoding: deflate) के साथ कैश की गई प्रतिक्रिया लौटाएगा Content-Encoding: gzip

यह बग कैसेट HttpResponseBase.Cacheएपीआई के कारण आउटपुट कैश सेटिंग्स (जैसे Cache-Control: public) HttpResponseBase.Headersको सेट करने के लिए होता है लेकिन Vary: Accept-Encodingहेडर को सेट करने के लिए एपीआई का उपयोग करने के कारण होता है । समस्या यह है कि ASP.NET है OutputCacheModuleहै नहीं प्रतिक्रिया हेडर के बारे में पता; यह केवल Cacheएपीआई के माध्यम से काम करता है। यही है, यह उम्मीद करता है कि डेवलपर केवल मानक HTTP के बजाय एक अदृश्य रूप से कसकर युग्मित एपीआई का उपयोग करेगा।

बग # 2

IIS 7.5 (Windows Server 2008 R2) का उपयोग करते समय बग # 1 IIS कर्नेल और उपयोगकर्ता कैश के साथ एक अलग समस्या पैदा कर सकता है। उदाहरण के लिए, एक बार एक बंडल के साथ सफलतापूर्वक कैश हो जाने के बाद Content-Encoding: gzip, इसे आईआईएस कर्नेल कैश में देखना संभव है netsh http show cachestate। यह 200 स्थिति कोड और "गज़िप" की सामग्री एन्कोडिंग के साथ एक प्रतिक्रिया दिखाता है। यदि अगले अनुरोध में एक अलग स्वीकार्य एन्कोडिंग (जैसे Accept-Encoding: deflate) है और एक If-None-Matchहेडर जो बंडल के हैश से मेल खाता है, तो IIS के कर्नेल और उपयोगकर्ता मोड कैश में अनुरोध को एक मिस माना जाएगा । इस प्रकार, कैसेट द्वारा अनुरोध किए जाने का कारण बनता है जो एक 304 लौटाता है:

हालाँकि, एक बार IIS के कर्नेल और उपयोगकर्ता मोड प्रतिक्रिया की प्रक्रिया करते हैं, वे देखेंगे कि URL के लिए प्रतिक्रिया बदल गई है और कैश को अपडेट किया जाना चाहिए। यदि IIS कर्नेल कैश को netsh http show cachestateफिर से जांचा जाता है , तो कैश्ड 200 प्रतिक्रिया को 304 प्रतिक्रिया के साथ बदल दिया जाता है। बंडल के बाद के सभी अनुरोध, परवाह किए बिना Accept-Encodingऔर If-None-Matchएक 304 प्रतिक्रिया लौटाएंगे। जहां सभी उपयोगकर्ताओं क्योंकि एक यादृच्छिक अनुरोध है कि एक अप्रत्याशित था के हमारे कोर स्क्रिप्ट के लिए एक 304 परोसा गया हम इस बग के विनाशकारी प्रभाव देखा Accept-Encodingऔर If-None-Match

समस्या यह है कि IIS कर्नेल और उपयोगकर्ता मोड कैश Accept-Encodingहेडर के आधार पर भिन्न करने में सक्षम नहीं हैं । इसके प्रमाण के रूप में, Cacheनीचे दिए गए वर्कअराउंड के साथ एपीआई का उपयोग करके , आईआईएस कर्नेल और उपयोगकर्ता मोड कैश हमेशा स्किप किए गए लगते हैं (केवल ASP.NET आउटपुट कैश का उपयोग किया जाता है)। netsh http show cachestateनीचे दिए गए वर्कअराउंड के साथ खाली होने की जाँच करके इसकी पुष्टि की जा सकती है। ASP.NET IIS कार्यकर्ता के साथ सीधे आईआईएस कर्नेल और उपयोगकर्ता मोड कैश प्रति-अनुरोध को सक्षम या अक्षम करने के लिए संचार करता है।

हम इस बग को IIS के नए संस्करणों (जैसे IIS एक्सप्रेस 10) पर पुन: पेश करने में सक्षम नहीं थे। हालांकि, बग # 1 अभी भी प्रतिलिपि प्रस्तुत करने योग्य था।

इस बग के लिए हमारा मूल निर्धारण IIS के कर्नेल / उपयोगकर्ता मोड को निष्क्रिय करना था, जो उल्लेख किए गए अन्य लोगों की तरह केवल कैसेट अनुरोधों के लिए कैशिंग था। ऐसा करने पर, हमने अपने वेब सर्वर के सामने कैशिंग की एक अतिरिक्त परत को तैनात करते समय बग # 1 का खुलासा किया। कारण यह है कि क्वेरी स्ट्रिंग हैक ने काम किया है क्योंकि एपीआई के आधार पर भिन्नता के लिए अगर अनुरोध का उपयोग नहीं किया गया है और यदि अनुरोध है OutputCacheModuleतो कैश मिस रिकॉर्ड करेगाCacheQueryString QueryString

वैकल्पिक हल

हम कैसेट वैसे भी दूर जाने की योजना बना रहे हैं, इसलिए कैसेट के अपने स्वयं के कांटे को बनाए रखने के बजाय (या एक पीआर विलय प्राप्त करने की कोशिश कर रहे हैं), हमने इस मुद्दे के आसपास काम करने के लिए एक HTTP मॉड्यूल का उपयोग करने का विकल्प चुना।

public class FixCassetteContentEncodingOutputCacheBugModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PostRequestHandlerExecute += Context_PostRequestHandlerExecute;
    }

    private void Context_PostRequestHandlerExecute(object sender, EventArgs e)
    {
        var httpContext = HttpContext.Current;

        if (httpContext == null)
        {
            return;
        }

        var request = httpContext.Request;
        var response = httpContext.Response;

        if (request.HttpMethod != "GET")
        {
            return;
        }

        var path = request.Path;

        if (!path.StartsWith("/cassette.axd", StringComparison.InvariantCultureIgnoreCase))
        {
            return;
        }

        if (response.Headers["Vary"] == "Accept-Encoding")
        {
            httpContext.Response.Cache.VaryByHeaders.SetHeaders(new[] { "Accept-Encoding" });
        }
    }

    public void Dispose()
    {

    }
}

मुझे आशा है कि यह किसी को मदद करता है 😄!

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