0%

nginx实现图片缩略图

项目中需要使用到缩略图功能,对比下来,使用nginx http_image_filter模块是最为快捷的方式,在此记录

nginx部署

image_filter模块依赖GD库,首先进行安装:

1
yum -y install gd-devel

然后进行nginx部署,可参考此脚本,注意需要在编译时configure时使用’–with-http_image_filter_module’引入http_image_filter模块

配置http_image_filter返回压缩图

image_filter在location块内使用,支持以下参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
image_filter <size>; // 以json的方式输出图片格式信息
image_filter rotate 90 | 180 | 270; // 图片逆时针旋转指定度数,该度数只能是90, 180, 270
image_filter resize <width> <height>; // 缩小图片到指定的规格,如果想让一个维度缩放,另外一个维度等比例缩放,则另外维度参数值为'-'.如果配合rotate指令使用,那么执行顺序是先缩放,后旋转
image_filter crop <width> <height>; // 按比例将图片缩小到较大的一边,并裁剪另一边多余的边缘
image_filter test; // 确保图片格式为jpeg,gif,png,webp等格式,否则返回415错误(Unsupported Media Type)


image_filter_buffer 10M; // 默认1M。设置用于读取图片的缓冲区的最大大小。当超过指定大小时,服务器返回 415 错误状态码(不支持的媒体类型)
image_filter_jpeg_quality 1~100; // 默认75。设置 JPEG 图片的转换质量。可接受的值范围在 1 到 100 之间。较小的值意味着较低的图片质量和较少的数据传输。最大的推荐值是 95
image_filter_webp_quality 1~100; // 默认80。设置 WebP 图片的转换质量。可接受的值在 1 到 100 之间。较小的值意味着较低的图片质量和较少的数据传输
image_filter_sharpen percent; // 默认0。增加最终图像的清晰度。锐度百分比可以超过 100。零值将禁用锐化
image_filter_transparency on|off; // 默认on。定义在使用调色板指定的颜色转换 GIF 图像或 PNG 图像时是否保留透明度。透明度的丧失使图像的质量更好的。PNG 中的 alpha 通道透明度始终保留
image_filter_interlace on|off; // 默认off。如果启用此选项,图片最后将被逐行扫描。对于 JPEG,图片最终将采用逐行JPEG格式,即从上到下扫描图片,显示时一行一行加载显示出来

以nginx代理静态文件为例,对图片类型(jpg|jpeg|gif|png)的请求,如果携带了width/height参数,那么将按照入参进行压缩处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 # 缩略图
location ~* /blogexamplebucket/(.+)\.(jpg|jpeg|gif|png) {
# 设置变量width默认为'-'
set $width -;
# 读取参数携带的width值
if ($arg_width) {
set $width $arg_width;
}

# 希望等比例缩放,这里只使用width参数,将宽度缩小到width,高度将等比例缩小
image_filter resize $width -;
image_filter_jpeg_quality 75;
# 图片缓存区最大20M
image_filter_buffer 20M;

# 代理服务器文件
# 按照location的模式匹配,$1.$2 为请求的文件名
proxy_pass http://your-file-server/blogexamplebucket/$1.$2;
# 指定缓存expires时长永不过期
expires max;
}

# 代理 oss blogexamplebucket 下文件
location /blogexamplebucket/ {
# 代理服务器文件
proxy_pass http://your-file-server;
expires max;
}

如果原始图片url为:http://blog-oss.connorma.cn/blogexamplebucket/hutao.jpg

原始图片

希望使用缩略图,那么可以添加width参数:http://blog-oss.connorma.cn/blogexamplebucket/hutao.jpg?width=100

缩略图

缩略图缓存

在以上示例中代理静态文件时设置了expires为max,使浏览器使用缓存,但是nginx侧性能考虑,每次请求时处理图片,将会带来一定的性能压力——jmeter跑一下请求缩略图,轻松就能把nginx机器的CPU打满

因此,考虑nginx使用proxy_store为缩略图添加磁盘缓存,一方面减少了图片处理的操作,另一方面通过nginx本地缓存加快客户端的响应速度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 缩略图
location ~* /blogexamplebucket/(.+)\.(jpg|jpeg|gif|png) {
# 设置变量width默认为'-'
set $width -;
# 读取参数携带的width值
if ($arg_width) {
set $width $arg_width;
}

# 希望等比例缩放,这里只使用width参数,将宽度缩小到width,高度将等比例缩小
image_filter resize $width -;
image_filter_jpeg_quality 75;
# 图片缓存区最大20M
image_filter_buffer 20M;

# 代理服务器文件
# 按照location的模式匹配,$1.$2 为请求的文件名
proxy_pass http://your-file-server/blogexamplebucket/$1.$2;
# 指定缓存expires时长永不过期
expires max;

# 开启本地磁盘缓存
proxy_store /data/nginx_cache/images/resize/$1_$2_$width;
# 缓存路径读写权限
proxy_store_access user:rw group:rw all:r;
# 缓存文件路径
proxy_temp_path /data/nginx_cache/images/resize;
}

需要注意,在使用磁盘缓存时,nginx会将文件首先写入临时目录proxy_temp_path下,然后移动到proxy_store指定的路径下(如果未指定,那么会保存到root或alias指定的路径下),因此为了减少IO压力,建议proxy_temp_path和proxy_temp_path使用同一FS下目录

proxy_store使用磁盘缓存文件,但是并不原生的支持缓存过期清理,缓存文件将占用大量磁盘空间;proxy_cache的缓存功能在这方面更完备,但是只支持内存的写入,不适合此类数量多、体积相对大的静态文件的情况。如何处理?可以集成lua模块(或使用openResty)嵌入脚本来清理文件,或者通过服务器内的crontab任务释放缓存空间等

不难想到,proxy_store按照示例的配置,就实现了回源。如果你在多地有机器部署了nginx,通过proxy_store,配合清理缓存文件的策略,就能实现一个基本的CDN