2013-02-11 23 views
12

Tôi muốn có một số trang nhất định có bộ nhớ Cache 10 phút cho khách hàng và 24 giờ cho máy chủ. Lý do là nếu trang thay đổi, khách hàng sẽ tìm nạp phiên bản cập nhật trong vòng 10 phút, nhưng nếu không có gì thay đổi thì máy chủ sẽ chỉ phải xây dựng lại trang một lần mỗi ngày.Cách đặt thời gian hết hạn Cache cho Máy khách và Máy chủ lưu trữ

Vấn đề là cài đặt bộ đệm đầu ra dường như ghi đè cài đặt ứng dụng khách. Dưới đây là những gì tôi đã thiết lập:

Tuỳ chỉnh ActionFilterAttribute Lớp

public class ClientCacheAttribute : ActionFilterAttribute 
{ 
    private bool _noClientCache; 

    public int ExpireMinutes { get; set; } 

    public ClientCacheAttribute(bool noClientCache) 
    { 
     _noClientCache = noClientCache; 
    } 

    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     if (_noClientCache || ExpireMinutes <= 0) 
     { 
      filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1)); 
      filterContext.HttpContext.Response.Cache.SetValidUntilExpires(false); 
      filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 
      filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
      filterContext.HttpContext.Response.Cache.SetNoStore(); 
     } 
     else 
     { 
      filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(ExpireMinutes)); 
     } 

     base.OnResultExecuting(filterContext); 
    } 
} 

Web Config cài đặt

<outputCacheSettings> 
    <outputCacheProfiles> 
     <add name="Cache24Hours" location="Server" duration="86400" varyByParam="none" /> 
    </outputCacheProfiles> 
    </outputCacheSettings> 

Làm thế nào tôi gọi đó là:

[OutputCache(CacheProfile = "Cache24Hours")] 
[ClientCacheAttribute(false, ExpireMinutes = 10)] 
public class HomeController : Controller 
{ 
    [...] 
} 

Nhưng loo vua tại Tiêu đề HTTP hiển thị:

HTTP/1.1 200 OK 
Cache-Control: no-cache 
Pragma: no-cache 
Content-Type: text/html; charset=utf-8 
Expires: -1 

Làm cách nào để triển khai đúng cách? Nó là một ứng dụng ASP.NET MVC 4.

+0

Tôi không quen thuộc với cú pháp này để lưu vào bộ nhớ cache. Tôi sử dụng thời lượng. Đã thành công với nó. Điều đó không giúp gỡ lỗi của bạn, nhưng đề xuất thay thế –

Trả lời

4

Trong hồ sơ OutputCache của bạn, hãy đặt vị trí thành ServerAndClient. Bộ lọc hành động của bạn phải ghi đè lên đầu ra một cách chính xác khi bạn thực hiện việc này.

+0

Làm như vậy sẽ thêm giá trị độ tuổi tối đa vào Tiêu đề, nhưng cũng đặt Hết hạn: HTTP/1.1 200 OK Bộ nhớ cache-Điều khiển: riêng tư, max-age = 86400 Loại nội dung: văn bản/html; charset = utf-8 Hết hạn: Thứ Ba, ngày 12 tháng 2 năm 2013 13:33:41 GMT – Josh

+0

Tôi không chắc chắn 100% kết quả cuối cùng của bạn, nhưng tôi nghĩ nếu bạn thêm một cuộc gọi vào Response.Cache.SetMaxAge trong bộ lọc hành động của bạn, CC: max-age và Expires sẽ khớp với nhau và bạn sẽ tốt để đi. – pauln

+0

Tôi đã thử thiết lập Response.Cache.SetMaxAge và nó đã bị ghi đè bởi Output Cached khi ở chế độ ServerAndClient. Và chỉ cần bỏ qua khi chỉ ở chế độ Lọc. Mục tiêu của tôi là đặt Cache-Control thành "công khai, max-age = 10" và hết hạn 10 phút kể từ bây giờ (GMT). Cache-Control được điều khiển bởi Output Cache và dường như tôi không thể ghi đè lên nó. – Josh

8

Bạn cần triển khai giải pháp của riêng bạn cho bộ nhớ đệm phía máy chủ và cho bộ nhớ đệm phía máy khách hoặc sử dụng ClientCacheAttribute hoặc OutputCache. Đây là lý do tại sao bạn sẽ yêu cầu giải pháp tùy chỉnh của bạn cho bộ đệm ẩn phía máy chủ.

  • ClientCacheAttribute chính sách bộ nhớ cache bộ để Response.Cache đó là loại HttpCachePolicyBase
  • và built-in OutputCache cũng đặt chính sách bộ nhớ cache để Response.Cache

Ở đây những gì tôi cố gắng làm nổi bật là we don't have collection of HttpCachePolicyBase but we only have one object of HttpCachePolicyBase so we can't set multiple cache policy for given response.

