目的:
减少图片存储数量,节省存储空间(现
mogilefs
存储了近
8
千万张图片,其中近一半为缩略图)。
存储系统中只存储原图,缩略图和其它尺寸的图根据
url
地址中的参数自动生成。
如:原图
http://cn.gcimg.net/gcproduct/mog_day_111015/11101511424d825ff432904758.jpg
缩略图:
http://cn.gcimg.net/gcproduct/mog_day_111015/11101511424d825ff432904758.jpg-300
http://cn.gcimg.net/gcproduct/mog_day_111015/11101511424d825ff432904758.jpg-300,250
在原图
url
后面加上尺寸信息,当只有一个参数时,宽固定,高按比例调节
当有两个参数时,分别为宽,高的尺寸。
要求
:
1
,能够快速处理
2
,能够根据
url
中的尺寸参数进行相应处理
系统的处理流程:
Client
|
Squid
|
Nginx
|gearmam
Python
使用到的技术:
Squid nginx php gearman python
Nginx rewrite
的写法:
upstream image_resize {
server 192.168.1.X;
}
########
在
location
中对
url
进行判断,符合规则的
url
进行重写,代理到后端去执行,因为想地址重写后地址栏中
url
不变,因此使用了
proxy_pass
。
if ($request_uri ~* "^/([a-z0-9./_]+)-([0-9]+),([0-9]+)$") {
rewrite "^/([a-z0-9./_]+)-([0-9]+),([0-9]+)$" /index.php?file=$1&x=$2&y=$3 break;
proxy_pass http: //image_resize;
}
if ($request_uri ~* "^/([a-z0-9./_]+)-([0-9]+)") {
rewrite "^/([a-z0-9./_]+)-([0-9]+)" /index.php?file=$1&x=$2 break;
proxy_pass http: //image_resize;
}
PHP
程序功能及代码:
PHP
接收
url
的参数,通过
gearman
发送给后端
python
处理,之后把处理的结果以图片形式展示出来
代码如下:
<?php
header('Content-type: image/jpeg');
$img_file=$_GET['file'];
$url= "http://cn.gcimg.net/".$img_file;
$sizex=$_GET['x'];
$sizey=isset($_GET['y'])?$_GET['y']:"-1";
$data=$url.",".$sizex.",".$sizey;
$client= new GearmanClient();
$client->addServer("192.168.1.x ",4730);//job 服务器地址
$image=$client->do('liguxk',$data);
//输出图片
echo $image;
?>
Python
图片处理脚本
#!/usr/bin/env python
'''
resize image size from gearman
write by lgq @liguxk
'''
import gearman
import urllib
from PIL import Image
from cStringIO import StringIO
class CustomGearmanWorker(gearman.GearmanWorker):
def on_job_execute(self, current_job):
return super(CustomGearmanWorker, self).on_job_execute(current_job)
def resizeimg(gearman_worker,job):
img_url,size_x,size_y=job.data.split(',')
size_x= int(size_x)
size_y= int(size_y)
sock=urllib.urlopen(img_url)
old_img_data=sock.read()
sock.close()
old_img=Image.open(StringIO(old_img_data))
old_x,old_y=old_img.size
if old_img.mode !='RGBA':
img_format='JPEG'
else:
img_format='PNG'
new_img=StringIO()
if size_y == -1:
imgswap=old_img.resize((size_x,(old_y*size_x)/old_x),Image.ANTIALIAS)
else:
imgswap=old_img.resize((size_x,size_y),Image.ANTIALIAS)
imgswap.save(new_img,img_format,quality=60)
return new_img.getvalue()
def main():
new_worker=CustomGearmanWorker(['192.168.1.x:4730','192.168.1.x:4730'])
new_worker.register_task('liguxk',resizeimg)
new_worker.work()
if __name__=='__main__':
while [1]:
main()
squid
命中率:
此系统中最前端为
squid
缓存,命中率在
80%
(见下图),因此透过
squid,
需要后端调度的本身就不多,这其中需要生成的图片又不多,而
worker
可以开多个,因此可以满足在线生成的需求。
压力测试报告:
左侧的为小图存储在mogilefs中的情况,右侧为使用实时处理的测试数据。
差别大的一个重要原因是因为通过处理的图片比原来的缩略图大小小了很多
李国强
2011-12-29