OpenResty (nginx+lua)+ceph+GraphicsMagick 动态生成处理图片

很久没有更新blog,一方面换了新工作,另一方面是懒。

很早就看见七牛,又拍云,新浪,阿里的图片处理了,当时觉得好厉害,没去研究里面的技术,后来@开发者头条 上有人实现了个简单的,基于openresty,openresty是我很早不知道的一个项目,可惜一直没入门lua. 这次新公司恰好有需要这个需求,本来是叫我这个运维找点开源的程序解决就ok,但是我这个“爱学习”的,怎么能放弃这个锻炼的机会。当然整 个项目我参考开源项目zimg

当然网上也有基于openresty(ngx_lua) 开源的项目,然而,我还是坚定要的造轮子。

最后一般公司除了特殊需求,还是建议使用七牛、又拍云提供的云存储及数据处理服务,解决图片的处理、存储、多节点访问速度的问题,这种方式优点是方案成熟,相应的有一定费用和开发工作省了。

# 介绍

# zimg

@招牌疯子开发。zimg的性能和扩展性不错,用c写的,大神,可惜版本也是没有大的更新,我这个项目架构就是参考他的设计。

# openresty

openresty 简直是高性能,异步非阻塞,6到不行,如果你只是觉得春哥(agentzh)只是打包工作,你还是too young, too native.

这东西一定要火,must be.

# graphicsmagick

GraphicsMagick是从 ImageMagick 分支出来,号称图像处理领域的瑞士军刀。 短小精悍的代码却提供了一个鲁棒、高效的工具和库集合,来处理图像的读取、写入和操作,支持超过88中图像格式,包括重要的DPX、GIF、JPEG、JPEG-2000、PNG、PDF、PNM和TIFF。 关键还提供了A simple Lua wrapper to graphicsmagick.

# ceph

一个 Linux PB 级分布式文件系统,当初我看到几个分布式的存储方案,tfs很久不更新了,sweeddfs简单一点,但是稳定性还是欠佳,并且还是有一些小问题。而ceph强大的强一制性,和自动修复能力,一下子就确实他了。

# 架构设计

# 访问流程

  1. 解析参数,并判断是否正确
  2. 从redis获取数据,否则从临时文件返回,并重新缓存到redis
  3. 若临时文件不存在,则使用原文件graphicsmagick生成新图片,保存并缓存。
  4. 若为ceph模式,则直接从ceph gateway获取,不会生成临时文件。

# 文件目录设计

这里借鉴 zimg 的方案,存储路径采用2级子目录的方案。由于 Linux 同目录下的子目录数最好不要超过2000个,再加上 MD5 的值本身就是32位十六进制数,zimg就采取了一种非常取巧的方式:根据 MD5 的前六位进行哈希,1-3位转换为十六进制数后除以4,范围正好落在1024以内,以这个数作为第一级子目录;4-6位同样处理,作为第二级子目录;二级子目录下是以 MD5 命名的文件夹,每个MD5文件夹内存储图片的原图和其他根据需要存储的版本.

├── 1024
│   └── 804
│       └── fffc929444a9fb7eb754217cfd7b0d58
│           ├── default
│           ├── w100_h100_g1_xnil_ynil_rnil_pnil_qnil_fnil
│           ├── w100_hnil_g1_xnil_ynil_rnil_pnil_qnil_fnil
│           ├── w100_hnil_gnil_xnil_ynil_rnil_pnil_qnil_fnil
│           └── wnil_hnil_gnil_xnil_ynil_rnil_pnil_qnil_fnil
├── 432
│   └── 471
│       └── 6c075eeaf073e39e280075450afb1cd0
│           └── default
└── 538
    └── 429
        └── 8686b4f53b5a392b90b9c0b35eaf9a11
            └── default

当然ceph我采用对象存储(文件系统还不稳定,官方不推荐使用),就不存在目录结构了。

# 图片处理

通过url参数还生成对应的图像

url: ?w=300&h=300&g=1&x=0&y=0&r=45&q=85&f=jpeg
(? + 长 + 宽 + 灰白化 + x + y + 旋转角度 + 压缩比 + 转换格式)
w: 宽
h: 高
g: 黑白
r: 旋转
q: 压缩比
f: 格式

# 上传图片

因为路径信赖图片的 md5 生成,所以这里我用百度前端开源的image-upload模块,上传时带上图片的 md5 信息。

# 安装

# GraphicsMagick OpenResty

sudo apt-get install GraphicsMagick libgraphicsmagick1-dev

or 

yum install GraphicsMagick GraphicsMagick-devel -y

# openresty
tar xvf ngx_openresty-VERSION.tar.gz
cd ngx_openresty-VERSION/
./configure
make
make install

# CMake-based LuaJIT + Luarocks

git clone https://github.com/torch/luajit-rocks.git
cd luajit-rocks
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/your/prefix -DWITH_LUAJIT21=ON

last

sudo luarocks install graphicsmagick
sudo luarocks install lua-resty-hmac

cd /usr/local/openresty/nginx/conf
mkdir conf.d

add "include conf.d/*.conf;" into nginx.conf

# last, in ngx-lua_images folder.

bash deploy.sh

# and add images folder, change it at config.lua if you need.

mkdir /home/files/images/
chown -R {nginx_user} /home/fiels/images

# 上传图片

http://localhost:8000/static/image-upload/ 

上传成功。

如果没有错误,就可以访问了。

http://localhost:8000/fffc929444a9fb7eb754217cfd7b0d58?w=500&h=500&g=1&x=0&y=0&r=45&q=75&f=jpeg
http://localhost:8000/get_info?md5=fffc929444a9fb7eb754217cfd7b0d58

# ceph

  1. 安装:略

  2. configure:

    • 修改./vendor/cephs3.lua的配置文件。
    • 修改confi.json的ceph_mode为true。
    • 删除nginx.conf的location /upload 段。
  3. 上传文件请使用ceph(s3 or swift) sdk上传文件和管理bucket.

# Benchmark

# 配置

渣配置

  • CPU: Intel(R) Celeron(R) CPU G1620 @ 2.70GHz
  • Memery: 2G

得益于 openresty 的高效(非阻塞,异步),结果是非常的出色。

clients/ ngx-lua-images v1.0 zimg v3.0.1
10 5182.29 Requests/sec 920.90 Requests/sec
50 5077.43 Requests/sec 957.33 Requests/sec
100 5080.09 Requests/sec 945.58 Requests/sec

# github

ngx-lua-images

# 感谢

--EOF--


>看不到评论?GFW!!!