项目中需要使用到缩略图功能,对比下来,使用nginx http_image_filter模块是最为快捷的方式,在此记录
nginx部署
image_filter模块依赖GD库,首先进行安装:
然后进行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