运维系列.Nginx中使用HTTP压缩功能(二)

简介: 运维系列.Nginx中使用HTTP压缩功能(二)

运维系列.Nginx中使用HTTP压缩功能(一):https://developer.aliyun.com/article/1582101

4. 优化Nginx HTTP压缩

4.1 静态文件与动态内容的压缩策略

Nginx中,对静态文件和动态内容的压缩策略需要分别考虑,因为它们的特性和处理方式有所不同。

对于静态文件,如HTMLCSSJavaScript、图片等,我们可以采用更激进的压缩策略。这是因为静态文件的内容不会频繁变化,我们可以预先压缩这些文件,并将压缩后的版本存储在服务器上。这种方法可以显著减少服务器的实时计算负担。

Nginx中,我们可以使用gzip_static模块来实现静态文件的预压缩。配置示例如下:

gzip_static on;
gzip_types text/plain text/css application/javascript application/json;

这个配置告诉Nginx优先查找并发送预压缩的".gz"文件。例如,当请求"style.css"时,如果存在"style.css.gz"文件,Nginx会直接发送这个预压缩的文件。

对于动态内容,如API响应或动态生成的HTML页面,我们需要采用实时压缩的策略。这是因为动态内容的每次响应可能都不同,无法预先压缩。在这种情况下,我们可以使用Nginx的动态gzip压缩功能:

gzip on;
gzip_types application/json text/plain;
gzip_min_length 1000;
gzip_comp_level 6;

这个配置启用了动态gzip压缩,指定了需要压缩的内容类型,设置了最小压缩大小为1000字节,压缩级别为6。

对于大型静态文件,如视频或大型PDF文件,通常不建议进行压缩。这些文件往往已经是压缩格式,再次压缩可能会增加文件大小或消耗过多的CPU资源。我们可以通过gzip_types指令排除这些文件类型:

gzip_types text/plain text/css application/javascript application/json;
# 注意这里没有包含视频或PDF的MIME类型

总的来说,对静态文件采用预压缩策略,对动态内容采用实时压缩策略,可以在性能和资源利用之间取得良好的平衡。

4.2 压缩与缓存的结合使用

压缩和缓存是两种强大的性能优化技术,当它们结合使用时,可以显著提升网站的性能和用户体验。

首先,我们可以在Nginx中同时启用压缩和缓存。对于静态内容,我们可以使用Nginx的缓存模块来存储压缩后的文件。配置示例如下:

http {
    proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_cache my_cache;
            proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
            proxy_cache_valid 200 60m;
            proxy_cache_valid 404 10m;

            gzip on;
            gzip_types text/plain text/css application/javascript application/json;

            proxy_pass http://backend;
        }
    }
}

在这个配置中,我们设置了一个缓存区域"my_cache",并在location块中启用了这个缓存。同时,我们也启用了gzip压缩。这意味着Nginx会先压缩内容,然后将压缩后的内容存储在缓存中。


对于动态内容,我们需要特别注意缓存策略。一种常见的做法是使用"Vary"头部来区分不同的压缩版本。例如:

location /api/ {
    proxy_pass http://backend;
    gzip on;
    gzip_types application/json;
    gzip_vary on;
    proxy_cache my_cache;
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
    proxy_cache_valid 200 5m;
}

这里的gzip_vary on指令会添加一个"Vary: Accept-Encoding"头部,告诉缓存服务器分别存储压缩和非压缩版本的内容。

另外,对于一些频繁变化的动态内容,我们可能需要禁用缓存或设置很短的缓存时间。例如:

location /realtime-data/ {
    proxy_pass http://backend;
    gzip on;
    gzip_types application/json;
    proxy_cache_bypass $http_pragma;
    proxy_cache_revalidate on;
    proxy_cache_min_uses 3;
    proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
    proxy_cache_valid 200 1m;
}

这个配置为实时数据设置了很短的缓存时间(1分钟),并允许客户端通过发送特定的头部(如"Pragma: no-cache")来绕过缓存。

