一般的大型网站都会将图片存放在专门的服务器,这样可以很好的提升网站的性能。比较简单的方式是采用云厂商提供的服务,比如七牛云、又拍云等。今天要介绍的是一款开源的实现方案zing。
zimg是一套国人针对图片处理服务器而设计开发的开源程序,目的是解决图片服务中如下三个问题:
以上三个问题,其实也是相互制约和钳制的,比如要想降低流量,就需要大量的计算,导致请求处理时间延长,系统单位时间内的处理能力下降;再比如为了存储更多的图片,必然要在查找上消耗资源,同样也会降低处理能力。所以,图片服务虽然看起来业务简单,实际做起来也不是一件小事。
zimg的定位:
以下是zimg支持的功能:
想要在展现图片这件事情上有最好的表现,首先需要从整体业务中将图片服务部分分离出来。使用单独的域名和建立独立的图片服务器有很多好处,比如:
图片服务器被独立出来之后,会面临两个选择,主流的方案是前端采用Nginx,中间是PHP或者自己开发的模块,后端是物理存储;比较特别一些的,比如Facebook,他们把图片的请求处理和存储合并成一体,叫做haystack,这样做的好处是,haystack只会处理与图片相关的请求,剥离了普通http服务器繁杂的功能,更加轻量高效,同时也使部署和运维难度降低。zimg采用的是与Facebook相似的策略,将图片处理的大权收归自己所有,绝大部分事情都由自己处理,除非特别必要,最小程度地引入第三方模块。
为了极致的性能表现,zimg全部采用C语言开发,总体上分为三个层次,前端http处理层,中间图片处理层和后端的存储层。下图为zimg架构设计图:
为了避免数据库带来的性能瓶颈,zimg不引入结构化数据库,图片的查找全部采用哈希来解决。事实上图片服务器的设计,是一个在I/O与CPU运算之间的博弈过程,最好的策略当然是继续拆:CPU敏感的http和图片处理层部署于运算能力更强的机器上,内存敏感的cache层部署于内存更大的机器上,I/O敏感的物理存储层则放在配备SSD的机器上,但并不是所有人都能负担得起这么奢侈的配置。zimg折中成本和业务需求,目前只需要部署在一台服务器上。由于不同服务器硬件不同,I/O和CPU运算速度差异很大,很难一棒子定死。zimg所选择的思路是,尽量减少I/O,将压力放在CPU上,事实证明这样的思路基本没错,在硬盘性能很差的机器上效果更加明显;即使以后SSD全面普及,CPU的运算能力也会相应提升,总体来说zimg的方案也不会太失衡。
虽然zimg在二进制实体上没有分模块,上面已经提到了原因,现阶段面向中小型的服务,单机部署即可,但是代码上是分离的。
main.c是程序的入口,主要功能是处理启动参数,部分参数功能如下:
zhttpd.c是解析http请求的部分,分为GET和POST两大部分,GET请求会根据请求的URL参数去寻找图片并转给图片处理层处理,最后将结果返回给用户;POST接收上传请求然后将图片存入计算好的路径中。为了实现zimg的总体设计愿景,zhttpd承担了很大部分的工作,也有一些关键点,下面捡重点的说一下:
zimg.c是调用imagemagick处理图片的部分,现阶段zimg服务于存储量在TB级别的单机图片服务器,所以存储路径采用2级子目录的方案。由于Linux同目录下的子目录数最好不要超过2000个,再加上MD5的值本身就是32位十六进制数,zimg就采取了一种非常取巧的方式:根据MD5的前六位进行哈希,1-3位转换为十六进制数后除以4,范围正好落在1024以内,以这个数作为第一级子目录;4-6位同样处理,作为第二级子目录;二级子目录下是以MD5命名的文件夹,每个MD5文件夹内存储图片的原图和其他根据需要存储的版本,假设一个图片平均占用空间200KB,一台zimg服务器支持的总容量就可以计算出来了:1024 * 1024 * 1024 * 200KB = 200TB
除了路径规划,zimg另一大功能就是压缩图片。从用户角度来说,zimg返回来的图片只要看起来跟原图差不多就行了,如果确实需要原图,也可以通过将所有参数置空的方式来获得。基于这样的条件,zimg.c对于所有转换的图片都进行了压缩,压缩之后肉眼几乎无法分辨,但是体积将减少67.05%。具体的处理方式为:
经过这样的处理之后可以很大程度的减少流量,实现设计目标。
zcache.c是引入memcached缓存的部分,引入缓存是很重要的,尤其是图片量级上升之后。在zimg中缓存被作为一个很重要的功能,几乎所有zimg.c中的查找部分都会先去检查缓存是否存在。比如:我想要a(代表某MD5)图片裁剪为100*100之后再灰白化的版本,那么过程是先去找a&w=100&h=100&g=1的缓存是否存在,不存在的话去找这个文件是否存在(这个请求所对应的文件名为 a/100*100pg),还不存在就去找这个分辨率的彩色图缓存是否存在,若依然不存在就去找彩色图文件是否存在(对应的文件名为 a/100*100p),若还是没有,那就去查询原图的缓,原图缓存依然未命中的话,只能打开原图文件了,然后开始裁剪,灰白化,然后返回给用户并存入缓存中。
可以看出,上面过程中如果某个环节命中缓存,就会相应地减少I/O或图片处理的运算次数。众所周知内存和硬盘的读写速度差距是巨大的,那么这样的设计对于热点图片抗压将会十分重要。
除了上述核心代码以外就是一些支持性的代码了,比如log部分,md5计算部分,util部分等。
安装依赖库:
sudo yum install -y wget openssl-devel cmake libevent-devel libjpeg-devel giflib-devel libpng-devel libwebp-devel ImageMagick-devel libmemcached-devel sudo yum install -y glibc-headers gcc-c++ sudo yum install -y build-essential nasm
安装依赖:
# openssl mkdir /usr/local/zimg/openssl cd /usr/local/zimg/openssl wget http://www.openssl.org/source/openssl-1.0.1i.tar.gz tar zxvf openssl-1.0.1i.tar.gz cd openssl-1.0.1i ./config shared --prefix=/usr/local --openssldir=/usr/ssl make && make install # cmake mkdir /usr/local/zimg/cmake cd /usr/local/zimg/cmake wget http://www.cmake.org/files/v3.0/cmake-3.0.1.tar.gz tar xzvf cmake-3.0.1.tar.gz cd cmake-3.0.1 ./bootstrap --prefix=/usr/local make && make install # libevent mkdir /usr/local/zimg/libevent cd /usr/local/zimg/libevent wget http://cloud.github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz tar zxvf libevent-2.0.21-stable.tar.gz cd libevent-2.0.21-stable ./configure --prefix=/usr/local make && make install # libjpeg-turbo mkdir /usr/local/zimg/libjpeg-turbo cd /usr/local/zimg/libjpeg-turbo wget https://downloads.sourceforge.net/project/libjpeg-turbo/1.3.1/libjpeg-turbo-1.3.1.tar.gz tar zxvf libjpeg-turbo-1.3.1.tar.gz cd libjpeg-turbo-1.3.1 ./configure --prefix=/usr/local --with-jpeg8 make && make install # webp mkdir /usr/local/zimg/webp cd /usr/local/zimg/ wget http://downloads.webmproject.org/releases/webp/libwebp-0.4.1.tar.gz tar zxvf libwebp-0.4.1.tar.gz cd libwebp-0.4.1 ./configure make sudo make install # jpegsrc mkdir /usr/local/zimg/jpegsrc cd /usr/local/zimg/ wget http://www.ijg.org/files/jpegsrc.v8b.tar.gz tar -xf jpegsrc.v8b.tar.gz cd jpeg-8b ./configure --prefix=/usr/local --enable-shared --enable-static make && make install # imageMagic mkdir /usr/local/zimg/imageMagick cd /usr/local/zimg/ wget http://www.imagemagick.org/download/ImageMagick.tar.gz tar zxvf ImageMagick.tar.gz cd ImageMagick-6.9.1-10 ./configure --prefix=/usr/local make && make install # libmemcached wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz tar zxvf libmemcached-1.0.18.tar.gz cd libmemcached-1.0.18 ./configure -prefix=/usr/local make && make install
可选的插件:
# memcached wget http://www.memcached.org/files/memcached-1.4.19.tar.gz tar zxvf memcached-1.4.19.tar.gz cd memcached-1.4.19 ./configure --prefix=/usr/local make make install # beansdb git clone https://github.com/douban/beansdb cd beansdb ./configure --prefix=/usr/local make # benseye git clone [email protected]:douban/beanseye.git cd beanseye make # SSDB wget --no-check-certificate https://github.com/ideawu/ssdb/archive/master.zip unzip master cd ssdb-master make # twemproxy git clone [email protected]:twitter/twemproxy.git cd twemproxy autoreconf -fvi ./configure --enable-debug=log make src/nutcracker -h
构建zimg
cd /usr/local #git clone https://github.com/buaazp/zimg -b master --depth=1 cd zimg make
安装成功后:
cd /usr/local/zimg/bin ./zimg conf/zimg.lua
打开http://localhost:4869看是否安装成功。
如果嫌手动安装太麻烦,就直接使用docker镜像
# 拉取zimg镜像 $ docker pull iknow0612/zimg # 启动zimg容器 $ docker run -it -d -p 4869:4869 -v /data/zimg/:/zimg/bin/img --name my_zimg iknow0612/zimg sh app.sh
可以自己基于zimg再封装图片服务。
参考链接: