项目

通用

个人资料

操作

CML,即缓存元语言

警告

  • mod_cml 已弃用,推荐使用提供类似功能的 mod_magnet

这是什么

CML 旨在将动态网站的缓存命中和缓存未命中决策
从动态应用程序中移出,从而无需启动应用程序或动态
语言。

特别是 PHP,众所周知在脚本开始执行之前会有巨大的开销。

如何安装

CML 使用的语言是 LUA,您可以在 https://lua.ac.cn/ 找到它。

要了解如何编写 LUA 代码的背景知识,请查看

优势

CML 的主要优势是其性能。

一个非常简单的基准测试显示:

  • 静态 'output.html'(由 PHP 脚本生成)约为 1000 请求/秒
  • 如果调用 index.cml(缓存命中),约为 600 请求/秒
  • 如果调用 index.php(缓存未命中),约为 50 请求/秒

使用 CML 将测试页面的性能提高了 12 倍,使其
几乎达到了静态文件传输的可能最大值。

使用模式

https://lighttpd.ac.cn/ 正在使用 CML 来降低负载(即使负载很小)。

首页的布局取决于几个文件:

  • content-1
  • content-6
  • 模板 /main.tmpl

如果任何文件被修改,页面的缓存版本也必须随之改变。

output_contenttype = "text/html" 

trigger_handler = "index.php" 

-- this file updated by the trigger 
output_include = { "output.html" }

docroot = request["DOCUMENT_ROOT"]
cwd = request["CWD"]

-- the dependencies
files = { cwd .. "content-1", cwd .. "content-6", docroot .. "main.tmpl" }

cached_mtime = file_mtime(cwd .. "output.html")

-- if one of the source files is newer than the generated files
-- call the trigger
for i,v in ipairs(files) do
  if file_mtime(v) > cached_mtime then return 1 end
end

return 0

延迟重新检查

如果您正在构建一个新闻聚合器,延迟缓存内容的重建一段时间会很有用,因为您可以假设新闻不会随着每次请求而改变。因此,您不需要在每次请求时重新验证,而是延迟验证检查。

-- same as above

-- check again in 5 minutes
delay_recheck = 3600

if cached_mtime + delay_recheck > os.time() then return 0 end

-- we are behind the delayed recheck, check the cache as usual

for i,v in ipairs(files) do
  if file_mtime(v) > cached_mtime then return 1 end
end

return 0

为了告诉中间的代理在收到此内容后的 5 分钟内不要再次检查,请使用 setenv 模块并添加一些缓存控制或过期头信息。

CML 与数据库

CML 不提供对 MySQL 或 PostgreSQL 等数据库的直接访问,而且可能永远不会。

有一种更好/更快的方式来使 CML 与数据库接口:MemCache

您所要做的就是将决定页面是否需要重新生成所需的信息保存在 memcached 存储本身中。假设每当您在数据库中存储一个条目时,您都为其关联一个版本 ID。一旦您对资源进行更改,版本 ID 就会递增。

这个版本 ID 现在同时存储在数据库和 memcache 中。CML 现在可以获取版本 ID,检查是否已为其生成内容,并在必要时生成。

output_contenttype = "text/html" 

content_key = md5(request["PATH_INFO"])
version = memcache_get_long(content_key)
cwd = request["CWD"]

trigger_handler = "generate.php" 

if version >= 0 then
  output_include = { cwd .. content_key .. "-" .. version .. ".html" }
  return 0
else
  return 1
end

generate.php 将需要:

  • 获取 PATH_INFO
  • 从数据库中获取相关信息
  • 为页面生成内容并写入磁盘
  • 将其交付给客户端

要使数据库与 memcached 接口,您可以使用 UDF

在 MySQL 和 UDF 中,您只需执行:

#!sql
BEGIN;
UPDATE content SET @v := (version = version + 1) WHERE id = <id>;
SELECT memcache_set("127.0.0.1:11211", <id>, @v);
COMMIT;

检查缓存当前正在使用的版本

#!sql
SELECT memcache_get("127.0.0.1:11211", <id>);

gstrauss 更新于 大约 3 年前 · 14 次修订