最后,对于一些大型静态文件,如视频或大型图片,我们可能希望缓存但不压缩。这可以通过在特定的location块中禁用压缩来实现:

location ~* \.(mp4|png|jpg|jpeg)$ {
    gzip off;
    proxy_cache my_cache;
    proxy_cache_valid 200 60m;
    proxy_pass http://backend;
}

通过这种方式,我们可以针对不同类型的内容制定最适合的压缩和缓存策略,从而最大化性能优化效果。需要注意的是,压缩和缓存策略的具体配置应该根据网站的实际情况和需求来调整,并进行充分的测试和监控,以确保达到最佳效果。

4.3 根据客户端特性调整压缩策略

在Nginx中,我们可以根据客户端的特性来调整压缩策略,以提供更加个性化和优化的用户体验。这种方法可以帮助我们在不同的设备和网络条件下实现最佳的性能。


首先,我们可以根据用户代理(User Agent)来调整压缩策略。Nginx提供了$http_user_agent变量,我们可以使用它来识别不同的浏览器和设备。例如,对于移动设备,我们可能希望使用更激进的压缩策略来节省带宽:

set $compression_level 6;
if ($http_user_agent ~* "Mobile") {
    set $compression_level 8;
}
gzip on;
gzip_comp_level $compression_level;

在这个配置中,我们为移动设备设置了更高的压缩级别。这可以帮助移动用户在可能较慢的网络条件下获得更好的加载速度。

其次,我们可以根据客户端的IP地址来调整压缩策略。例如,对于来自特定地理位置的用户,我们可能知道他们的网络条件较差,因此可以应用更强的压缩:

geo $compression_level {
    default 6;
    10.0.0.0/8 8;
    192.168.0.0/16 8;
}
gzip on;
gzip_comp_level $compression_level;

这个配置为特定的IP范围设置了更高的压缩级别。

另外,我们还可以根据请求头中的"Accept-Encoding"字段来调整压缩策略。虽然现代浏览器通常都支持gzip,但有些客户端可能支持更高效的压缩算法,如Brotli

brotli on;
brotli_comp_level 6;
brotli_types text/plain text/css application/javascript application/json;

gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/javascript application/json;

map $http_accept_encoding $prefer_brotli {
    "~br" 1;
    default 0;
}

location / {
    if ($prefer_brotli) {
        set $args $args&prefer_brotli=1;
    }
    proxy_pass http://backend;
}

在这个配置中,我们同时启用了Brotligzip压缩,并根据客户端的"Accept-Encoding"头部来决定使用哪种压缩方法。

最后,我们还可以考虑根据当前服务器负载来动态调整压缩策略。虽然Nginx本身不直接支持这种功

能,但我们可以通过结合使用Lua模块来实现:

http {
    lua_shared_dict compression_level 10m;

    init_by_lua_block {
        local compression_level = ngx.shared.compression_level
        compression_level:set("level", 6)
    }

    server {
        location / {
            set_by_lua_block $dynamic_comp_level {
                local compression_level = ngx.shared.compression_level
                return compression_level:get("level")
            }

            gzip on;
            gzip_comp_level $dynamic_comp_level;

            # 其他配置...
        }
    }
}

在这个配置中,我们使用Lua共享字典来存储当前的压缩级别。我们可以通过外部脚本根据服务器负载动态更新这个值,从而实现基于服务器负载的动态压缩策略调整。


通过根据客户端特性调整压缩策略,我们可以为不同的用户提供更加优化的体验,同时也能更好地平衡服务器资源的使用。


4.4 监控和调整压缩性能

监控和调整压缩性能是优化Nginx HTTP压缩的关键步骤。通过持续的监控和适时的调整,我们可以确保压缩策略始终保持最佳状态。

首先,我们需要监控压缩的效果。Nginx提供了一些变量,可以帮助我们了解压缩的情况:

  1. $gzip_ratio:这个变量显示gzip压缩的比率。我们可以将这个信息记录到访问日志中:
log_format compression '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" "$gzip_ratio"';

access_log /var/log/nginx/access.log compression;

