一、FastDFS分布式文件系统简介
1、传统的文件存储VS分布式存储
传统文件存储方式的弊端:
● 如果用户数量多,IO操作比较多,对磁盘访问压力很大
● 如果磁盘发生故障,会造成数据丢失
● 存储容量有限
2、分布式文件系统的概念
分布式文件系统(Distributed File System)是管理文件的,但管理的文件通常不是在一个服务器节点上,而是在多个服务器节点上,这些服务器节点通过网络相连构成一个庞大的文件存储服务器集群,这些服务器都用于存储文件资源,通过分布式文件系统来管理这些服务器上的文件。
FastDFS一款用C语言编写的开源的分布式文件系统,使用FastDFS很容易构建一套高性能的文件服务器集群提供文件上传、下载等服务。
3、FastDFS中文件上传流程
服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage)
跟踪器(tracker)主要做调度工作,在内存中(内存操作导致Tracker server的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了)记录集群中存储节点storage的状态信息,是前端Client和后端存储节点storage的枢纽。
存储节点(storage)用于存储文件,包括文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等。
二、FastDFS安装
1、安装依赖
安装编译库。yum install -y gcc-c++
安装异步事件处理库。yum install -y libevent
安装git。yum install -y git
克隆libfastcommon依赖库。git clone https://github.com/happyfish100/libfastcommon.git
进入安装目录。cd libfastcommon
编译源码。./make.sh
安装。./make.sh install
克隆fastdfs。git clone https://github.com/happyfish100/fastdfs.git
进入安装目录。cd fastdfs
编译源码与安装。./make.sh && ./make.sh install
拷贝配置文件。cp fastdfs/conf/* /etc/fdfs
2、修改配置
修改tracker配置文件(需要新建目录,mkdir /pic/server/fastdfs/tracker -p
):
# the tracker server port
# tracker默认端口
port = 22122
# the base path to store data and log files
# 指定日志文件路径
base_path = /pic/server/fastdfs/tracker
启动tracker服务的指令:/usr/binfdfs_trackerd /etc/fdfs/tracker.conf
重启tracker服务的指令:/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart
如果tracker服务启动成功则如下图:
修改storage配置文件(提前在/pic/server/fastdfs/目录下面新建storage文件夹):
# 不同组存储不同内容, 同一组之间会采用push同步
group_name = group1
# 不修改启动会报错, 用于指定日志文件路径
base_path = /pic/server/fastdfs/storage
# 配置图片存储路径
store_path0 = /pic/server/fastdfs/storge
# 多个tracker保证高可用
tracker_server = xx.xx.xx.xx:22122
# tracker_server = 192.168.209.122:22122
启动storge服务的指令:/usr/binfdfs_storaged /etc/fdfs/storage.conf
重启storge服务的指令:/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart
如果storge服务启动成功则如下图:
修改client配置文件(提前在/pic/server/fastdfs/目录下面新建client文件夹):
# 不修改启动会报错, 用于指定日志文件路径
base_path = /pic/server/fastdfs/storage
# 多个tracker保证高可用
tracker_server = xx.xx.xx.xx:22122
# tracker_server = 192.168.209.122:22122
测试client:/usr/bin/fdfs_test /etc/fdfs/client.conf upload /etc/fdfs/anti-steal.jpg
OK,可以看到上传图片成功了,但是现在还访问不到,需要和Nginx整合。
三、FastDFS功能增强
1、Nginx和FastDFS整合(可通过HTTP访问)
下载Nginx和FastDFS整合模块。git clone https://github.com/happyfish100/fastdfs-nginx-module.git
在vim编辑的时候,可通过:set nu
查看行号。
修改src目录下的config文件:
拷贝配置文件。cp mod_fastdfs.conf /etc/fdfs
修改配置文件(vim mod_fastdfs.conf
):
# the base path to store log files
base_path=/pic/server/fastdfs/storage
tracker_server=xx.xx.xx.xx:22122
# if the url / uri including the group name
# set to false when uri like /M00/00/00/xxx
# set to true when uri like ${group_name}/M00/00/00/xxx, such as group1/M00/xxx
# default value is false
url_have_group_name = true
# store_path#, based 0, if store_path0 not exists, it's value is base_path
# the paths must be exist
# must same as storage.conf
store_path0=/pic/server/fastdfs/storage
重装Nginx,安装时的配置文件如下:
./configure \
--prefix=/usr/nginx \
--pid-path=/usr/nginx/logs/nginx.pid \
--lock-path=/usr/nginx/logs/nginx.lock \
--error-log-path=/usr/nginx/logs/error.log \
--http-log-path=/usr/nginx/logs/access.log \
--http-client-body-temp-path=/usr/nginx/client_body_temp \
--http-proxy-temp-path=/usr/nginx/proxy_temp \
--http-fastcgi-temp-path=/usr/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/usr/nginx/uwsgi_temp \
--http-scgi-temp-path=/usr/nginx/scgi_temp \
--with-http_gzip_static_module \
--add-module=/root/fastdfs-nginx-module/src
重新编译与安装。make && make install
查看Nginx已安装的模块。/usr/local/nginx/sbin/nginx -V
PS:可能会无法显示。。。
修改Nginx配置文件:
server {
listen 80;
server_name localhost;
location ~/group([0-9])/M00/ { #~表示区分大小写的正则匹配
ngx_fastdfs_module; #交给整合模块
alias /pic/server/fastdfs/storage/data/; #将这个目录拼接上剩下的URI作为URL
}
}
2、 图片压缩(可通过文件名动态压缩图片)
安装依赖库。yum -y install gd-devel
在原有的配置文件中添加下面模块(新增模块会覆盖已有模块):
--with-http_stub_status_module \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_image_filter_module
重新编译与安装。make && make install
FastDFS整合Nginx实现图片压缩,需要修改Nginx的配置:
location ~ group1/M00/(.+)_(\d+)x(\d+)\.(jpg|gif|png)$ {
alias /pic/server/fastdfs/storage/data;
ngx_fastdfs_module;
set $w $2;
set $h $3;
if ($w != "0") {
rewrite group1/M00(.+)_(\d+)x(\d+)\.(jpg|gif|png)$ group1/M00$1.$4 break;
}
if ($h != "0") {
rewrite group1/M00(.+)_(\d+)x(\d+)\.(jpg|gif|png)$ group1/M00$1.$4 break;
}
image_filter resize $w $h;
image_filter_buffer 10M;
}
效果如下图:
四、Spring整合的demo
@Component("fastDFSClient")
public class FastDFSClientUtil {
private Logger logger = LoggerFactory.getLogger(FastDFSClientUtil.class);
@Autowired
private FastFileStorageClient storageClient;
/**
* 上传文件
*
* @param file 要上传的文件
* @return 文件存储路径(group1/M00/00/00/ ...)
*/
public String uploadBase64(MultipartFile file) {
StorePath storePath = null;
try {
String fileExtendName = PropertiesUtil.getProperty("fastdfs.pic.extend.name");
storePath = storageClient.uploadImage(new FastImageFile(file.getInputStream(), file.getSize(), fileExtendName, null));
return storePath.getGroup() + "/" + storePath.getPath();
} catch (IOException e) {
e.printStackTrace();
logger.info("上传文件发生错误");
return "";
}
}
/**
* 删除文件
*
* @param filePath 文件路径(group1/M00/00/00/...)
* @return 是否删除成功
*/
public boolean deleteFile(String filePath) {
if (StringUtils.isBlank(filePath))
return false;
StorePath storePath = StorePath.parseFromUrl(filePath);
if (storePath == null)
return false;
try {
storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}