搭建FastDFS分布式集群通过Nginx+Lua+GraphicsMagick实现动态压缩图片
Posted xuad88
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搭建FastDFS分布式集群通过Nginx+Lua+GraphicsMagick实现动态压缩图片相关的知识,希望对你有一定的参考价值。
一、需求
根据用户的请求参数对图片动态裁剪并自动加上水印,将裁剪后的图片和原图保存在同一级目录
例如原图地址的路径为:/images/uploads/2021/09/01.jpg
按200x200裁剪后的图片路径为:/images/uploads/2021/09/01_200x200.jpg
当用户第一次请求200x200的图片时,会自动将图片动态裁剪为200x200的大小,并自动加上水印。
二、实现方式
1、nginx自带的http_image_filter_module模块
image filter module使用的是GD,性能、效率、处理后的图片质量不如 GraphicsMagick,并且裁剪后也不会保存,这样每次请求过来都要重新裁剪,会导致访问速度很慢。
image filter module 不会真正生成裁剪/缩放后的图片,而是通过 Nginx 直接输出的,这样每次请求或缓存过期后都需要重新裁剪/缩放,这样无疑会增加 Nginx 的负担。
2、搭配Lua+GraphicsMagick实现
使用Lua+GraphicsMagick裁剪的图片会保存在磁盘上,用户以后再访问就不再做裁剪,而是直接取之前保存的裁剪后的图片,从而访问效率相比前者好很多。
三、FastDFS集群模块架构
FastDFS 系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)。
- Tracker Server: 跟踪服务器,主要做调度工作,起到均衡的作用;负责管理所有的storage server和group,每个storage在启动后会连接 Tracker,告知自己所属 group 等信息,并保持周期性心跳。多个Tracker之间是对等关系,不存在单点故障。
- Storage Server: 存储服务器,主要提供容量和备份服务;以 group 为单位,每个 group 内可以有多台 storage server,组内的storage server上的数据互为备份。
- Client: 客户端,上传下载数据的服务器。
四、系统环境
节点 | IP地址 | 操作系统 | 安装软件 |
Tracker Server | 192.168.5.106 | Centos 7.6 64位 | Fastdfs |
Tracker Server | 192.168.5.154 | Centos 7.6 64位 | Fastdfs |
Tracker Server | 192.168.5.177 | Centos 7.6 64位 | Fastdfs |
Storage Server | 192.168.5.115 | Centos 7.6 64位 | Fastdfs+Nginx+Lua+GraphicsMagick |
五、安装部署
全局操作(所有机器执行)
wget https://github.com/happyfish100/libfastcommon/archive/V1.0.38.tar.gz
wget https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz
mkdir /data/fastdfs
安装libfastcommon
tar zxvf V1.0.38.tar.gz
cd libfastcommon-1.0.38/
./make.sh
./make.sh install
安装fastdfs
tar zxvf V5.11.tar.gz
cd fastdfs-5.11/
./make.sh
./make.sh install
tracker节点操作
cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf
cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
storage节点操作
cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
cp /root/fastdfs-5.11/conf/http.conf /etc/fdfs/
cp /root/fastdfs-5.11/conf/mime.types /etc/fdfs/
修改tracker server配置
port=22122
base_path=/data/fastdfs
启动tracker server
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start
firewall-cmd --permanent --add-rich-rule=\'rule family="ipv4" source address="192.168.5.0/24" port port="22122" protocol="tcp" accept\'
firewall-cmd --reload
修改storage server配置
port=23000
base_path=/data/fastdfs
store_path0=/data/fastdfs
tracker_server=192.168.5.106:22122
tracker_server=192.168.5.154:22122
tracker_server=192.168.5.177:22122
http.server_port=8088
启动storage server
firewall-cmd --permanent --add-rich-rule=\'rule family="ipv4" source address="192.168.5.0/24" port port="23000" protocol="tcp" accept\'
firewall-cmd --reload
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf start
fdfs_monitor /etc/fdfs/storage.conf list # 查看集群状态
修改Client配置
base_path=/data/fastdfs
tracker_server=192.168.5.106:22122
tracker_server=192.168.5.154:22122
tracker_server=192.168.5.177:22122
下载相关插件
wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.20.tar.gz
tar zxvf V1.20.tar.gz
cd /opt/fastdfs-nginx-module-1.20/src/
cp mod_fastdfs.conf /etc/fdfs/
cd /opt/
git clone https://github.com/alibaba/nginx-http-concat.git
git clone https://github.com/simpl/ngx_devel_kit.git
git clone https://github.com/openresty/echo-nginx-module.git
wget https://github.com/openresty/lua-nginx-module/archive/v0.10.14.tar.gz
tar zxvf v0.10.14.tar.gz
wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
wget http://www.lua.org/ftp/lua-5.3.1.tar.gz
wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.18.tar.gz
yum -y install readline-devel
安装LuaJIT
tar -zxf LuaJIT-2.0.4.tar.gz
cd LuaJIT-2.0.4/
make && make install
export LUAJIT_LIB=/usr/local/lib
export LUAJIT_INC=/usr/local/include/luajit-2.0
ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
安装lua
tar -zxvpf lua-5.3.1.tar.gz
cd lua-5.3.1/
make linux
make install
安装GraphicsMagick
tar zxvf GraphicsMagick-1.3.18.tar.gz
cd GraphicsMagick-1.3.18/
./configure --prefix=/usr/local/GraphicsMagick --enable-shared
make && make install
编译nginx
cd nginx-1.16.1/
./configure --prefix=/data/nginx --with-http_realip_module --with-http_sub_module --with-http_flv_module --with-http_dav_module --with-http_addition_module --with-http_stub_status_module --with-openssl=/usr/local/openssl --add-module=/opt/ngx_cache_purge-2.3 --with-http_gzip_static_module --with-http_ssl_module --with-stream --with-stream_ssl_module --add-module=/opt/nginx_upstream_check_module-master --add-module=/opt/fastdfs-nginx-module-1.20/src/ --with-http_image_filter_module --with-pcre --add-module=/opt/nginx-http-concat --add-module=/opt/lua-nginx-module-0.10.14 --add-module=/opt/ngx_devel_kit --add-module=/opt/echo-nginx-module --with-ld-opt=-Wl,-rpath,$LUAJIT_LIB
make
cp objs/nginx /data/nginx/sbin/
配置lua脚本
mkdir /data/nginx/conf/lua
cd /data/nginx/conf/lua/
chmod +x fastdfs.lua
fastdfs.lua内容
-- 写入文件
local function writefile(filename, info)
local wfile=io.open(filename, "w") --写入文件(w覆盖)
assert(wfile) --打开时验证是否出错
wfile:write(info) --写入传入的内容
wfile:close() --调用结束后记得关闭
end
-- 检测路径是否目录
local function is_dir(sPath)
if type(sPath) ~= "string" then return false end
local response = os.execute( "cd " .. sPath )
if response == 0 then
return true
end
return false
end
-- 检测文件是否存在
local file_exists = function(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
-- 反向查找路径
function last_find(str, k)
local ts = string.reverse(str);
local _, i = string.find(ts, k);
return string.len(ts) - i + 1;
end
local area = nil
local originalUri = ngx.var.uri;
local originalFile = ngx.var.file;
local index = last_find(ngx.var.uri, "([0-9]+)x([0-9]+)");
if index then
originalUri = string.sub(ngx.var.uri, 0, index-2);
area = string.sub(ngx.var.uri, index);
index = string.find(area, "([.])");
area = string.sub(area, 0, index-1);
local index = last_find(originalFile, "([0-9]+)x([0-9]+)");
originalFile = string.sub(originalFile, 0, index-2)
end
-- check original file
if not file_exists(originalFile) then
local fileid = string.sub(originalUri, 2);
-- main
local fastdfs = require(\'restyfastdfs\')
local fdfs = fastdfs:new()
fdfs:set_tracker("0.0.0.0", 22122)
fdfs:set_timeout(1000)
fdfs:set_tracker_keepalive(0, 100)
fdfs:set_storage_keepalive(0, 100)
local data = fdfs:do_download(fileid)
if data then
-- check image dir
if not is_dir(ngx.var.image_dir) then
os.execute("mkdir -p " .. ngx.var.image_dir)
end
writefile(originalFile, data)
end
end
-- 创建缩略图
local image_sizes = {"800x800","710x300","735x250","250x150","186x150","122x122","120x120","345x345","295x295","292x292","262x262","274x274","190x190","150x150","144x144","110x110","690x340","72x72","100x100","180x180","480x240","750x740","216x216","490x190","126x126"};
function table.contains(table, element)
for _, value in pairs(table) do
if value == element then
return true
end
end
return false
end
if table.contains(image_sizes, area) then
local bg;
if string.lower(string.sub(ngx.var.file,-3))=="jpg" then
bg=" -background white ";
else
bg=" -background transparent ";
end;
local command1 = "/usr/local/GraphicsMagick/bin/gm convert -quality 90 " .. originalFile .. " -thumbnail " .. area .. bg .. " -gravity center -extent " .. area .. " " .. ngx.var.file;
local command2 ="";
if area == "800x800" then
command2 = "/usr/local/GraphicsMagick/bin/gm composite -geometry +100+100 -dissolve 50 /data/nginx/image/yaotu1.png " .. ngx.var.file .. " " ..ngx.var.file;
else
command2 = "/usr/local/GraphicsMagick/bin/gm composite -geometry +60+60 -dissolve 50 /data/nginx/image/yaotu2.png " .. ngx.var.file .. " " ..ngx.var.file;
end;
os.execute(command1);
os.execute(command2);
end;
if file_exists(ngx.var.file) then
--ngx.req.set_uri(ngx.var.uri, true);
ngx.exec(ngx.var.uri)
else
ngx.exit(404)
end
上传水印图片
mkdir /data/nginx/image/
添加nginx配置
server {
listen 8088;
server_name localhost;
location /hello {
default_type \'text/plain\';
content_by_lua \'ngx.say("hello,lua")\';
}
location ~/group[0-9]/M00 {
#root /data/fastdfs;
alias /data/fastdfs/data;
set $image_root "/data/fastdfs/data";
if ($uri ~ "/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/([a-zA-Z0-9]+)/(.*)") {
set $image_dir "$image_root/$3/$4/";
set $image_name "$5";
set $file "$image_dir$image_name";
}
if (!-f $file) {
content_by_lua_file "/data/nginx/conf/lua/fastdfs.lua";
}
ngx_fastdfs_module;
}
access_log /data/nginx/logs/img_access.log main;
}
六、测试
上传图片
fdfs_upload_file /etc/fdfs/client.conf ./c.jpg
上传成功后图片路径为
group1/M00/00/00/wKgFc2FEJuKAX9rKAAMGDjihSg4931.jpg
访问图片
http://xxx.xxx.xxx.xxx:8088/group1/M00/00/00/wKgFc2FEJuKAX9rKAAMGDjihSg4931.jpg
访问缩略图
http://xxx.xxx.xxx.xxx:8088/group1/M00/00/00/wKgFc2FEJuKAX9rKAAMGDjihSg4931.jpg_735x250.jpg
以上是关于搭建FastDFS分布式集群通过Nginx+Lua+GraphicsMagick实现动态压缩图片的主要内容,如果未能解决你的问题,请参考以下文章