通过分析这些日志,我们可以了解压缩的效果,并找出哪些类型的内容可能需要调整压缩策略。

  1. $content_length$body_bytes_sent:这两个变量分别表示原始内容长度和发送的字节数。我们可以使用这两个变量来计算实际的压缩比:
log_format compression_detail '$remote_addr - $remote_user [$time_local] '
                              '"$request" $status $body_bytes_sent '
                              '"$http_referer" "$http_user_agent" '
                              '$content_length $body_bytes_sent';

access_log /var/log/nginx/compression_detail.log compression_detail;

其次,我们需要监控服务器的资源使用情况,特别是CPU使用率。压缩是一个CPU密集型的操作,过度的压缩可能会导致服务器负载过高。我们可以使用系统监控工具如top、htop或更高级的监控系统如Prometheus和Grafana来监控服务器的CPU使用情况。


基于监控结果,我们可以进行以下调整:

  1. 调整压缩级别:如果发现CPU使用率过高,可以考虑降低压缩级别。相反,如果CPU资源充足,可以提高压缩级别以获得更好的压缩效果。
gzip_comp_level 4;  # 降低压缩级别
  1. 调整最小压缩大小:如果发现很多小文件被压缩,但压缩效果不明显,可以提高最小压缩大小。
gzip_min_length 1000;  # 只压缩大于1000字节的内容
  1. 调整压缩类型:根据监控结果,我们可能会发现某些类型的文件压缩效果不佳,可以考虑将这些类型从压缩列表中移除。
gzip_types text/plain text/css application/javascript application/json;
# 移除了一些压缩效果不佳的类型
  1. 使用gzip_static:对于静态文件,如果发现动态压缩消耗了大量CPU资源,可以考虑使用gzip_static模块,预先压缩文件。
gzip_static on;
  1. 考虑使用更高效的压缩算法:如果监控显示gzip压缩效果不够理想,可以考虑使用Brotli等更高效的压缩算法。
brotli on;
brotli_comp_level 4;
brotli_types text/plain text/css application/javascript application/json;


最后,压缩性能的监控和调整应该是一个持续的过程。网站的内容和流量模式可能会随时间变化,因此我们需要定期审查监控数据,并相应地调整压缩策略。同时,在进行任何调整后,都应该密切监控变化对性能的影响,确保调整确实带来了预期的改善。


通过持续的监控和调整,我们可以确保Nginx的HTTP压缩始终保持在最佳状态,既能提供良好的压缩效果,又不会对服务器性能造成过大的负担。


5. HTTP压缩的注意事项

HTTP压缩是一种强大的性能优化技术,但在实际应用中需要注意一些潜在的问题和权衡。本节将详细讨论使用HTTP压缩时需要考虑的几个关键方面。

5.1 CPU使用率与压缩级别的权衡

HTTP压缩是一个计算密集型的过程,特别是在高压缩级别下。虽然更高的压缩级别可以产生更小的文件大小,但也会消耗更多的CPU资源。这种权衡在选择压缩级别时尤为重要。


对于大多数网站来说,中等压缩级别(如gzip的4-6级)通常能够在压缩效果和CPU使用率之间取得良好的平衡。然而,最佳的压缩级别会因服务器硬件、网站流量和内容类型而异。

Nginx中,我们可以通过gzip_comp_level指令来设置压缩级别。例如:

gzip_comp_level 6;


需要注意的是,压缩级别的增加并不总是线性地对应文件大小的减少。从级别6增加到级别9可能只会带来微小的文件大小减少,但会显著增加CPU使用率。因此,建议进行详细的性能测试,找出最适合你特定情况的压缩级别。


对于高流量的网站,可能需要考虑使用硬件加速或专门的压缩服务器来处理压缩任务,以减轻主要Web服务器的负担。

5.2 避免重复压缩

重复压缩不仅会浪费服务器资源,还可能导致文件大小增加而不是减少。在Nginx配置中,我们需要注意避免对已经压缩的内容再次进行压缩。

