如何在 Apache 2.x 中使用 mod_deflate 预压缩文件?

Posted

技术标签:

【中文标题】如何在 Apache 2.x 中使用 mod_deflate 预压缩文件?【英文标题】:How can I pre-compress files with mod_deflate in Apache 2.x? 【发布时间】:2010-09-09 16:22:46 【问题描述】:

我通过 apache 使用 Content-Encoding: zip 提供所有内容,但它会即时压缩。我的大量内容是磁盘上的静态文件。我想事先对文件进行 gzip 压缩,而不是在每次请求时都压缩它们。

我相信这是 mod_gzip 在 Apache 1.x 中自动执行的操作,但只是将文件放在旁边带有 .gz 的文件。 mod_deflate 不再是这种情况。

【问题讨论】:

我不认为你会节省很多;使用现代 Web 服务器,动态压缩内容的成本可以忽略不计。 我在 Xen VM 中运行 Web 服务器,因此我想为其他 VM 节省尽可能多的 CPU。此外,与动态压缩相比,我能够将使用 httperf 在预压缩的 55k 文件上测量的请求率提高一倍。 见***.com/questions/9076752/… 【参考方案1】:

无论如何,这个功能在 mod_gzip 中被放错了地方。在 Apache 2.x 中,you do that with content negotiation。具体来说,您需要使用Options directive 启用MultiViews,并且您需要使用AddEncoding directive 指定您的编码类型。

【讨论】:

***.com/questions/9076752/…【参考方案2】:

用我在配置中遗漏的非常简单的一行来回答我自己的问题:

Options FollowSymLinks MultiViews

我错过了 MultiViews 选项。它在 Ubuntu 默认的 Web 服务器配置中,所以不要像我一样把它扔掉。

我还写了一个快速的 Rake 任务来压缩所有文件。

namespace :static do
    desc "Gzip compress the static content so Apache doesn't need to do it on-the-fly."
    task :compress do
        puts "Gzipping js, html and css files."
        Dir.glob("#RAILS_ROOT/public/**/*.js,html,css") do |file|
            system "gzip -c -9 #file > #file.gz"
        end
    end
end

【讨论】:

【参考方案3】:

我担心 MultiViews 不会按预期工作:文档说 Multiviews 工作“如果服务器收到对 /some/dir/foo 的请求,如果 /some/dir 启用了 MultiViews,并且 /some/dir/foo 确实不存在...”,换句话说:如果您在同一目录中有文件 foo.js 和 foo.js.gz,即使 AcceptEncoding gzip 标头为由浏览器传输(您可以通过暂时禁用 mod_deflate 并使用例如 HTTPFox 监控响应来验证此行为)。

我不确定 MultiViews 是否有办法解决这个问题(也许你可以重命名原始文件,然后添加一个特殊的 AddEncoding 指令),但我相信你可以构造一个 mod_rewrite 规则来处理这个问题。

【讨论】:

我确定它当时有效,而且我确定我没有删除原始文件。莫名其妙地涉及了 mod_rewrite 。我可能有一条规则是“如果文件存在,则静态提供此服务”。我可能已将其更改为包含 .gz 扩展名,但我不再有权访问该系统进行验证。 如果在您的示例中您只请求 foo 而不是 foo.js,它将起作用。如果客户端接受 gzip,他们将获得 foo.js.gz,否则他们将获得 foo.js。 见***.com/questions/9076752/…【参考方案4】:

可以使用mod_negotiation 提供预压缩文件,尽管它有点挑剔。主要困难在于only requests for files which do not exist are negotiated。因此,如果foo.jsfoo.js.gz 都存在,则/foo.js 的响应将始终未压缩(尽管/foo 的响应可以正常工作)。

我找到的最简单的解决方案 (from François Marier) 是使用双文件扩展名重命名未压缩的文件,因此 foo.js 部署为 foo.js.js 因此对 /foo.js 的请求在 foo.js.js 之间协商(无编码) 和foo.js.gz(gzip 编码)。

我将这个技巧与以下配置结合起来:

Options +MultiViews
RemoveType .gz
AddEncoding gzip .gz

# Send .tar.gz without Content-Encoding: gzip
<FilesMatch ".+\.tar\.gz$">
    RemoveEncoding .gz
    # Note:  Can use application/x-gzip for backwards-compatibility
    AddType application/gzip .gz
</FilesMatch>

我wrote a post 详细讨论了此配置的原因和一些替代方案。

【讨论】:

这似乎不再起作用了。使用 Apache 2.4.25 我总是得到未压缩的结果,可能是因为 MultiViews 只有在文件不存在的情况下才会启动。医生说了这么多。可惜! 好消息@MvG,你是绝对正确的!我已经用解决方法更新了答案,尽管它并不理想,因为它需要重命名未压缩的文件和一些配置技巧。希望对您有所帮助! @Kevinoid:这正是我自己想出的解决方法,在上面睡觉之后。不错!【参考方案5】:

我有一个从源代码构建的 Apache 2,我发现我必须在我的 httpd.conf 文件中修改以下内容:

将多视图添加到选项:

Options Indexes FollowSymLinks MultiViews

取消注释 AddEncoding:

AddEncoding x-compress .Z
AddEncoding x-gzip .gz .tgz

评论添加类型:

#AddType application/x-compress .Z
#AddType application/x-gzip .gz .tgz

【讨论】:

【参考方案6】:

mod_gzip 也可以即时压缩内容。您可以通过实际登录到您的服务器并从 shell 执行此操作来预压缩文件。

cd /var/www/.../data/
for file in *; do
    gzip -c $file > $file.gz;
done;

【讨论】:

这将删除原始文件,这意味着没有 Aceept-Encoding: gzip 的客户端将不会被服务。 在编辑时,为什么不添加 -9 并尽可能获得最高压缩率。我的 1500 个文件在 38 秒内压缩,因此在带宽和下载时间中节省每个字节是值得的。 :) (也希望我可以在之前的评论中编辑我的错字。呃) 不是根据我 Mac 上的手册页,它说 -6 是默认值。【参考方案7】:

您可以使用mod_cache 代理内存或磁盘中的本地内容。我不知道这对mod_deflate 是否会按预期工作。

【讨论】:

【参考方案8】:

我有很多大的 .json 文件。大多数读者都处于这种情况。预览答案没有谈到返回的“Content-type”。

如果您希望以下请求透明地返回带有“Content-Type: application/json”的预压缩文件,请使用 Multiview 和 ForceType

http://www.domain.com/(...)/bigfile.json
-> Content-Encoding:gzip, Content-Type: Content-Encoding:gzip

1) 文件必须重命名:“file.ext.ext”

2) 多视图与 ForceType 配合得很好

在文件系统中:

// Note there is no bigfile.json
(...)/bigfile.json.gz
(...)/bigfile.json.json

在你的 apache 配置中:

<Directory (...)>
    AddEncoding gzip .gz
    Options +Multiviews
    <Files *.json.gz>
        ForceType application/json
    </Files>
</Directory>

简短:)

【讨论】:

以上是关于如何在 Apache 2.x 中使用 mod_deflate 预压缩文件?的主要内容,如果未能解决你的问题,请参考以下文章

Apache2.4.x与Apache2.2.x的一些区别

Apache Commons DBCP 2.x 在生产中的稳定性

您如何利用“Apache httpOnly cookie 披露”?

apache配置

apache_conf 使用ApacheConnector为Jersey 2.x客户端配置代理

如何指定 Log4J 2.x 配置位置?