禁止浏览器缓存
方法也很简单,就是输出日期小于当前日期就可以了,这样就简单的实现了ASP.NET禁止浏览器缓存的功能了。
代码如下 | 复制代码 |
System.Web.HttpContext.Current.Response.BufferOutput = false; System.Web.HttpContext.Current.Response.ExpiresAbsolute = DateTime.Now.AddDays(-1); System.Web.HttpContext.Current.Response.Cache.SetExpires(DateTime.Now.AddDays(-1)); System.Web.HttpContext.Current.Response.Expires = 0; System.Web.HttpContext.Current.Response.CacheControl = “no-cache”; System.Web.HttpContext.Current.Response.Cache.SetNoStore(); |
asp.net的浏览器缓存实现
上面我们说的是静态页面的情况,那么aspx页面,也就是动态页面会是怎么样一种情况?现在,我们创建一个动态网页来看一看。先来创建一个最简单的aspx,如下:
代码如下 | 复制代码 |
<body> <%=DateTime.Now %> </body> |
请求一下,得到的头信息如下:
然后再多次请求一下,我们发现每次都是200OK,并且我们发现头信息中丢了一个很重要的信息,那就是Last-Modified。服务器没有告诉浏览器自己的对象的最后修改日期,那么浏览器就只好每次去服务器重新获取全部数据了。看到这里,我们应该明白了,要让浏览器不去拿数据,动态程序就得想法设法自己添加这个头信息。
好的,现在我们就在ASPX的后台代码中这样来实现一个最简单的头信息添加:
代码如下 | 复制代码 |
protected void Page_Load(object sender, EventArgs e) { this.Response.AddHeader("Last-Modified", DateTime.Now.ToString("U", DateTimeFormatInfo.InvariantInfo)); } |
添加了头信息后,我们发现再次请求URL后,头信息变为如下:
可以欣喜滴看到,响应头中包含了Last-Modified,而请求头中则包含了If-Modified-Since。
当然,我们仍旧发现,每次请求还是200OK。这是当然了,既然头信息都是ASP.NET在后台添加的,那么我们要返回什么样的响应状态给服务器这段逻辑也得由自己来写。现在,我们假设我们要让浏览器缓存10秒的时长,其完整的代码应该如下:
代码如下 | 复制代码 |
protected void Page_Load(object sender, EventArgs e) { this.Response.AddHeader("Last-Modified", DateTime.Now.ToString("U", DateTimeFormatInfo.InvariantInfo)); DateTime IfModifiedSince; if (DateTime.TryParse(this.Request.Headers.Get("If-Modified-Since"), out IfModifiedSince)) { if ((DateTime.Now - IfModifiedSince.AddHours(8)).Seconds < 10) { Response.Status = "304 Not Modified"; Response.StatusCode = 304; return; } } //其它 } |
经过这次修改后,如果我们在10秒内持续请求该aspx页面,则始终返回304状态,也即浏览器不会去服务器拿正文,只会在本地去读取自己的缓存,这样一来,服务器压力自然就小了。如果我们10秒内不对服务器请求这个页面,则10秒后会返回200OK,即重新到服务器拿页面数据。
现在,用AB来模拟100并发用户进行1000次请求,得到的比较结果如下(注意,为了强化效果,我们在后台需要模拟一些比较耗时的动作,比如读取数据库):
左边是未做缓存的aspx页面,右边是做了缓存的aspx页面,可以看到,吞吐率相差10倍之多。
提示,使用ab进行压力测试的时候,需要加入If-Modified-Since的头信息,命令如下
asp.net mvc浏览器缓存和压缩的实现
cache在开发高可扩展性的web应用中起着至关重要的作用,我们可以按照预定的时间将任何get请求缓存到浏览器中,如果在预定的时间内用户请求同一URL那么response就会通过浏览器的cache来实现而非server。可以通过下面的action filter在ASP.NET MVC应用中实现同样的功能:
代码如下 | 复制代码 |
using System; using System.Web; using System.Web.Mvc;
public class CacheFilterAttribute: ActionFilterAttribute { /// <summary> /// Get or sets the cache duration in seconds . the default is 10 seconds /// </summary> /// <value> the cache duration in seconds </value>
public int Duration { get; set; } public CacheFilterAttribute() { Duration = 10; } public override void OnActionExecuted(FiterExecutedContext filterContext) { if (Duration <= 0) return;
HttpCachePolicy cache = fiterContext.HttpContext.Response.Cache; TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
cache.SetCacheability(Httpcacheablity.public); cache.SetExpires(DateTime.Now.Add(cacheDuration); cache.SetMaxAge(cacheDuration); cache.AppendCacheExtension("must revalidate, proxy-revalidate"); } } |
可以在controller action method中应用这个filter:
代码如下 | 复制代码 |
[CacheFilter(Duration = 60)] public void Category(string name, int? page) {
} |
提升web 应用性能的另外一个重要因素便是压缩,目前大多数的浏览器都接受压缩过的内容,这样就大大节省了带宽。可以通过下面的filter在ASP.NET WEB应用中压缩你的response:
代码如下 | 复制代码 |
using System.Web; using System.Web.Mvc;
public class CompressFilter : ActionFilterAttribute { public override OnActionExecuting(FilterExecutingContext filterContext) { HttpRequestBase request = filterContext.HttpContext.Request; string acceptEncoding = request.Headers("Accept-Encoding");
if (string.IsNullOrEmpty(acceptEncoding)) return;
acceptEncoding = acceptEncoding.ToUpperInvariant();
HttpResponseBase response = filterContext.HttpContext.Response;
if (acceptEncoding.Contains("GZIP")) { reponse.AppendHeader("Content-encoding","gzip"); response.Filter = new GZipStream(response.Filter,CompressionMode.Compress); } } } |
可以在Controller action method中应用这个filter:
代码如下 | 复制代码 |
[CompressFilter] public void Category(string name, int? page) {
} |
当然也可以两个filter一块儿使用:
代码如下 | 复制代码 |
[CompressFilter] [CacheFilter(Duration = 60,Order = 2)] public void Category(string name, int? page) {
} |