有几种情况可能导致重复压缩:

  1. 对已经是压缩格式的文件(如jpg、png、zip等)进行压缩。
  2. 在反向代理设置中,后端服务器和Nginx都启用了压缩。
  3. 使用gzip_static模块时,同时启用了动态gzip压缩。

为了避免这些问题,我们可以采取以下措施:

  1. gzip_types指令中排除已压缩的文件类型:
gzip_types text/plain text/css application/javascript application/json;
  1. 在使用反向代理时,可以通过设置gzip_proxied指令来控制对代理请求的压缩行为:
gzip_proxied off;
  1. 当使用gzip_static模块时,可以禁用动态gzip压缩:
gzip off;
gzip_static on;

通过这些配置,我们可以有效避免重复压缩,提高服务器效率。


5.3 特定文件类型的压缩考虑

不同类型的文件对压缩的反应不同。文本文件(如HTML、CSS、JavaScript)通常能够获得很好的压缩效果,而某些二进制文件(如图片、视频)可能已经是压缩格式,再次压缩可能效果不佳甚至可能增加文件大小。

因此,我们需要仔细考虑哪些类型的文件应该被压缩。在Nginx中,我们可以使用gzip_types指令来指定需要压缩的MIME类型:

gzip_types text/plain text/css application/javascript application/json image/svg+xml;

对于大型文件,如视频或大型PDF文件,即使它们是可压缩的,也可能不适合进行实时压缩。这是因为压缩这些文件可能会导致较长的响应时间,影响用户体验。对于这些文件,可以考虑预先压缩或使用其他优化策略,如分片下载或流式传输。

5.4 安全性考虑(BREACH攻击等)

虽然HTTP压缩能够显著提高性能,但它也可能引入一些安全风险,最著名的是BREACH(Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext)攻击。


BREACH攻击利用了压缩算法的特性来推断加密数据的内容。攻击者可以通过观察加密流量的大小变化来猜测响应中的秘密信息,如CSRF令牌。


为了减轻BREACH攻击的风险,可以考虑以下措施:

  1. 对敏感数据禁用压缩。例如,可以在包含敏感信息的特定路径上禁用压缩:
location /sensitive/ {
    gzip off;
}
  1. 使用随机填充来混淆响应大小。这可以通过在应用层面添加随机长度的注释或空白字符来实现。
  2. 分离敏感数据和公共数据,将它们放在不同的响应中。
  3. 使用内容安全策略(CSP)来限制跨站点请求。
  4. 实现诸如每次请求改变CSRF令牌等安全措施。

需要注意的是,完全禁用压缩并不总是一个可行的选择,因为这会显著影响性能。相反,我们需要在安全性和性能之间找到适当的平衡点。


在实施HTTP压缩时,网站管理员和开发人员需要全面考虑这些因素。通过仔细权衡CPU使用率、避免重复压缩、选择适当的文件类型进行压缩,以及采取必要的安全措施,我们可以充分利用HTTP压缩的优势,同时最小化潜在的风险和问题。

6. 测试和验证HTTP压缩

在配置和实施HTTP压缩后,进行全面的测试和验证是确保压缩效果的关键步骤。本节将介绍几种常用的测试和验证HTTP压缩的方法,包括使用浏览器开发者工具、命令行工具以及专门的压缩效果分析工具。

6.1 使用浏览器开发者工具

现代浏览器的开发者工具提供了强大的功能,可以帮助我们轻松地检查和验证HTTP压缩的效果。以下是使用浏览器开发者工具测试HTTP压缩的步骤:

首先,打开你的网站,然后按F12键(或右键选择"检查")打开开发者工具。切换到"网络"(Network)标签页。


在网络标签页中,你可以看到所有的HTTP请求。查找你想要检查的资源,通常是HTML、CSS或JavaScript文件。点击该资源,查看其详细信息。


在响应头(Response Headers)部分,查找"Content-Encoding"字段。如果看到"gzip"、“br”(Brotli)或其他压缩方式,说明该资源已被压缩。


