如何在Nginx上实现即时图像压缩?

12

问题:

我使用 CentOS 系统。我想要优化网络服务(不调整大小)并压缩静态图像资源(jpg/gif/png),同时保留原始数据。

例如,当请求访问 http://server-A/images/image.jpg 时,会实时压缩图片(并缓存),这是通过事先配置的有损/无损参数实现的。

我想要实现类似 Cloudflare 中“Polish”功能的效果,但在自己的 Web 服务器上实现。

有哪些工具可用于此集成?

另一种思路:

是否可以监视路径/originals/以检测是否有任何更改,如果有,则进行离线图像压缩并将其输出到/compressed/路径中?

2个回答

1
我认为您可以通过以下几种方式实现。
选项1:使用Apache的PageSpeed模块(也称为mod_pagespeed):
PageSpeed模块优化图像,使它们的大小最小化,从而减少它们的加载时间。它们移除不可见的图像信息并应用高效的压缩技术。这可以节省50%或更多的数据。
使用PageSpeed模块,您可以专注于网站的内容,知道您的访问者将在使用最小带宽的同时,以最佳格式和尺寸接收图像。

https://www.modpagespeed.com/doc/filter-image-optimize

安装信息可以在官方文档中找到。

选项 #2:使用自定义图像压缩服务,并将图像请求反向代理到该服务。

如果 Apache PageSpeed 模块无法正常工作,您可以设置一个反向代理缓存。Nginx 首先检查缓存,获取MISS,然后从压缩服务内部请求图像,返回压缩的图像,同时将其保存到磁盘上,以便下一次请求会HIT缓存。

详细设置如下。

首先,您需要创建一个location { ... }块,其中包含nginx在获取原始图像请求时匹配的正则表达式。

server { 
  # your standard nginx server stuff here, then:

  # when reverse proxying, nginx needs a DNS resovler defined
  # you may be able to skip this if you use an IP address instead of
  # example.com below.
  resolver               1.1.1.1 1.0.0.1 valid=300s;
  resolver_timeout       2s;
  
  location ~ ^/your/image/originals/(.*) {
       proxy_ssl_server_name on;
       proxy_pass https://www.example.com/your-custom-compression-service/$1;

       # plus we need to define some extra stuff for caching; which I put
       # in another file for modularity or reuse if later needed.
       include "/absolute/path/to/nginx-includes/location-cache.config";
    }
}

在您的“location-cache.config”文件中(可以命名为任何名称),您需要为缓存起一个名字,我们称其为“images_cache”:
proxy_cache            images_cache;
proxy_cache_valid      200 1d; # Cache HTTP 200 responses for up to 1 day.

# Keep using a stale cache during the short time it takes to refresh it (so
# we don't get a bunch of requests through # at the instant the cache becomes
# invalid).
# See: https://www.nginx.com/blog/mitigating-thundering-herd-problem-pbs-nginx/
proxy_cache_use_stale  error timeout invalid_header updating
                        http_500 http_502 http_503 http_504;

# "Allows starting a background subrequest to update an expired cache item,
# while a stale cached response is returned to the client."
# See: https://www.nginx.com/blog/nginx-caching-guide/#proxy_cache_background_update
proxy_cache_background_update on;

最后,在http {...}块中,您设置了我们上面命名的“images_cache”缓存:
proxy_cache_path
    /tmp/nginx-cache

    # Use a two-level cache directory structure, because the default
    # (single directory) is said to lead to potential performance issues.
    # Why that is default then... your guess is as good as mine.
    levels=1:2

    # A 10MB zone keeps ~80,000 keys in memory. This helps quickly determine
    # if a request is a HIT or a MISS without having to go to disk.
    keys_zone=images_cache:10m

    # If something hasn't been used in quite a while (60 days), evict it.
    inactive=60d

    # Limit on total size of all cached files.
    max_size=100m;

在您的自定义图像压缩服务(如上例example.com)中,您可能需要编写一个小型服务(使用Node、Python、Rust或其他语言),该服务获取传递给它的URL,从磁盘位置(例如.../images/originals)获取URL,压缩并返回它。我将留给读者自行处理 :-)

-1

.jpg 图像已经是一种压缩的二进制格式。在这里,nginx 无法为您做任何事情。

如果我正确理解了您的问题,您想要在保持相同质量的情况下减小图像的大小,这需要更好的压缩算法或质量较低的图像。

如果我正确理解了 cloudflares 的方法,对于 lossless,他们只是剥离图像的元数据(Exif),您也可以实现这一点,但不是通过 nginx,而是通过您的 asset 管道。

第二种方法,lossy,实现了更好的图像压缩算法,这也可以部署在您的 asset 管道中。请参见 tinypng 等内容。

希望能有所帮助, G


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接