IIS에서 브라우저 캐싱 활용(구글 페이지 속도 문제)
브라우저 캐싱 활용에 대한 몇 가지 질문이 있지만 ASP에서 이를 수행하는 방법에 유용한 것을 찾지 못했습니다.NET 적용.구글의 페이지 속도는 이것이 성능의 가장 큰 문제라고 말합니다.지금까지 web.config에서 이 작업을 수행했습니다.
<system.webServer>
<staticContent>
<!--<clientCache cacheControlMode="UseExpires"
httpExpires="Fri, 24 Jan 2014 03:14:07 GMT" /> -->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.24:00:00" />
</staticContent>
</system.webServer>
주석 코드가 작동합니다.만료 헤더를 미래의 특정 시간으로 설정할 수 있지만 설정할 수 없습니다.cacheControlMaxAge
지금부터 정적 컨텐츠를 캐시할 날짜를 설정합니다.작동하지 않습니다.제 질문은 다음과 같습니다.
내가 어떻게 그럴 수 있을까?특정 폴더에 대해서만 캐싱을 설정하는 것이 가능하다는 것을 알고 있는데, 해결책도 되지 않습니다.응용 프로그램은 윈도우즈 Server 2012에서 호스팅되며, IIS8에서는 응용 프로그램 풀이 클래식으로 설정됩니다.
웹 구성에서 이 코드를 설정한 후 페이지 속도가 72(이전에는 71)가 되었습니다.50개의 파일이 캐시되지 않았습니다.(지금은 49) 왜 그런지 궁금했는데 한 파일이 실제로 캐시되어 있다는 것을 이제야 깨달았습니다(svg 파일).유감스럽게도 png와 jpg 파일은 그렇지 않았습니다.이것은 나의 web.config 입니다.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="exceptionManagement" type="Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionManagerSectionHandler,Microsoft.ApplicationBlocks.ExceptionManagement" />
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E34" requirePermission="false" allowDefinition="Everywhere" />
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
</configSections>
<exceptionManagement mode="off">
<publisher mode="off" assembly="Exception" type="blabla.ExceptionHandler.ExceptionDBPublisher" connString="server=188......;database=blabla;uid=blabla;pwd=blabla; " />
</exceptionManagement>
<location path="." inheritInChildApplications="false">
<system.web>
<httpHandlers>
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler,System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e34" validate="false" />
<add verb="GET" path="Image.ashx" type="blabla.WebComponents.ImageHandler, blabla/>"
<add verb="*" path="*.aspx" type="System.Web.UI.PageHandlerFactory" />
<add verb="*" path="*.jpg" type="System.Web.StaticFileHandler" />
<add verb="GET" path="*.js" type="System.Web.StaticFileHandler" />
<add verb="*" path="*.gif" type="System.Web.StaticFileHandler" />
<add verb="GET" path="*.css" type="System.Web.StaticFileHandler" />
</httpHandlers>
<compilation defaultLanguage="c#" targetFramework="4.5.1" />
<trace enabled="false" requestLimit="100" pageOutput="true" traceMode="SortByTime" localOnly="true"/>
<authentication mode="Forms">
<forms loginUrl="~/user/login.aspx">
<credentials passwordFormat="Clear">
<user name="blabla" password="blabla" />
</credentials>
</forms>
</authentication>
<authorization>
<allow users="*" />
</authorization>
<sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes" cookieless="false" timeout="20" />
<globalization requestEncoding="utf-8" responseEncoding="utf-8" culture="en-GB" uiCulture="en-GB" />
<xhtmlConformance mode="Transitional" />
<pages controlRenderingCompatibilityVersion="4.5" clientIDMode="AutoID">
<namespaces>
</namespaces>
<controls>
<add assembly="Microsoft.AspNet.Web.Optimization.WebForms" namespace="Microsoft.AspNet.Web.Optimization.WebForms" tagPrefix="webopt" />
</controls>
</pages>
<webServices>
<protocols>
<add name="HttpGet" />
<add name="HttpPost" />
</protocols>
</webServices>
</system.web>
</location>
<appSettings>
</appSettings>
<connectionStrings>
</connectionStrings>
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization maxJsonLength="200000" />
</webServices>
</scripting>
</system.web.extensions>
<startup>
<supportedRuntime version="v2.0.50727" />
<supportedRuntime version="v1.1.4122" />
<supportedRuntime version="v1.0.3705" />
</startup>
<system.webServer>
<rewrite>
<providers>
<provider name="ReplacingProvider" type="ReplacingProvider, ReplacingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5ab632b1f332b247">
<settings>
<add key="OldChar" value="_" />
<add key="NewChar" value="-" />
</settings>
</provider>
<provider name="FileMap" type="DbProvider, Microsoft.Web.Iis.Rewrite.Providers, Version=7.1.761.0, Culture=neutral, PublicKeyToken=0525b0627da60a5e">
<settings>
<add key="ConnectionString" value="server=;database=blabla;uid=blabla;pwd=blabla;App=blabla"/>
<add key="StoredProcedure" value="Search.GetRewriteUrl"/>
<add key="CacheMinutesInterval" value="0"/>
</settings>
</provider>
</providers>
<rewriteMaps configSource="rewritemaps.config" />
<rules configSource="rewriterules.config" />
</rewrite>
<modules>
<remove name="ScriptModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3456AD264E35" />
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
<handlers>
<add name="Web-JPG" path="*.jpg" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="Web-CSS" path="*.css" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="Web-GIF" path="*.gif" verb="GET,HEAD,POST" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="Web-JS" path="*.js" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
</handlers>
<validation validateIntegratedModeConfiguration="false" />
<httpErrors errorMode="DetailedLocalOnly" existingResponse="Auto">
<remove statusCode="404" subStatusCode="-1"/>
<remove statusCode="500" subStatusCode="-1"/>
<error statusCode="404" path="error404.htm" responseMode="File"/>
<error statusCode="500" path="error.htm" responseMode="File"/>
</httpErrors>
</system.webServer>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="soapBinding_AdriagateService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" messageEncoding="Text">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</basicHttpBinding>
<netTcpBinding>
<binding name="NetTcpBinding_ITravellerService" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="blabla" bindingConfiguration="soapBinding_blabla" contract="" Address="blabla" name="blabla" />
<endpoint address="blabla" binding="basicHttpBinding" bindingConfiguration="soapBinding_IImagesService"
contract="ImagesService.IImagesService" name="soapBinding_IImagesService"/>
<identity>
<servicePrincipalName value="blabla"/>
</identity>
</endpoint>
</client>
</system.serviceModel>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
</system.web>
<elmah>
<security allowRemoteAccess="false" />
</elmah>
<location path="elmah.axd" inheritInChildApplications="false">
<system.web>
<httpHandlers>
<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="ELMAH" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
</handlers>
</system.webServer>
</location>
</configuration>
편집: 정확한 만료 날짜를 설정하면 캐싱이 작동하지만 jpg,gif....에 대해서는 작동하지 않습니다. png에 대해서만.
EDIT2: 설정한 경우cacheControlCustom="public"
여기와 같이:
<clientCache cacheControlCustom="public"
cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
캐싱은 작동하지만 여전히 jpegs와 gif에는 작동하지 않습니다. svgs와 pngs에만 작동합니다.
대부분의 브라우저 캐싱 문제는 응답 헤더를 보고 해결할 수 있습니다(Google chrome developer 도구에서 수행 가능).
는.clientCache
당신의web.config
에서 볼 수 .max-age
86400
초 단위로 1일입니다.
다음은 이 설정에 대한 web.config 스니펫입니다.
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
에는 요, 이 .max-age
Cache-Control
머리말따라서 브라우저는 콘텐츠를 캐싱해야 합니다.이것은 대부분 사실이지만 일부 브라우저에서는 다른 플래그를 설정해야 합니다.구체적으로.public
캐시 제어 헤더에 대해 설정된 플래그입니다.이를 사용하여 쉽게 추가할 수 있습니다.cacheControlCustom
의에 합니다.web.config
예가 . 여기 예가 있습니다.
<clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
이제 페이지를 재시도하고 헤더를 검사할 때입니다.
에서 볼 수 Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δpublic, max-age=86400
우리 데 것을 . 그래서 우리 브라우저는 리소스를 캐싱하는 데 필요한 모든 것을 가지고 있습니다.이제 구글 크롬의 헤더와 네트워크 탭을 조사하는 것이 도움이 될 것입니다.
파일에 대한 첫번째 요청입니다.파일이 캐시되지 않았습니다...
이제 이 페이지로 다시 이동합니다(참고: 페이지를 새로 고치지 마십시오. 잠시 후에 이에 대해 설명하겠습니다).지금 캐시에서 응답이 반환됩니다(원으로 표시됨).
이제 브라우저 새로 고침 기능을 사용하거나 둘 중 하나를 사용하여 페이지를 새로 고치면 어떻게 됩니까?잠깐만..어디서(from cache)
가세요.
구글 크롬에서는 새로 고침 버튼을 사용하면 캐시 헤더에 관계없이 정적 리소스가 다시 다운로드됩니다(여기에 설명을 삽입하십시오).즉, 리소스가 다시 검색되고 최대 헤더가 전송되었음을 의미합니다.
이제 위의 모든 설명을 마치고 캐시 헤더를 어떻게 모니터링하고 있는지 테스트해 보십시오.
갱신하다
핸들러 handler)가 말씀하셨습니다. (IHttpHandler
)의 이름을 붙였습니다Image.ashx
내용 유형은 다음과 같습니다.image/jpg
은 이입니다. 기본 동작은 이 핸들러를 캐시하는 것입니다. "IIS"가 됩니다..ashx
코드 자체에 캐시 헤더를 명시적으로 설정하지 않고는 캐싱 대상이 되지 않으며, 동적 스크립트로 사용됩니다.
일반적으로 여기서 주의를 기울여야 합니다.IHttpHandlers
일반적으로 동적 컨텐츠를 제공하기 때문에 캐시되지 않아야 합니다.내용이 변경되지 않을 경우에는 캐시 헤더를 코드에 직접 설정할 수 있습니다.시정는과다의다sne에서 캐시 헤더를 설정하는 예입니다.IHttpHandlers
을 Response
맥락.
context.Response.ContentType = "image/jpg";
context.Response.Cache.SetMaxAge(TimeSpan.FromDays(1));
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetSlidingExpiration(true);
context.Response.TransmitFile(context.Server.MapPath("~/out.jpg"));
를 는 을 하고 에 몇 가지 을 설정하고 .Cache
◦ 을 얻기 했습니다.원하는 응답을 얻기 위해 속성을 설정했습니다.
context.Response.Cache.SetMaxAge(TimeSpan.FromDays(1));
력에을록다e을 설정하도록 지시합니다.max-age=
의Cache-Control
머리말이 될1
미래의 하루(86400초).context.Response.Cache.SetCacheability(HttpCacheability.Public);
력에을록다e을 설정하도록 지시합니다.Cache-Control
o로 머리글을 .public
합니다. 이는 브라우저에 개체를 캐시하도록 지시하기 때문에 매우 중요합니다.context.Response.Cache.SetSlidingExpiration(true);
력에을고지다다etegose에e을력tsmax-age=
의Cache-Control
머리말을 제대로 합니다.슬라이딩 만료를 설정하지 않으면 IIS 출력 캐싱이 maxage 헤더를 무시합니다.이것을 종합해보면 이런 결과가 나옵니다.
위에서 말한 것처럼 당신은 캐시를 원하지 않을 수도 있습니다..ashx
일반적으로 동적 컨텐츠를 제공하는 파일입니다. 해당 이 특정 나당가정간에지을다수을할여을의우적다r수할r을나esroteescnu당nftadyne적to.ashx
파일.파일.
이제 위에 나열된 프로세스와 함께 사용자 정의 문자열로 전달되는 내용을 브라우저가 확인할 수 있도록 캐시 헤더의 ETag(wiki 참조) 구성 요소도 설정할 수 있습니다.위키에는 다음과 같이 명시되어 있습니다.
웹 의 특정 입니다. 그 되면, ETag의 URL이 변경됩니다. 만약 그 URL의 리소스 내용이 변경된다면, 새로운 것과 다른 것입니다.
ETag
가 할당됩니다.
이는 브라우저가 응답에서 제공되는 내용을 식별하기 위한 일종의 고유한 식별 정보입니다. 시 이를전시가를해다음 aar다를해dya가이를enrresl면gIf-None-Match
머리글에 다음과 같이 붙입니다.ETag
마지막 회답에서우리는 우리의 핸들러를 수정하여 그들을 감지할 수 있습니다.If-None-Match
와한과다가r과t한rdo와가와 비교합니다.Etag
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .ETags
그러나 경험칙은 하나의 개체만을 정의할 가능성이 높은 식별자를 제공하는 것입니다.이 경우 다음과 같이 연결된 두 문자열을 사용하는 것이 경우
System.IO.FileInfo file = new System.IO.FileInfo(context.Server.MapPath("~/saveNew.png"));
string eTag = file.Name.GetHashCode().ToString() + file.LastWriteTimeUtc.Ticks.GetHashCode().ToString();
위의 토막글에서는 파일 시스템에서 파일을 로드하고 있습니다(어디서나 얻을 수 있습니다).저는 그럼 사용하고 있습니다.GetHashCode()
메서드(모든 개체에 대해)를 지정하여 개체의 정수 해시 코드를 가져옵니다.예제에서 파일 이름의 해시, 마지막 쓰기 날짜를 연결합니다.마지막 쓰기 날짜의 이유는 파일이 변경된 경우 해시 코드도 변경되어 지문이 달라지기 때문입니다.
그러면 다음과 같은 해시 코드가 생성됩니다.306894467-210133036
.
그럼 핸들러에서 이걸 어떻게 사용하죠?아래는 핸들러의 새롭게 수정된 버전입니다.
System.IO.FileInfo file = new System.IO.FileInfo(context.Server.MapPath("~/out.png"));
string eTag = file.Name.GetHashCode().ToString() + file.LastWriteTimeUtc.Ticks.GetHashCode().ToString();
var browserETag = context.Request.Headers["If-None-Match"];
context.Response.ClearHeaders();
if(browserETag == eTag)
{
context.Response.Status = "304 Not Modified";
context.Response.End();
return;
}
context.Response.ContentType = "image/jpg";
context.Response.Cache.SetMaxAge(TimeSpan.FromDays(1));
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Cache.SetSlidingExpiration(true);
context.Response.Cache.SetETag(eTag);
context.Response.TransmitFile(file.FullName);
보시다시피 핸들러를 꽤 많이 바꿨지만 우리가 생성하는 것을 알게 될 것입니다.Etag
시,신인rn신,If-None-Match
∙ 를 반환하여 내용이 변경되지 않았음을 브라우저에 알립니다.304 Not Modified
.
다음은 우리가 추가하는 것을 제외하고는 같은 핸들러였습니다.ETag
헤더 호출:
context.Response.Cache.SetETag(eTag);
이것을 브라우저에서 실행하면 얻을 수 있습니다.
(파일 이름을 변경한 것과 같이) 이미지를 보면 캐시 시스템의 모든 구성 요소가 자리 잡았음을 알 수 있을 것입니다.ETag
헤더고서청를다고며다e고g를s로청고서며estgdrs .If-None-Match
변경된 캐시 파일에 따라 저희 핸들러가 대응할 수 있도록 합니다.
이거 써요.이건 저한테 효과가 있어요.
<staticContent>
<clientCache cacheControlMode="UseExpires" httpExpires="Tue,19 Jan 2038 03:14:07 GMT"/>
</staticContent>
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="10.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
위 내용을 이용하면 브라우저에서 10일간 정적 내용 파일이 캐시됩니다.한한보e에 대한 상세 정보<clientCache>
요소는 여기서 찾을 수 있습니다.
사용할 수도 있습니다.<location>
특정 파일의 캐시 설정을 정의하는 요소:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<location path="path/to/file">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="10.00:00:00" />
</staticContent>
</system.webServer>
</location>
</configuration>
언급URL : https://stackoverflow.com/questions/21074198/leverage-browser-caching-in-iis-google-pagespeed-issue
'programing' 카테고리의 다른 글
워드프레스 쇼트코드가 작동하지 않음 (0) | 2023.09.11 |
---|---|
MySQLDB 패키지 설치 방법은?(가져오기 오류: setuptools라는 모듈이 없습니다.) (0) | 2023.09.11 |
목록 보기를 축소하지 않고 스크롤 보기에 넣을 수 있는 방법은 무엇입니까? (0) | 2023.09.11 |
Node.js에서 S3 getObject의 응답을 얻는 방법은? (0) | 2023.09.11 |
formGroup은 FormGroup 인스턴스를 필요로 합니다. (0) | 2023.09.11 |