同时,你还可以比较资源的原始大小和传输大小。在资源列表中,通常有"Size"和"Transferred"两列。"Size"表示资源的原始大小,“Transferred"表示实际传输的大小。如果"Transferred"明显小于"Size”,说明压缩生效了。


此外,许多浏览器的开发者工具还提供了禁用缓存的选项。启用这个选项可以确保每次请求都从服务器获取最新的资源,有助于准确测试压缩效果。

6.2 使用命令行工具(curl等)

命令行工具如curl提供了更直接的方式来测试HTTP压缩。以下是使用curl测试HTTP压缩的方法:

首先,我们可以使用curl发送一个不接受压缩的请求:

curl -H "Accept-Encoding: identity" -I http://www.example.com

这个命令会显示响应头,但不下载实际内容。查看"Content-Length"头部可以看到未压缩的资源大小。

然后,我们可以发送一个接受压缩的请求:

curl -H "Accept-Encoding: gzip" -I http://www.example.com

如果服务器支持压缩,你应该能在响应头中看到"Content-Encoding: gzip"。

要查看实际的压缩效果,可以使用以下命令:

curl -H "Accept-Encoding: gzip" --write-out "%{size_download}\n" --output /dev/null --silent http://www.example.com

这个命令会显示下载的字节数,即压缩后的大小。

通过比较这两个大小,我们可以计算出压缩比。

6.3 压缩效果分析工具介绍

除了浏览器开发者工具和命令行工具,还有一些专门的在线工具和软件可以帮助我们分析HTTP压缩的效果。


其中一个流行的在线工具是GTmetrix。这个工具不仅可以测试页面加载速度,还可以检查是否启用了GZIP压缩,并提供详细的压缩效果报告。使用GTmetrix,你只需输入网站URL,它就会自动分析页面并生成报告,包括压缩前后的文件大小、压缩比等信息。


另一个有用的工具是Google的PageSpeed Insights。这个工具也可以检测是否启用了文本压缩,并在其性能报告中提供相关建议。


对于更深入的分析,WebPageTest是一个强大的选择。它提供了详细的瀑布图,显示了每个资源的加载时间和大小,包括压缩前后的大小。WebPageTest还允许你从不同的地理位置和使用不同的网络条件进行测试,这对于全面评估压缩效果非常有帮助。


此外,一些Nginx模块如ngx_http_gzip_static_module提供了压缩统计功能。通过配置Nginx日志格式,我们可以记录每个请求的压缩比,从而进行长期的压缩效果监控和分析。


最后,对于大型网站或应用,使用专业的性能监控工具如New Relic或Datadog可能更为合适。这些工具可以提供实时的性能数据,包括压缩相关的指标,帮助我们持续监控和优化压缩效果。


通过综合使用这些工具和方法,我们可以全面地测试和验证HTTP压缩的效果,确保压缩配置达到预期的性能提升目标。同时,持续的监控和分析也有助于我们及时发现和解决潜在的问题,不断优化网站的性能。


7. 总结

本文全面介绍了Nginx中HTTP压缩的原理、配置方法和优化策略。我们详细讨论了gzip和Brotli压缩的配置,探讨了静态文件与动态内容的压缩策略,以及如何结合缓存使用压缩。同时,我们还介绍了根据客户端特性调整压缩策略的方法,以及如何监控和调整压缩性能。此外,文章还提醒了使用HTTP压缩时需要注意的事项,如CPU使用率与压缩级别的权衡、避免重复压缩、特定文件类型的压缩考虑以及安全性问题等。


通过合理配置和优化Nginx的HTTP压缩,我们可以显著减少数据传输量,提高网站加载速度,改善用户体验。然而,压缩策略的制定需要权衡多个因素,包括服务器性能、网络条件、内容类型等。因此,建议网站管理员根据具体情况进行测试和调整,找到最适合自己网站的压缩配置。同时,持续的监控和优化也是确保压缩效果长期有效的关键。

最后,希望本文对你有所帮助。

F. 参考资料

下面是本文相关参考资料,描述不详细的地方可以从下面的链接中查找更加全面的信息。

