ASP.NET 缓存与 GZIP 页面性能优化教程
提升经典 ASP.NET 页面性能可同时做两件事:用输出缓存减少重复的页面生成和数据访问,用 IIS GZIP 动态压缩减小 HTML、CSS、JavaScript、JSON 等文本响应的传输体积。缓存解决服务器重复工作,GZIP 解决网络传输,两者不能互相替代,也都应当按内容变体和敏感性设定边界。
开始前先划清范围
本文贯穿场景是一个由 IIS 托管的 ASP.NET 产品列表页:
- URL 参数
categoryId会改变页面内容; - 同一分类内容 60 秒内可以复用;
- 页面不包含登录用户私有数据;
- 输出为 HTML,适合压缩。
如果页面包含账户余额、用户姓名、CSRF token 或按用户变化的权限结果,不能直接使用公共输出缓存配置。
第一步:给 Web Forms 页面加输出缓存
在 .aspx 页顶部加入:
<%@ OutputCache Duration="60"
VaryByParam="categoryId"
Location="Server" %>
Duration="60"表示缓存 60 秒;VaryByParam="categoryId"为不同分类参数保存不同响应;Location="Server"将本场景的缓存范围放在服务器端。
如果遗漏 VaryByParam,不同分类可能命中同一页结果,这是正确性问题,不是单纯性能问题。对 MVC 项目应使用当前项目版本对应的输出缓存属性/配置,不把 Web Forms 页指令复制到 Controller。
第二步:对共享数据使用应用缓存
若页面中只有某份读多写少的数据查询昂贵,可只缓存数据,不缓存整页输出。在 .NET Framework 4 及以上可考虑 MemoryCache;老项目也常见 System.Web.Caching.Cache。以下是 MemoryCache 的简化边界:
using System;
using System.Runtime.Caching;
public Product[] GetProducts(int categoryId)
{
string key = "products:category:" + categoryId;
var cache = MemoryCache.Default;
if (cache.Get(key) is Product[] cached)
return cached;
Product[] products = repository.LoadProducts(categoryId);
cache.Set(
key,
products,
new CacheItemPolicy
{
AbsoluteExpiration = DateTimeOffset.UtcNow.AddSeconds(60)
});
return products;
}
这段代码演示键必须包含 categoryId。高并发下多个未命中请求可能同时回源,真实项目应根据所用缓存 API 增加单飞/互斥机制,但不要在全局大锁内执行所有分类查询。
第三步:在 IIS 开启静态和动态压缩
先在服务器角色/功能中安装 IIS 的 Static Content Compression 和 Dynamic Content Compression。只写 web.config 但没安装模块,配置不会生效。
在站点允许的配置范围内加入:
<configuration>
<system.webServer>
<urlCompression
doStaticCompression="true"
doDynamicCompression="true" />
</system.webServer>
</configuration>
IIS 的 <urlCompression> 用于在站点、应用或目录级启用静态/动态内容压缩;具体算法、MIME 类型和 CPU 阈值由 IIS 压缩配置决定。
从实际处理来看,GZIP 是 HTTP 内容编码协商的结果:浏览器在 Accept-Encoding 中声明支持,IIS 选择支持的编码并在响应中返回 Content-Encoding: gzip。不要手工把未压缩内容加上该响应头。
第四步:验证缓存和 GZIP
验证输出缓存
- 清空测试环境中的对应缓存,请求
categoryId=1,记录服务器处理时间和数据库查询次数。 - 在 60 秒内用相同参数再请求一次。预期页面结果相同,且不再执行该页的昂贵生成路径。
- 改为
categoryId=2。预期产生新的内容变体,不能返回分类 1 的页面。 - 等待超过 60 秒后再请求,确认数据能重新生成。
验证 GZIP
在浏览器开发者工具的 Network 面板打开某个 HTML 或 JSON 请求,检查:
- 请求头含
Accept-Encoding: gzip或包含 gzip 的编码列表; - 响应头含
Content-Encoding: gzip; - 传输大小小于解压后的资源大小。
对 PNG、JPEG、WebP、ZIP 等已压缩格式,不应以“没有 GZIP”作为错误。重复压缩通常几乎不节省体积,反而消耗 CPU。
常见失败和修正
缓存后用户看到别人的内容
立即停用该页的共享输出缓存,检查内容实际由哪些参数、登录身份、语言、设备或权限决定。不能准确表达变体时,改为缓存不含用户私有信息的数据或页面片段。
已配置 doDynamicCompression 但没有 gzip
- 确认 IIS 动态压缩角色服务已安装。
- 确认当前配置节没有被服务器级锁定。
- 检查响应 MIME 类型是否在动态压缩类型中启用。
- 检查服务器 CPU 是否超过 IIS 动态压缩禁用阈值。
- 确认测试请求确实带了支持的
Accept-Encoding。
开启后 CPU 升高
压缩是用 CPU 换带宽。先按 MIME 类型和内容大小限定压缩对象,然后检查动态压缩 CPU 阈值。不要只看单个页面的压缩比,还要看并发下的 CPU、响应时间和出站带宽。
总结
经典 ASP.NET 页面的缓存与 GZIP 应分开设计和验证:输出缓存要正确表达所有内容变体,并避免缓存用户私有响应;IIS 压缩要先安装模块,再对文本 MIME 类型启用,最后用 Content-Encoding 和传输大小核实生效。先正确,再测量,才能把缓存与压缩变成可控的性能改进。
-
09.21
LINQ 筛选、排序、分组与联接完整示例
-
09.21
NHibernate 3 lambda-configuration 属性配置方法
-
09.21
NHibernate 2.1.2 延迟加载配置与验证教程
-
09.21
Flutter BoxConstraints 无限高度报错怎么修复
-
09.21
ASP.NET 缓存与 GZIP 页面性能优化教程
-
09.21
NHibernate 3 fluent-configuration 属性配置教程
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