从七牛上线的时候就开始使用七牛云存储的服务,对于其中的图片处理一直比较好奇,只需要简单的在图片的访问链接上加上参数,就可以按照定义的功能,得到裁剪或者处理好的图片。
对于实现的机制,也不能说是完全没有概念,只是从来没有认真的思考或者尝试着动手实现一下。所以一直只是一个当作缩放工具来用的普通用户;最近正好看到一个使用nginx和libgb实现的图片处理服务,感觉非常简单就可以搭建,果断尝试了之后,确实get了一项很实用的技能或者说是工具。
运行原理和机制
实现一个图片处理服务器本身如果不去自己实现web服务器和图片处理的核心程序的话,只是以使用功能为目的的话,图片处理功能更多在于技术选型和运维。定义好资源访问的路由规则和调用图片处理的语法之后,简单的运行原理应该包含以下步骤:
- web服务器将资源请求转发给有处理能力并且已经注册的应用服务器或者调用本地程序;
- 应用服务器(例如PHP)根据路由规则,和应用程序本身的设计,定位到路由对应的图片二进制文件;
3 根据路由,或者其他http header信息,解析要对图片进行的解析操作; - 应用服务器自己实现,或者调用其他的图片处理库,或者调用其他程序(例如ImageMagick),对二进制文件进行处理,获得处理好的图片;
- 将图片按照http协议,返回请求的客户端。
自己设计实现对ImageMagick、GD的封装,或者是尝试自己编写处理图片的程序,都是很有趣的事情,应该找机会亲自动手实践。
解决方案
最近偶然看到的一个方案是,使用nginx提供的nginx-module-image-filter,nginx的扩展模块,就可以提供最基础的图片裁剪服务器,简单了解之后,马上着手使用docker开始搭建nginx图片处理服务器。
安装nginx,并开启image-filter模块
本例中使用centos安装nginx,要使用image-filter模块,首先需要安装gd,实际上gd是真正处理图片等程序,使用yum安装yum install -y gd-devel
。
参看nginx的官方文档之后,知道image-filter这个module默认不会自己编译到安装包中的,所以需要自己手动安装,下载nginx源码,解压缩之后进入目录,执行./configure --prefix=/usr/local/nginx --with-http_image_filter_module
,然后make编译。
编译成功之后curl http://localhost:8080/
,检查安装是否成功。
下面是完整的Dockerfile文件,为了提高下载速度,使用的是时速云提供的centos镜像。
FROM index.tenxcloud.com/tenxcloud/docker-centos
#FROM centos
RUN yum install -y gd-devel wget \
&& yum -y install gcc gcc-c++ kernel-devel make \
&& wget http://nginx.org/download/nginx-1.11.7.tar.gz \
&& tar -xzvf nginx-1.11.7.tar.gz \
&& wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.39.tar.gz \
&& tar -xzvf pcre-8.39.tar.gz \
&& cd nginx-1.11.7 \
&& ./configure --prefix=/usr/local/nginx --with-http_image_filter_module --with-pcre=../pcre-8.39 \
&& make \
&& make install
ENV PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/nginx/sbin
WORKDIR /var/www
EXPOSE 80 443
CMD ["nginx", "-g", "daemon off;"]
nginx配置,启用image filter
安装完nginx之后,直接设置image filter的规则就可以使用图片处理功能。
location /img/ {
proxy_pass http://backend;
image_filter resize 150 100;
image_filter rotate 90;
error_page 415 = /empty;
}
location = /empty {
empty_gif;
}
通过设置proxy_pass
,我们要对某个网站上的图片进行裁剪,只需要将代理设置到指向该网站就可以了。
image_filter resize 150 100;
就是重新调整图片的尺寸。
image_filter off;
配置可以关闭image filter。
通过结合nginx的解析规则,我们就可以根据url链接的参数,动态的制定要缩放图片的大小。
location ~* (.*\.(jpg|gif|png))!/w/(.*)/h/(.*)$ {
set $width $3;
set $height $4;
rewrite "(.*\.(jpg|gif|png))(.*)$" $1;
}
location ~* /static/.*\.(jpg|gif|png)$ {
proxy_pass http://www.liuwill.com;
image_filter resize $width $height;
}
配置完成之后,调用nginx -s reload
加载新的配置文件,然后输入链接http://localhost/static/image_url.png/w/100/h/100
,查看效果。
详细说明可以参看nginx提供的image filter官方文档。
github地址:https://github.com/liuwill-projects/docker-nginx-img