编号 文档名称 URL
1 Nginx 官方文档 - ngx_http_gzip_module 模块 http://nginx.org/en/docs/http/ngx_http_gzip_module.html
2 Nginx 官方文档 - ngx_http_gzip_static_module 模块 http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html
3 Nginx 官方文档 - ngx_http_gunzip_module 模块 http://nginx.org/en/docs/http/ngx_http_gunzip_module.html
4 Nginx 官方文档 - ngx_http_proxy_module 模块 http://nginx.org/en/docs/http/ngx_http_proxy_module.html
5 HTTP/1.1 协议规范 - RFC 2616 https://tools.ietf.org/html/rfc2616
6 HTTP/1.1 消息语法与路由 - RFC 7230 https://tools.ietf.org/html/rfc7230
7 HTTP/1.1 语义与内容 - RFC 7231 https://tools.ietf.org/html/rfc7231
8 HTTP/1.1 条件请求 - RFC 7232 https://tools.ietf.org/html/rfc7232
9 Brotli 压缩算法规范 - RFC 7932 https://tools.ietf.org/html/rfc7932
12 MDN Web Docs - 内容安全策略 (CSP) https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
13 W3C - Content Security Policy Level 3 https://www.w3.org/TR/CSP3/
14 Nginx 官方文档 - ngx_http_headers_module 模块 http://nginx.org/en/docs/http/ngx_http_headers_module.html
15 Nginx 官方文档 - ngx_http_ssl_module 模块 http://nginx.org/en/docs/http/ngx_http_ssl_module.html
16 HTTP 缓存 - RFC 7234 https://tools.ietf.org/html/rfc7234
17 Nginx 官方文档 - ngx_http_upstream_module 模块 http://nginx.org/en/docs/http/ngx_http_upstream_module.html
19 HTTP/2 规范 - RFC 7540 https://tools.ietf.org/html/rfc7540
20 Nginx 官方文档 - ngx_http_v2_module 模块 http://nginx.org/en/docs/http/ngx_http_v2_module.html
目录
相关文章
|
28天前
|
JSON 移动开发 监控
快速上手|HTTP 接口功能自动化测试
HTTP接口功能测试对于确保Web应用和H5应用的数据正确性至关重要。这类测试主要针对后台HTTP接口,通过构造不同参数输入值并获取JSON格式的输出结果来进行验证。HTTP协议基于TCP连接,包括请求与响应模式。请求由请求行、消息报头和请求正文组成,响应则包含状态行、消息报头及响应正文。常用的请求方法有GET、POST等,而响应状态码如2xx代表成功。测试过程使用Python语言和pycurl模块调用接口,并通过断言机制比对实际与预期结果,确保功能正确性。
117 3
快速上手|HTTP 接口功能自动化测试
|
9天前
|
负载均衡 安全 应用服务中间件
nginx的强大功能和如何使用?
nginx的强大功能和如何使用?
24 2
|
1天前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
6 0
|
2月前
|
应用服务中间件 网络安全 nginx
运维专题.Docker+Nginx服务器的SSL证书安装
运维专题.Docker+Nginx服务器的SSL证书安装
60 3
|
2月前
|
缓存 应用服务中间件 API
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇(三)
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇(三)
34 3
|
2月前
|
缓存 安全 应用服务中间件
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇(二)
Nginx七层(应用层)反向代理:HTTP反向代理proxy_pass篇(二)
31 1
|
2月前
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
40 0
Ueditor——请求后台配置项http错误,上传功能将不能正常使用
|
2月前
|
缓存 负载均衡 安全
介绍一下Nginx的反向代理功能吧
【8月更文挑战第22天】介绍一下Nginx的反向代理功能吧
44 0
|
2月前
|
缓存 安全 应用服务中间件
Nginx的反向代理功能有哪些应用场景呢
【8月更文挑战第22天】Nginx的反向代理功能有哪些应用场景呢
127 0
|
2月前
|
缓存 负载均衡 监控
Nginx的反向代理功能如何实现的呢
【8月更文挑战第22天】Nginx的反向代理功能如何实现的呢
25 0

热门文章

最新文章