Thậm chí nếu chúng tôi có thể đặt Http Cacheability thành HttpCacheability.ServerAndPrivate nhưng agai n bạn sẽ chạy trong vấn đề khác với thời lượng bộ nhớ cache (tức là cho máy khách 10 phút & máy chủ 24 giờ)

Điều tôi đề nghị là sử dụng OutputCache để lưu vào bộ đệm phía máy khách và thực hiện bộ đệm ẩn của máy chủ.

+0

Tôi đã cố gắng tránh điều đó, dễ dàng hơn để tạo ra một phía máy khách tùy chỉnh (về cơ bản quản lý các tiêu đề http), sau đó tạo một giải pháp phía máy chủ tùy chỉnh vì bạn phải quản lý các bản sao trang trong bộ nhớ cache. Thật không may khi tôi đã cố gắng có OutputCache quản lý chỉ bộ đệm máy chủ, nó ghi đè lên tiêu đề http mà tôi đã đặt thủ công cho khách hàng. Bạn có biết cách ghi đè lên tiêu đề http mà Bộ đệm đầu ra đặt khi ở chế độ Máy chủ không? – Josh

+0

Josh nó có khả năng xảy ra & nó là rõ ràng quá vì kết quả hợp lý được lưu trữ sau khi kết quả thực hiện trong khi trong hầu hết trường hợp chúng tôi quản lý tiêu đề từ phương pháp hành động hoặc trước khi kết quả thực hiện –

+0

và đó là lý do tại sao tôi đề nghị sử dụng OutputCache cho phía khách hàng. tiêu đề không được khuyến khích thay vì sử dụng Chính sách bộ nhớ cache cho bộ nhớ cache của khách hàng. –

3

Theo Net 4.5, nó IS có thể có những chính sách khách hàng và máy chủ bộ nhớ đệm khác nhau mà không cần viết các nhà cung cấp bộ nhớ cache tùy chỉnh:

// Set the cache response expiration to 3600 seconds (use your own value here). 
HttpContext.Current.Response.Cache.SetExpires(DateTime.UtcNow.AddSeconds(3600)); 

// Set both server and browser caching. 
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.ServerAndPrivate); 

// Prevent browser's default max-age=0 header on first request 
// from invalidating the server cache on each request. 
HttpContext.Current.Response.Cache.SetValidUntilExpires(true); 

// Set an HTTP ETag header on the page using a random GUID. 
HttpContext.Current.Response.Cache.SetETag(System.Guid.NewGuid() 
              .ToString().Replace("-", "")); 

// Set last modified time. 
HttpContext.Current.Response.Cache.SetLastModified(DateTime.UtcNow); 

// Now here is the critical piece that forces revalidation on each request!: 
HttpContext.Current.Response.Cache.AppendCacheExtension(
    "must-revalidate, proxy-revalidate, max-age=0"); 

Kết quả là mỗi khi trang web được tái sinh trong bộ nhớ cache server, nó được một ETag mới. Điều này làm cho yêu cầu If-None-Match trả lại toàn bộ trang trở lại trình duyệt. Nếu bản sao được lưu trong bộ nhớ cache của trình duyệt giống với những gì được tạo trong bộ nhớ cache của máy chủ (cùng một ETag), trình duyệt sẽ trả lại 304 Không được sửa đổi.

Lưu ý rằng không có tiêu đề bộ nhớ cache nào được thêm vào trong cuộc xung đột AppendCacheExtension với tiêu đề được phát ra bởi bộ nhớ đệm gốc. Bất cứ khi nào bạn cố gắng sửa đổi các tiêu đề bộ nhớ đệm được phát ra bởi .Net caching, Net sẽ luôn thay thế cho những gì bạn đang cố gắng thực hiện. Bí quyết là thêm các tiêu đề không xung đột mới, không cố gắng thay đổi những gì .Net đã được phát ra. Quan trọng nhất, bạn phải nối thêm tiêu đề tối đa. Bạn không được sử dụng .SetMaxAge(), vì điều này cũng đặt độ tuổi tối đa của bản sao được lưu trong bộ nhớ cache của trang.

Việc này tốn khá nhiều công sức để tìm ra, nhưng nó hoạt động, ít nhất là trong .Net 4.5.

+0

Đây không phải là kỹ thuật thiết lập một thời gian bộ nhớ cache phía khách hàng khác nhau, dòng cuối cùng tôi tin là không khác nhau từ thiết lập HttpContext.Current.Response.Cache.SetRevalidation (HttpCacheRevalidation.AllCaches); Tôi upvoted câu trả lời bởi vì nó là tốt hơn để sử dụng workaround này hơn để reimplement phía máy chủ bộ nhớ đệm. Các chi phí trong khách hàng revalidating bộ nhớ cache đối với máy chủ là tối thiểu vì vậy tôi nghĩ rằng đây là một câu trả lời tuyệt vời. – madamission