手册:文件缓存
MediaWiki有一个缓存条目的HTML代码的可选缓存方案。
操作和使用
文件缓存只为匿名用户服务,他们看到的是相同的HTML渲染。 已登录用户不能用这个缓存,因为他们的页面包含了用户名、选择的皮肤等。
文件缓存是通过在LocalSettings.php中设置$wgUseFileCache 和$wgFileCacheDirectory 参数启用的:
$wgUseFileCache = true; // 默认: false
$wgFileCacheDirectory = "$IP/images/cache"; // 默认值:"{$wgUploadDirectory}/cache",等于"$IP/images/cache"
这将导致wiki的每个页面的渲染HTML网页存储在硬盘上的单个文件中。匿名用户的任何后续请求都不会通过再次呈现页面来满足,而是通过发送存储在磁盘上的HTML版本来满足。这节省了时间。
生成的HTML web文本存储在$wgFileCacheDirectory
下的目录中的磁盘中,看起来有点像:
-rw-r--r-- 1 apache apache 57421 Jan 7 01:58 cache/0/04/P%C3%A1gina_principal.html -rw-r--r-- 1 apache apache 29608 Jan 4 16:37 cache/1/17/P%C3%A1gina_Riscada.html -rw-r--r-- 1 apache apache 21592 Jan 3 07:27 cache/1/1c/P%C3%A1gina_Duplicada.html -rw-r--r-- 1 apache apache 36088 Jan 7 02:03 cache/2/24/P%C3%A1gina_principal_alternativa.html -rw-r--r-- 1 apache apache 44205 Jan 7 06:10 cache/a/a4/P%C3%A1gina_linkada.html -rw-r--r-- 1 apache apache 24686 Jan 3 07:27 cache/d/db/P%C3%A1gina_Invertida.html -rw-r--r-- 1 apache apache 17222 Jan 3 06:28 cache/f/f0/P%C3%A1gina_n%C3%A3o_encontrada.html
在此示例中,文件缓存目录为“cache/”,存储的wiki页面命名为“Página …”,生成一个对应的“Página_…”。html文件。 这些文件将在用户访问wiki上的文章时创建;您可以使用rebuildFileCache.php维护脚本一次性创建它们。
文件缓存倾向于积极缓存;缓存的页面没有设置到期日期,即使页面包含变量、扩展名和其他可变输出,也会无条件缓存。某些扩展禁用具有动态内容的页面的文件缓存。
考虑使用$wgUseGzip 代替或组合使用,以获得更有效的结果。
对于较大的站点,使用外部缓存(如squid或varnish)比启用文件缓存更好。
如果文件缓存似乎不工作,请确保Web服务器具有写入所选目录的权限。
限制
缓存文件的文件名由相应的页面标题决定。 根据页面标题中使用的语言,必须对文件名中的某些字符进行编码,以构成相应文件系统的有效文件名。 For languages like Arabic, Chinese and so on this may result in the following PHP warning:
PHP Warning: file_put_contents(cache/......html.gz): failed to open stream: File name too long in includes/cache/FileCacheBase.php on line 171
這是一個已知限制。 参见工單T148684。
分类和图像描述页不会从文件缓存中清除。 例如,从分类中添加或删除页面不会更新分类页面,导致未登录的用户无法看到分类页面中的更改。 这是一个已知的限制。 参见工單T26575
域和范围
缓存仅适用于以下用户:
- 未登录。
- 他们的user_newtalk标志未激活。
仅对以下页面进行缓存:
- 不是特殊页面。
- 不是重定向。
- 正在当前版本中查看,纯访问,无url参数
这涵盖了对wiki的大多数请求,但设置字节码和应用程序缓存来处理其余的请求仍然很重要。
驗證
缓存文件的修改时间与每次访问上设置为LocalSettings.php 的全局$wgCacheEpoch
时间戳进行比较。
如果文件至少与这两个文件一样新,则认为它是有效的,并直接发送给客户端。如果它较旧或不存在,将继续分析和渲染,并保存结果以供将来使用。
验证
通过将$wgCacheEpoch
设置为当前时间或删除缓存中的所有文件,可以使整个缓存无效。
通过更新其page.page_touched字段,单个页面将失效,调用Title::invalidateCache()
可以方便地完成。
这应该在文章创建、编辑保存、重命名以及链接文章的创建和删除(以便更新编辑链接)时完成。
编辑模板时发生的无效操作,例如,检查使用模板将缓存日期与page_touched进行比较的页面。
一些情况尚未得到妥善处理,可能包括:
- 浏览器“重新加载”或“刷新”(只重新加载相同的缓存页面而不更新)
- 来自扩展(如$1)的输出变量禁用这些页面的文件缓存,以避免过时数据。
即使在浏览器刷新时,那些不返回的数据也会返回过时的数据。
- 某些长错误消息可以无限期缓存,就像它们是有效的页面内容一样;只有?action=purge将在存储后从文件缓存中删除这些文件。 最小输出大小阈值用于避免缓存大多数错误,如致命的PHP错误。
另请参阅:Manual:$wgInvalidateCacheOnLocalSettingsChange 。
過期
可能会有一些缓存页面过期的方法,特别是对于包含变量的页面(它是X日期,我们有X篇文章等)。
如果$parserOutput->getCacheTime()
为-1
,则页面输出将禁用文件缓存。
没有设置到期时间的规定,因此所有页面的所有HTML都将永久缓存。
一个显式的?action=purge
命令(或对页面的编辑)将重新生成该页面,但MediaWiki内部无缓存标志和浏览器刷新都不会删除过期的扩展输出,一旦它作为文件缓存页面的一部分存储。
刷新选项卡
可以添加一个选项卡来强制一个单独的页面无效并使用?action=purge使用清理页面缓存扩展进行清除。
壓縮
可选地,可以压缩缓存以节省空间和带宽。(这需要在PHP配置中启用zlib。)
$wgUseGzip = true;
如果启用压缩,缓存文件将保存为.html.gz。 在Accept-Encoding字段中宣传支持gzip的浏览器将直接获得gzip版本;对于那些没有这样做的浏览器,我们会立即解压缩数据,并将明文发送给它们。
将发送一个"Vary: User-agent"标头,告诉代理缓存要更加小心地向谁重新发送数据。 (“Vary: Accept-encoding”更合适,但Internet Explorer拒绝缓存如此标记的页面。)
紧急回退
此頁面已过时。 |
如果wiki无法与数据库服务器联系,它将尝试显示请求的任何页面的缓存版本,无论该页面是否为当前页面,并在其中添加“database is down”消息。
這有一些限制:
- 特殊页面没有任何覆盖,只有一条警告信息
- 重定向页面未缓存,因此单击指向重定向的链接不会到达最终目标
- 由于MediaWiki检查DB以查看标题是否具有有效的跨wiki前缀,标题中带有冒号的页面(有效命名空间除外)仍可能失败。只有当页面前缀没有跨wiki缓存条目(请参见
$wgInterwikiExpiry
)或$wgMainCacheType
回退到(或设置为)DB_cache
时,才会出现这种情况。 - 尝试使用非访问操作会导致纯页面视图,这可能会令人困惑
- MySQL连接超时可能会有问题,这会导致放弃前花费很长时间,特别是如果使用持久连接并且数据库稍后失效。调整php.ini中的mysql.connect_timeout(设置为3或更多)以解决。编辑Web服务器的php.ini而不是命令行的php.ini。
- 如果
$wgStatsMethod
设置为cache
,而$wgMainCacheType
回退到(或设置为)DB_CACHE,则回退可能失败
直接提供缓存页面
默认情况下,MediaWiki使用php传递缓存页面。下面是我们如何使用Web服务器配置技巧直接提供缓存文件,而根本不调用MediaWiki或PHP。
首先,设置$wgFileCacheDepth = 0;
。然后我们添加重写规则。见下文。
Apache
已发现以下mod_rewrite规则在运行Apache 2.2的共享Web主机上的.htaccess
文件中有效:
RewriteBase / # If a cached page exists under /w/html_cache, do an internal redirect to it: RewriteCond %{HTTP_COOKIE} !UserID= RewriteCond %{QUERY_STRING} !. RewriteCond %{DOCUMENT_ROOT}/w/html_cache/$1.html -s RewriteRule ^wiki/(.+)$ /w/html_cache/$1.html [B,L,NS]
然而,对于标题包含标点符号或非ASCII字符的页面,此重写规则无法正常工作。 一个整洁的解决方案是使用RewriteMap,但.htaccess上下文不支持这一点。 相反,通过直接从原始请求行提取URL转义标题,可以使用以下技巧处理非ASCII标题:
RewriteBase / # If a cached page exists under /w/html_cache, do an internal redirect to it: RewriteCond %{HTTP_COOKIE} !UserID= RewriteCond %{QUERY_STRING} !. ReWriteCond %{THE_REQUEST} ^GET\x20/wiki/([^\x20/]+)\x20HTTP RewriteCond %{DOCUMENT_ROOT}/w/html_cache/%1.html -s RewriteRule ^wiki/(.+)$ /w/html_cache/%1.html [B,L,NS]
The previous rewrite rules will handle requests of the form
https://site/wiki/Page_Name
To handle requests where the Page_Name is in the QUERY_STRING like
https://site/w/index.php?title=Page_Name
the following works:
RewriteCond %{HTTP_COOKIE} !UserID= RewriteCond %{QUERY_STRING} ^title=([^&]+)$ RewriteCond %{DOCUMENT_ROOT}/images/cache/ns0\%3A%1.html -s RewriteRule ^ /images/cache/ns0\%253A%1.html? [B,L,NS]
这仍然与包含句点、斜线或其他标点符号的标题不匹配,文件缓存会转义这些标点符号,但浏览器不会(反之亦然)。 还应确保发送适当的Vary标头:
Header append Vary Cookie
还要注意,由于这个重定向技巧完全绕过了MediaWiki,所以它不会尊重$wgCacheEpoch
。
您可能需要根据需要手动清除或重建缓存。
Nginx
由于nginx配置语言非常有限(例如,它不允许嵌套if语句),因此它需要ngx_lua模块。
以下conf应该集成在服务器块中,它假设:
- 您正在使用的url类似于example.com/Page;
- 缓存文件夹位于MediaWiki文件夹中(默认);
- 你已经在最终的location块中将.php文件代理到php-fpm(或其他文件)。
并且這有一些限制:
- 与Apache解决方案一样,您必须运行cron作业或在缓存文件更改时手动重建缓存文件;
- 标题包含非ASCII字符的页面是通过PHP提供的(无论如何对用户来说应该是透明的)。
根据需要更改路径。
location ~ /cache/(.*) {
internal;
}
location / {
default_type 'text/html';
rewrite_by_lua '
local cookie = ngx.req.get_headers()["Cookie"] or ""
if string.match(cookie, "UserID") then -- if we are logged in...
ngx.exec("@rewrite")
else
local page = string.sub(ngx.var.request_uri, 2, -1) -- get the page name without the leading slash
local filename = page .. ".html"
local f = io.open("/var/www/w/cache/" .. filename, "r")
if f ~= nil then -- if the file exists, close it and serve it directly
io.close(f)
ngx.header["x-wiki-cache"] = "via nginx" -- headers to help you debug
ngx.exec("/cache/" .. filename)
else
ngx.header["x-wiki-cache"] = "via mediawiki"
ngx.exec("@rewrite")
end
end
';
}
location @rewrite {
rewrite ^/([^?]*)(?:\?(.*))? /index.php?title=$1&$2 last;
}
代码维护
- Maintained by Unknown or Unassigned[Maintainers page].
- Issue tracker: Phabricator MediaWiki-Core-HTTP-Cache (Report an issue)