FastDFS — легкая распределенная файловая система с открытым исходным кодом, которая управляет файлами, в ее функции входят: хранение файлов, синхронизация файлов, доступ к файлам (загрузка файлов, загрузка файлов) и т. д. Решает проблему массового хранения и балансировки нагрузки. время он также может загружать файлы на один компьютер в среде кластера, и в то же время другие узлы в группе также создают резервные копии загруженных файлов. При разработке распределенной системы одной из проблем, которые необходимо решить, является проблема изображения, аудио и видео, обмена файлами и резервного копирования данных, Распределенная файловая система как раз может решить эту задачу. Служба FastDFS в основном имеет две роли: Tracker и Storage.Служба Tracker используется для планирования связи между узлом хранения и клиентом, играет роль в балансировке нагрузки при доступе и записывает текущее состояние узла хранения.Это является хабом, соединяющим клиент и узел хранения.Хранилище используется для хранения файлов
-
Развертывание кластера FastDFS
-
Общая схема модуля развертывания
-
Подготовка окружающей среды
название описывать версия системы центос 6.9 libfatscommon Некоторые общие пакеты функций, разделенные FastDFS FastDFS Основная программа FastDFS fastdfs-nginx-module Связанные модули FastDFS и nginx nginx nginx1.15.5 - Установить среду сборки
yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y
-
Описание пути установки диска
инструкция Место расположения FastDFS, поэтому место установки установочного пакета /usr/local/src данные трекера /data/fdfs/tracker ХранениеДанные /data/fdfs/Storage путь к файлу конфигурации /etc/fdfs
-
установить libfatscommon
-
Распаковать и установить
unzip libfastcommon-master.zip cd libfastcommon-master ./make.sh && ./make.sh install #编译安装
-
Установить FastDFS
-
Распаковать и установить
unzip fastdfs-master.zip cd fastdfs-master ./make.sh && ./make.sh install #编译安装 cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf #客户端文件,测试用 cp /usr/local/src/fastdfs/conf/http.conf /etc/fdfs/ #供nginx访问使用 cp /usr/local/src/fastdfs/conf/mime.types /etc/fdfs/ #供nginx访问使用
-
Установите модуль fastdfs-nginx
-
Распаковать и установить
unzip fastdfs-nginx-module-master.zip cp /usr/local/src/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs #复制配置文件到fdfs目录
-
установить нгинкс
-
Распаковать и установить
tar -zxvf nginx-1.15.5.tar.gz cd nginx-1.15.5 #添加fastdfs-nginx-module模块 ./configure --add-module=/usr/local/src/fastdfs-nginx-module-master/src/ make && make install #编译安装
-
Конфигурация развертывания кластера FastDFS
- конфигурация трекера
#服务器ip为 xxx.xxx.78.12, xxx.xxx.78.13 vim /etc/fdfs/tracker.conf #需要修改的内容如下 port=22122 # tracker服务器端口(默认22122,一般不修改) base_path=/data/fdfs/tracker #存储日志和数据的根目录
-
Конфигурация хранилища
vim /etc/fdfs/storage.conf #需要修改的内容如下 port=23000 # storage服务端口(默认23000,一般不修改) base_path=/data/fdfs/storage # 数据和日志文件存储根目录 store_path0=/data/fdfs/storage # 第一个存储目录 tracker_server=xxx.xxx.78.12:22122 # 服务器1 tracker_server=xxx.xxx.78.13:22122 # 服务器2 http.server_port=8888 # http访问文件的端口(默认8888,看情况修改,和nginx中保持一致)
- конфигурация клиента
vim /etc/fdfs/client.conf #需要修改的内容如下 base_path=/home/moe/dfs tracker_server=xxx.xxx.78.12:22122 # 服务器1 tracker_server=xxx.xxx.78.13:22122 # 服务器2
- Настроить доступ к nginx
vim /etc/fdfs/mod_fastdfs.conf #需要修改的内容如下 tracker_server=xxx.xxx.78.12:22122 # 服务器1 tracker_server=xxx.xxx.78.13:22122 # 服务器2 url_have_group_name=true store_path0=/data/fdfs/storage #配置nginx.config vim /usr/local/nginx/conf/nginx.conf #添加如下配置 server { listen 8888; ## 该端口为storage.conf中的http.server_port相同 server_name localhost; location ~/group[0-9]/ { ngx_fastdfs_module; } ...... ...... error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } }
-
Запустить сервис, протестировать
启动之前我们还需要在防火墙开通端口 vim /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22122 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 23000 -j ACCEPT -A INPUT -m state --state NEW -m tcp -p tcp --dport 8888 -j ACCEPT service iptables restart #重启防火墙
-
Операции запуска, выключения и перезапуска для каждой службы
#tracker /etc/init.d/fdfs_trackerd start #启动tracker服务 /etc/init.d/fdfs_trackerd restart #重启动tracker服务 /etc/init.d/fdfs_trackerd stop #停止tracker服务 chkconfig fdfs_trackerd on #自启动tracker服务 #storage /etc/init.d/fdfs_storaged start #启动storage服务 /etc/init.d/fdfs_storaged restart #重动storage服务 /etc/init.d/fdfs_storaged stop #停止动storage服务 chkconfig fdfs_storaged on #自启动storage服务 #nginx /usr/local/nginx/sbin/nginx #启动nginx /usr/local/nginx/sbin/nginx -s reload #重启nginx /usr/local/nginx/sbin/nginx -s stop #停止nginx
-
Обнаружение кластеров
# 会显示会有几台storage服务器,有2台就会显示 Storage 1-Storage 2的详细信息 /usr/bin/fdfs_monitor /etc/fdfs/storage.conf
-
Тест загрузки изображений
#上传成功返回 文件访问 ID # fdfs_upload_file 客户端配置文件 上传文件路径 fdfs_upload_file /etc/fdfs/client.conf /data/test.png
-
доступ к тестовому файлу
http://xxx.xxx.78.12/group1/M00/00/00/rB9ODFvXuSiAWBYBAALSAkm_6RQ360.png http://xxx.xxx.78.13/group1/M00/00/00/rB9ODFvXuSiAWBYBAALSAkm_6RQ360.png
Протестируйте порт nginx по умолчанию 80 для доступа к только что загруженному файлу.Оба адреса могут получить доступ к файлу для достижения цели резервного копирования данных.
-
На этом развертывание сервера FastDFS завершено.
-
Интеграция клиента FastDFS в SpringBoot
-
Прежде всего, согласно официальной подсказке исходного кода, мы сначала загружаем исходный код и используем maven, чтобы скомпилировать его в пакет jar и поместить на частный сервер maven компании (Nexus) или на ваш локальный частный сервер maven (есть другие методы, такие как ant, пожалуйста, проверьте github для получения подробной информации)Адрес загрузки исходного кода FastDFS-java-client-SDK
#编译jar包(解压下载的FastDFS-java-client-SDK源码,使用mvn命令需要先有maven环境) mvn clean install
-
Добавьте зависимости в проект maven pom.xml
<dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.27-SNAPSHOT</version> </dependency>
-
Затем мы добавляем файл fdfs_client.conf в каталог ресурсов проекта.
connect_timeout = 30 network_timeout = 30 charset = UTF-8 http.tracker_http_port = 80 http.anti_steal_token = no http.secret_key = 123456 #前面配置的集群tracker服务器地址 tracker_server = xxx.xxx.78.12:22122 tracker_server = xxx.xxx.78.13:22122
-
Напишите класс объекта загружаемого файла
/** * @Author: maoqitian * @Date: 2018/10/26 0026 17:57 * @Description: FastDFS 文件类 */ public class FastDFSFileEntity { //文件名称 private String name; //内容 private byte[] content; //文件类型 private String ext; //md5值 private String md5; //作者 private String author; public FastDFSFileEntity(String name, byte[] content, String ext, String height, String width, String author) { super(); this.name = name; this.content = content; this.ext = ext; this.author = author; } public FastDFSFileEntity(String name, byte[] content, String ext) { super(); this.name = name; this.content = content; this.ext = ext; } public String getName() { return name; } public void setName(String name) { this.name = name; } public byte[] getContent() { return content; } public void setContent(byte[] content) { this.content = content; } public String getExt() { return ext; } public void setExt(String ext) { this.ext = ext; } public String getMd5() { return md5; } public void setMd5(String md5) { this.md5 = md5; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
-
Напишите операционный класс FastDFS, в основном для загрузки и инициализации сервера отслеживания конфигурации, загрузки файлов, скачивания, удаления и других классов рабочих инструментов.
/** * @Author: maoqitian * @Date: 2018/10/29 0029 9:30 * @Description: FastDFS 操作类 */ public class FastDFSClient { private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class); //双重守护单例 private static volatile FastDFSClient mInstance; /** * 加载配置信息 **/ static { try { String filePath=new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath(); ClientGlobal.init(filePath); }catch (Exception e){ logger.error("FastDFS Client Init Fail!",e); } } private FastDFSClient(){ } public static FastDFSClient getInstance(){ if(mInstance == null){ synchronized (FastDFSClient.class){ if(mInstance == null){ mInstance=new FastDFSClient(); } } } return mInstance; } /** * @Author maoqitian * @Description 上传文件 * @Date 2018/10/29 0029 9:42 * @Param [fastDFSFileEntity] * @return java.lang.String[] **/ public String[] upload(FastDFSFileEntity file){ logger.info("File Name: " + file.getName() + "File Length:" + file.getContent().length); NameValuePair[] metalist=new NameValuePair[1]; metalist[0]=new NameValuePair("author",file.getAuthor()); long startTime = System.currentTimeMillis(); String[] uploadResults= null; StorageClient storageClient=null; try { storageClient=getTrackerClient(); uploadResults = storageClient.upload_file(file.getContent(),file.getExt(),metalist); }catch (IOException e){ logger.error("IO Exception when uploadind the file:"+file.getName(),e); } catch (Exception e){ logger.error("Non IO Exception when uploadind the file:"+file.getName(),e); } logger.info("upload_file time used:" + (System.currentTimeMillis() - startTime) + " ms"); if(uploadResults==null && storageClient!=null){ logger.error("upload file fail, error code:" + storageClient.getErrorCode()); } String groupName = uploadResults[0]; String remoteFileName = uploadResults[1]; logger.info("upload file successfully!!!" + "group_name:" + groupName + ", remoteFileName:" + " " + remoteFileName); return uploadResults; } public FileInfo getFile(String groupName, String remoteFileName) { try { StorageClient storageClient = getTrackerClient(); return storageClient.get_file_info(groupName, remoteFileName); } catch (IOException e) { logger.error("IO Exception: Get File from Fast DFS failed", e); } catch (Exception e) { logger.error("Non IO Exception: Get File from Fast DFS failed", e); } return null; } public InputStream downFile(String groupName, String remoteFileName) { try { StorageClient storageClient = getTrackerClient(); byte[] fileByte = storageClient.download_file(groupName, remoteFileName); InputStream ins = new ByteArrayInputStream(fileByte); return ins; } catch (IOException e) { logger.error("IO Exception: Get File from Fast DFS failed", e); } catch (Exception e) { logger.error("Non IO Exception: Get File from Fast DFS failed", e); } return null; } /** * @Author maoqitian * @Description * @Date 2018/10/31 0031 11:19 * @Param [remoteFileName] * @return int -1 失败 0成功 **/ public int deleteFile(String remoteFileName) throws Exception { StorageClient storageClient = getTrackerClient(); int i = storageClient.delete_file("group1", remoteFileName); logger.info("delete file successfully!!!" + i); return i; } public StorageServer[] getStoreStorages(String groupName) throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerClient.getStoreStorages(trackerServer, groupName); } public ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException { TrackerClient trackerClient = new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName); } public String getTrackerUrl() throws IOException { return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ClientGlobal.getG_tracker_http_port()+"/"; } /** * @Author maoqitian * @Description 获取 StorageClient * @Date 2018/10/29 0029 10:33 * @Param [] * @return org.csource.fastdfs.StorageClient **/ private StorageClient getTrackerClient() throws IOException{ TrackerServer trackerServer=getTrackerServer(); StorageClient storageClient=new StorageClient(trackerServer,null); return storageClient; } /** * @Author maoqitian * @Description 获取 TrackerServer * @Date 2018/10/29 0029 10:34 * @Param [] * @return org.csource.fastdfs.TrackerServer **/ private TrackerServer getTrackerServer() throws IOException { TrackerClient trackerClient=new TrackerClient(); TrackerServer trackerServer = trackerClient.getConnection(); return trackerServer; }
-
Запись контроллера, получение запросов и загрузка файлов для возврата пути доступа к файлу (вот пример загрузки файла, другие функции загрузки, удаления и других файлов могут быть написаны в соответствии с вашими потребностями)
/** * @Author maoqitian * @Description 上传文件 * @Date 2018/10/30 0030 15:07 * @Param [file] * @return com.gxxmt.common.utils.ResultApi **/ @RequestMapping("/upload") public ResultApi upload(@RequestParam("file") MultipartFile file) throws Exception { if (file.isEmpty()) { throw new RRException("上传文件不能为空"); } String url; //此处域名获取可以根据自需求编写 String domainUrl = OSSFactory.build().getDomainPath(); logger.info("配置的域名为"+domainUrl); if (StringUtils.isNotBlank(domainUrl)){ url = uploadFile(file,domainUrl); return ResultApi.success.put("url",url); }else { return ResultApi.error("域名配置为空,请先配置对象存储域名"); } } /** * @Author maoqitian * @Description 上传文件到 FastDFS * @Date 2018/10/29 0029 11:11 * @Param [file] * @Param [domainName] 域名 * @return path 文件访问路径 **/ public String uploadFile(MultipartFile file,String domainName) throws IOException { String[] fileAbsolutePath={}; String fileName=file.getOriginalFilename(); String ext=fileName.substring(fileName.lastIndexOf(".")+1); byte[] file_buff=null; InputStream inputStream = file.getInputStream(); if(inputStream!=null){ int available = inputStream.available(); file_buff=new byte[available]; inputStream.read(file_buff); } inputStream.close(); FastDFSFileEntity fastDFSFileEntity=new FastDFSFileEntity(fileName,file_buff,ext); try { fileAbsolutePath=FastDFSClient.getInstance().upload(fastDFSFileEntity); logger.info(fileAbsolutePath.toString()); }catch (Exception e){ logger.error("upload file Exception!",e); throw new RRException("文件上传出错"+e); } if(fileAbsolutePath == null){ logger.error("upload file failed,please upload again!"); throw new RRException("文件上传失败,请重新上传"); } String path=domainName+fileAbsolutePath[0]+ "/"+fileAbsolutePath[1]; return path; }
-
-
Протестируйте метод и загрузите изображение
-
Из распечатки журнала мы видим, что изображение было успешно загружено.
-
Тестовый доступ для загрузки изображений
-
На данный момент развертывание серверного кластера FastDFS и интеграция клиента в SpringBoot завершены, в будущем мы можем с радостью использовать сервис FastDFS для сохранения наших картинок и т. д. и их резервного копирования. Если в статье что-то не так, пожалуйста, оставьте сообщение и укажите на это, каждый может учиться и развиваться вместе. Если вы считаете, что моя статья поможет вам, пожалуйста, поставьте мне лайк и подпишитесь.