ASP 文件中很多include ,会在 IIS 中,每次有人来就读很多文件,还是一次性缓存到 IIS? - 第1页 - 码农库
 
首页 /编程语言和算法/VB6/VBA/ASP/TB
 ASP 文件中很多include ,会在 IIS 中,每次有人来就读很多文件,还是一次性缓存到 IIS?
今天 15:55

ASP(经典 ASP,VBScript)IIS 中 工作机制

注意:这是SSI 服务器端包含,不是 ASP 的Server‑Execute/Server‑Include,是 IIS 解析阶段处理。

核心结论

是 IIS 在执行 ASP 脚本前,做文本合并(预处理器)**,不是运行时动态加载。

不会永久缓存合并后的脚本到 IIS 内存,但 ASP 有脚本缓存;文件改动会自动失效。

每一个请求到来:

IIS SSI 先把被 include 的文件原文文本插入主 asp 文件对应位置,拼接成一份完整的 ASP 源码。

交给 ASP 脚本引擎(asp.dll)编译执行。

如果该份拼接后的脚本没有被缓存,就编译;如果已经缓存,直接跑编译好的字节码。

⚠️重点:SSI 包含是文本级拼接,发生在脚本编译之前,不是运行时读文件。

详细过程(IIS 6 / IIS7 + 经典 ASP)

情况 A:文件没改动

用户请求 main.asp

IIS SSI 扫描 main.asp,遇到,读取磁盘上a.asp原始内容,把文本插入 main.asp 里面,得到完整源码。

asp.dll 检查:这份组合源码是否已经有编译缓存(Script Cache)

✅有缓存:直接执行编译好的脚本,不再重新解析、不重新 VBS 编译;但 SSI 这一步仍然要做(检查文件时间戳判断缓存是否有效)

❌无缓存:对拼接好的全部源码做编译,字节码放入 ASP 脚本缓存,供后续请求复用。

即使命中脚本缓存,IIS 仍然会访问磁盘读取 include 文件的文件时间戳,用来判断文件有没有修改;不需要读取完整文件内容,只拿文件属性。

情况 B:任意一个被 include 的 asp 文件修改了

只要main.asp、a.asp、b.asp其中任意一个磁盘文件修改,时间戳变化,ASP 缓存立刻作废。下一次请求会:

SSI 重新读取全部 include 文件文本,重新拼接完整源码

重新编译,生成新缓存。

情况 C:每请求都会完整读磁盘文件?

未命中缓存(文件刚改、冷启动):真实读磁盘,读取 include 文件全部内容,文本拼接。

命中缓存:只读取文件元信息(时间戳)校验,不读取整个文件内容,直接跑缓存字节码。

IIS 重启、应用池回收后,全部脚本缓存清空,下一次访问全部重新读文件 + 编译。

virtual vs file

<!--#include file="a.asp" -->   '相对物理目录
<!--#include virtual="/inc/a.asp" --> '网站虚拟路径

两者 SSI 处理逻辑完全一样,只是找文件方式不同,缓存机制无差别。

和 Server.Execute/ Server.Transfer 的区别

<% Server.Execute("a.asp") %>

Server.Execute是运行时调用,不是 SSI 文本拼接,每次执行都会独立处理该页面,和#include完全不一样,不要混淆。

性能关键点(大量 include 的坑)

大量 include 不会导致每次请求都反复读全部文件内容(缓存命中后),但是每次请求都要做时间戳检查。几十个 include 文件,每个请求都要拿几十个文件的 last‑write 时间。

如果 include 极多(几十上百),高并发场景下,大量文件时间戳检查会带来一定磁盘 IO 压力。

只要任意一个被包含文件改动,整个页面缓存全部失效,下一次访问全部重新读文件编译。

SSI 是预处理,include 不能放在 if 判断里面!

<% If False Then %>
<!--#include file="debug.asp" -->  '❌就算条件false,SSI仍然会把文件拼进来!!
<% End If %>

SSI 在 VBS 运行之前就处理完毕,VBS 的逻辑控制不到#include。想条件包含只能用Server.Execute。

IIS 中 ASP 脚本缓存配置(IIS7+)

经典 ASP 缓存由ASP 脚本引擎控制:

Cache Scripts:True (默认开启),就是把编译后的字节码缓存内存;关闭的话,每一次请求都要读所有 include 文件、拼接、重新编译,性能暴跌。

Script File Cache Size:最大缓存多少脚本,站点 include 多页面多要调大。

这个缓存是应用池内存缓存,应用池回收就清空。不是 IIS 全局永久缓存。

总结一句话

有大量:冷启动 / 文件修改时,请求会读取所有被包含的磁盘文件文本做源码拼接;缓存命中之后,不会重读完整文件内容,只校验各个 include 文件的修改时间,直接运行内存中编译好的脚本。不是一次性永久加载到 IIS,应用池回收就全部清空重来。


也就是说,如果一个 asp 文件没被用到,IIS 是不会缓存它的,那么第一次访问这个 asp 文件才缓存?

是的,完全正确

经典 ASP 的脚本缓存是按需延迟缓存(惰性缓存):

文件不被请求到,就不会读、不会编译、不会进缓存。只有第一次实际执行到这个页面,才会触发整套流程:SSI 读取所有 include 文件 →拼接源码 →编译 →把字节码放进 ASP 脚本缓存。

 
全部回复(0)
首页 | 电脑版 |