位置: IT常识 - 正文

FastDFS(fastdfs和minio哪个好)

发布时间:2024-01-23
FastDFS 入门 分布式文件系统 分布式文件系统 (Distributed File System) 是一个软件/软件服务器,这个软件可以用来管理文件。但这个软件所管理的文件通常不是在一个服务器节点上,而是在多个服务器节点上,这些服务器节点通过网络相连构成一个庞大的文件存储服务器集群,这些服务器 ... FastDFS 入门分布式文件系统

推荐整理分享FastDFS(fastdfs和minio哪个好),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:minio和fastdfs,fastdfs空间不足,fastdfs空间不足,fastdfs空间不足,fastdfs空间不足,fastdfs部署,fastdfs部署,fastdfs部署,内容如对您有帮助,希望把文章链接给更多的朋友!

分布式文件系统 (Distributed File System) 是一个软件/软件服务器,这个软件可以用来管理文件。但这个软件所管理的文件通常不是在一个服务器节点上,而是在多个服务器节点上,这些服务器节点通过网络相连构成一个庞大的文件存储服务器集群,这些服务器都用于存储文件资源,通过分布式文件系统来管理这些服务器上的文件。

常见的分布式文件系统有:FastDFS、GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS 等。

分布式文件系统与传统文件系统对比:

传统方式弊端:

如果用户数量多,IO 操作比较多,对磁盘访问压力很大

如果磁盘发生故障,会造成数据丢失

存储容量有限

分布式文件系统优点:

解决单点故障问题,多服务器节点保证文件读写提供数据备份提供扩容等FastDFS 简介

FastDFS 是一个开源的轻量级分布式文件系统,为互联网应用量身定做,简单、灵活、高效,采用 C 语言开发,由阿里巴巴开发并开源。

FastDFS 对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载、文件删除)等,解决了大容量文件存储的问题,特别适合以文件为载体的在线服务,如相册网站、文档网站、图片网站、视频网站等等。

FastDFS 充分考虑了冗余备份、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS 很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

FastDFS 代码托管在 github 上:https://github.com/happyfish100/fastdfs

FastDFS 整体架构

FastDFS 文件系统由两大部分构成,一个是客户端,一个是服务端

客户端通常指我们的程序,比如我们的 Java 程序去连接 FastDFS、操作 FastDFS,那我们的 Java 程序就是一个客户端,FastDFS 提供专有 API 访问,目前提供了 C、Java 和 PHP 几种编程语言的 API,用来访问 FastDFS 文件系统。

服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage)

跟踪器(tracker)主要做调度工作,在内存中记录集群中存储节点 storage 的状态信息,是前端 Client 和后端存储节点 storage的枢纽。因为相关信息全部在内存中,Tracker server 的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了。

存储节点(storage)用于存储文件,包括文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等。

FastDFS 环境搭建资源准备

资源下载地址(或百度云盘直取):https://github.com/happyfish100

资源介绍:

fastdfs-6.08.tar.gz:FastDFS 的安装包(只能在 Linux 上安装)fastdfs-client-java-1.28.zip:FastDFS 的 Java 客户端源代码fastdfs-nginx-module-1.22.zip:FastDFS-Nginx 的扩展模块libfastcommon-1.0.56.tar.gz:FastDFS 的公共函数库(Linux 上安装)FastDFS 安装

FastDFS 没有 Windows 版本,不能在 Windows 下使用。

FastDFS 需要安装部署在 Linux 环境下。

安装 gcc、libevent、libevent-devel 前置依赖

yum install gcc libevent libevent-devel -y

将 FastDFS 的安装包 fastdfs-6.08.tar.gz 和 FastDFS 的公共函数库 libfastcommon-1.0.56.tar.gz 上传到 /home/soft/ 下

解压缩公共函数库 tar -zxvf libfastcommon-1.0.56.tar.gz

进入解压缩后的公共函数库根目录,执行编译命令:./make.sh

编译完成后,执行安装命令:./make.sh install,以上,公共函数库安装完毕

同样,按照此步骤,将 FastDFS 先后进行解压,编译,安装!

至此 FastDFS 安装完成!

所有编译出来的文件存放在 /usr/bin 目录下(放在 /usr/bin 下的命令,我们可在任何地方使用,不用切目录)

所有配置文件存放在 /etc/fdfs 目录下,如下:(后面会使用到这些配置文件)

client.confstorage.confstorage_ids.conftracker.conf

注意:还需要将 /home/soft/fastdfs-6.08/conf/下的 http.conf 和 mime.types 两个文件拷贝到 /etc/fdfs/ 目录下;

后期程序会使用到这两个文件,避免报错;

cp /home/soft/fastdfs-6.08/conf/http.conf /etc/fdfs/cp /home/soft/fastdfs-6.08/conf/mime.types /etc/fdfs/FastDFS 配置

如果你使用的安装版本中/etc/fdfs下的配置文件有类似 .sample 扩展名,则其为示例配置文件,需要去掉 .sample 后缀才能生效,这点需要注意下。

将 storage.conf 和 tracker.conf 下载到本机,进行相关配置

配置 tracker.conf 文件:(跟踪器配置文件)

找到 base_path 参数,配置 tracker 存储数据的目录并手动创建:(需要确保该目录存在,目录需要我们手动创建好)

base_path:配置 tracker 存储数据的目录

base_path = /opt/fastdfs/tracker

配置 storage.conf 文件:(存储节点配置文件)

找到 base_path 参数,配置 storage 存储数据的目录并手动创建:(需要确保该目录存在,目录需要我们手动创建好)

base_path:配置 storage 存储数据的目录

path_path = /opt/fastdfs/storage

找到 store_path0 参数,配置 storage 的磁盘存放路径,即真正存放文件的目录:(需确保该目录存在,需我们手动创建好)

store_path0:真正存放文件的目录

store_path0 = /opt/fastdfs/storage/files

找到 tracker_server 参数,配置当前存储节点的跟踪器地址:(只需要配置 IP 即可,端口不要改动)

tracker_server:注册当前存储节点的跟踪器地址

tracker_server = 192.168.154.129:22122

将在 Windows 中配置完成并保存的 tracker.conf 和 storage.conf 两个文件上传到 /etc/fdfs目录下,并覆盖原文件;

上传并覆盖的命令:rz -y

FastDFS 启动

FastDFS 服务启动需要启动两个脚本:tracker 服务和 storage 服务

命令语法参考:fdfs_trackerd <config_file> [start | stop | restart]fdfs_storaged <config_file> [start | stop | restart]在确保需要手动创建的目录存在的情况下,分别执行下列命令启动 FastDFS:(不加 start 默认是启动)fdfs_trackerd /etc/fdfs/tracker.conffdfs_storaged /etc/fdfs/storage.confps -ef|grep fdfs 查看相关进程,是否启动成功FastDFS 重启分别执行下列命令重启 FastDFS:fdfs_trackerd /etc/fdfs/tracker.conf restartfdfs_storaged /etc/fdfs/storage.conf restartps -ef|grep fdfs 查看相关进程,是否重启成功FastDFS 关闭分别执行下列命令关闭 FastDFS:(其实也可使用 kill 关闭,但为了防止上传文件中数据丢失,不建议使用 kill 方式)fdfs_trackerd /etc/fdfs/tracker.conf stopfdfs_storaged /etc/fdfs/storage.conf stopps -ef|grep fdfs 查看相关进程,是否成功关闭FastDFS 测试

此处示例的上传下载操作其实开发中用不到,主要是感受下 FastDFS 的执行;重点是上传成功后组名和远程文件名的解读!

测试说明:测试文件上传和删除

测试前配置修改

需要修改 /etc/fdfs/client.conf 配置文件的两个参数(自行修改,步骤不再复述;需确保所填的 client 目录存在)

修改小技巧:直接在该文件目录下打开 xftp 传输,直接在传输页面打开文件,修改并保存!

注意:client.conf 文件只在测试的时候才会用到!

base_path = /opt/fastdfs/clienttracker_server = 192.168.154.129:22122测试文件上传测试命令语法参考:Usage: fdfs_test <config_file> <operation>operation: upload, download, getmeta, setmeta, delete and query_servers

启动或重启 FastDFS 服务:

fdfs_trackerd /etc/fdfs/tracker.conf restartfdfs_storaged /etc/fdfs/storage.conf restartps -ef|grep fdfs 查看相关进程,是否重启成功

在 /home 下创建一个用于测试的文件 vim test.txt

上传该文件,执行:

fdfs_test /etc/fdfs/client.conf upload /home/test.txt

上传成功后会显示一些相关信息,其中最重要的有如下两个信息:【重点!】

group_name:组名(决定文件存到哪个机器)

remote_filename:远程文件名(决定文件存放到哪个磁盘目录下)

FastDFS 存储文件时会自动将文件重命名

该文件存储的路径:/opt/fastdfs/storage/files/data/00/00/wKiagGJUGnWAGvVNAAAAFU1LnYY803.txt

group_name=group1, remote_filename=M00/00/00/wKiagGJUGnWAGvVNAAAAFU1LnYY803.txt

测试文件下载下载命令格式:Usage: fdfs_test <config_file> download <group_name> <remote_filename>

在 /home 目录下执行下列命令:

fdfs_test /etc/fdfs/client.conf download group1 M00/00/00/wKiagGJUGnWAGvVNAAAAFU1LnYY803.txt

在 /home 当前目录下看到下载成功的 wKiagGJUGnWAGvVNAAAAFU1LnYY803.txt 文件

测试文件删除删除命令格式:Usage: fdfs_test <config_file> delete <group_name> <remote_filename>

直接执行:

fdfs_test /etc/fdfs/client.conf delete group1 M00/00/00/wKiagGJUGnWAGvVNAAAAFU1LnYY803.txt

可在 /opt/fastdfs/storage/files/data/00/00路径下看到对应的原文件已经被删除

注意没有搭建集群默认只有一个组 group1FastDFS 存储文件的同时会存储一个与其对应的属性文件(备份文件也是,一个备份文件对应一个属性文件)后缀名包含 -m 的为属性文件(meta)在Linux中并没有磁盘一说,是虚拟的分布式文件系统 FastDFS 的 HTTP 访问在文件上传的时候,上传成功的信息中有提示我们可以通过某个路径去访问上传的文件,但是我们直接访问这个路径,却不可以,那么已经上传到 FastDFS 文件系统中的文件,我们如何在浏览器中访问呢?FastDFS 提供了一个 Nginx 扩展模块,利用该模块,我们可以通过 Nginx 访问已经上传到 FastDFS 上的文件。

步骤示例:

1.前期准备将 FastDFS-Nginx 的扩展模块 fastdfs-nginx-module-1.22.zip 上传到 /home/soft 下;解压:unzip fastdfs-nginx-module-1.22.zip ;将解压缩的 /home/soft/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf 文件下载到 Windows 中,后边会进行配置使用;将解压缩的扩展模块源代码的 src 路径 /home/soft/fastdfs-nginx-module-1.22/src拷贝下来,先存着,后面配置重新安装的 Nginx 时会用到这个路径;2.重装 Nginx

注意:Nginx 的安装需要 Linux 安装相关的几个库,否则编译会出现错误;

FastDFS(fastdfs和minio哪个好)

如果之前没有安装过 Nginx,则先执行下列命令安装!如果之前安装过 Nginx,下面这相关库的安装步骤就可直接跳过!

yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y

接下来重新安装 Nginx:因为扩展模块必须在 Nginx 的安装过程中才能添加,所以我们需要重新安装一个 nginx,为了和原来已安装的 Nginx 进行区分,我们把新安装的 Nginx 取名为 nginx_fdfs(指定 nginx 安装路径时进行取名)

将 Nginx 压缩包上传到 /home/soft/ 目录下,并进行解压缩;

进入解压缩后的 Nginx 目录下,按照下面的说明检查路径,并执行下列配置命令:

./configure --prefix=/usr/local/nginx_fdfs --add-module=/home/soft/fastdfs-nginx-module-1.22/src--prefix 是指定nginx安装路径--add-module 指定fastDFS的nginx模块(即扩展模块)的源代码路径(之前已让拷贝存着了)

执行编译命令:make;

执行安装命令make install,完成 Nginx 的重新安装

3.FastDFS 的 Nginx 访问配置

对之前下载下来的扩展模块 src 下的 mod_fastdfs.conf 文件进行如下四项配置:(nginx_mod 目录需要手动创建)

创建目录可使用:mkdir -p /opt/fastdfs/nginx_mod命令

base_path=/opt/fastdfs/nginx_modtracker_server=192.168.154.129:22122url_have_group_name = truestore_path0=/opt/fastdfs/storage/files

使用rz -y命令将配置后的 mod_fastdfs.conf 文件上传到 /etc/fdfs目录下

在 /usr/local/nginx_fdfs/conf目录下,使用 sz nginx.conf命令,将 nginx.conf 文件下载到 Windows 中,进行如下配置:(注意:是在 server 下新建一个 location 进行配置,千万不要直接在原有的 location 中进行修改!)

下面正则使用固定,可直接复制!

#拦截请求路径中包含 /group[1-9]/M0[0-9] 的请求,用 fastdfs的Nginx 模块进行转发location ~ /group[1-9]/M0[0-9] { ngx_fastdfs_module; }

在 /usr/local/nginx_fdfs/conf路径下输入 rz -y上传配置好的 nginx.conf 进行原文件覆盖;

检查配置文件是否有语法错误后,启动 Nginx

注意:检查语法错误这步骤可以省略,这里复习一下

/usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf -t/usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf

查看是否启动成功;

如果 master 和 worker 进程都启动成功,则启动成功;

若上面两个缺少一个,则有可能是之前的配置出错!可能是 nginx_mod 目录没有创建,或 nginx.conf 中配置信息有问题!

ps -ef|grep nginx

启动成功后,则可通过 Nginx 访问已经上传到 FastDFS 上的文件。

4.浏览器访问测试

再进行一次文件上传:在 /home/路径下创建一个文件,如 t.text,随便写进去一些内容;

上传到 FastDFS 中,执行:

fdfs_test /etc/fdfs/client.conf upload t.text

复制控制台中返回的示例文件地址,进行访问测试即可(如果访问时直接是下载文件了,而不是显示文件内容;解决这个问题,可参考https://blog.csdn.net/qq_21457601/article/details/51853248?utm_source=blogxgwz3;其实问题不大,目的已经达到了,即使是直接下载了文件,访问测试也是成功的)

http://192.168.154.129/group1/M00/00/00/wKiagGJURUuAMfHuAAAAHUAYZwU38.text访问流程

访问流程/扩展模块执行流程图:

FastDFS 在普通 Java 项目中开发示例在实际项目开发,FastDFS 提供的主要功能upload:上传文件download:下载文件delete:删除文件FastDFS 文件系统的 Java 客户端FastDFS 文件系统 Java 客户端是指采用 Java 语言编写的一套程序,专门用来访问 fastDFS 文件系统,其实就是一个 jar 包。它并没有添加到 maven 的中央仓库中,我们要使用,需要手动下载源代码,编译到自己的本地 maven 仓库。【现在中央仓库好像有了?自己看着选择吧,可以用自己编译的,也可以直接使用中央仓库的】下载地址:https://github.com/happyfish100/fastdfs(其实之前准备资源,已经让下载过)

将 FastDFS 文件系统 Java 客户端编译到本地 maven 仓库步骤:

下载 FastDFS 客户端源代码 fastdfs-client-java-1.28.zip,解压缩;

进入解压缩的根目录,在文件路径地址栏输入 cmd 命令,进入 dos 窗口,输入 mvn clean install命令,即可将其编译到自己的本地 maven 仓库中,在项目中配置其依赖后可直接使用。

[INFO] Installing C:\Users\linwe\Downloads\fastdfs-client-java-1.28\pom.xml to D:\Java\maven\repository\org\csource\fastdfs-client-java\1.28-SNAPSHOT\fastdfs-client-java-1.28-SNAPSHOT.pom[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------

注意:当在项目 pom 中引入该 maven 依赖时,若无法识别出来,则可以在 IDEA 中设置更新下本地仓库。

Java 项目中使用 FastDFS(用的少,一般在web项目中用)

需求:在普通 Java 项目中使用 FastDFS 文件系统实现对文件的上传,下载和删除操作

步骤示例:

创建普通 maven java 项目,不需要使用 archetype 原型模板

在 pom 中添加 FastDFS 客户端依赖,并刷新 pom(可用自己编译的,也可在中央仓库中自己找)

<dependencies> <!--中央仓库中的FastDFS依赖--> <!--<dependency>--> <!-- <groupId>com.github.tobato</groupId>--> <!-- <artifactId>fastdfs-client</artifactId>--> <!-- <version>1.27.2</version>--> <!--</dependency>--> <!--自己手动编译的本地仓库中FastDFS依赖--> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.28-SNAPSHOT</version> </dependency></dependencies>

在 resources 下创建一个 fastdfs.conf 文件,配置 tracker 跟踪器服务,配置自己的 IP

tracker_server=192.168.154.129:22122

此处直接创建并将相关方法封装为工具类,改参数进行测试调用

public class FastDFSUtil { public static void main(String[] args) { upload(); // download(); // delete(); } /** * 文件上传 */ public static void upload() { try { //读取FastDFS配置文件,用于将所有的tracker的地址读取到内存中 ClientGlobal.init("fastdfs.conf"); // 使用无参构造方式创建tracker客户端对象(配合配置文件使用),用于获取tracker和storage的服务端对象 TrackerClient tc = new TrackerClient(); // 通过tracker客户端对象获取tracker和storage的服务端对象 TrackerServer ts = tc.getTrackerServer(); StorageServer ss = tc.getStoreStorage(ts); // 通过tracker和storage的服务端对象创建Storage客户端对象,来操作数据 StorageClient sc = new StorageClient(ts, ss); /** * 文件上传 * 参数1:需上传文件的绝对路径 * 参数2:文件扩展名 * 参数3:文件的属性文件(通常不用上传) * 返回值:返回一个String数组,此数据非常重要,必须妥善管理,建议存入数据库 * 数组中第一个元素为文件所在组名 * 数组中第二个元素为文件所在远程路径名 */ String[] result = sc.upload_file("D:/image/love.png", "png", null); for (String str : result) { System.out.println(str); } } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } } /** * 文件下载 */ public static void download() { try { //读取FastDFS配置文件,用于将所有的tracker的地址读取到内存中 ClientGlobal.init("fastdfs.conf"); // 使用无参构造方式创建tracker客户端对象(配合配置文件使用),用于获取tracker和storage的服务端对象 TrackerClient tc = new TrackerClient(); // 通过tracker客户端对象获取tracker和storage的服务端对象 TrackerServer ts = tc.getTrackerServer(); StorageServer ss = tc.getStoreStorage(ts); // 通过tracker和storage的服务端对象创建Storage客户端对象,来操作数据 StorageClient sc = new StorageClient(ts, ss); /** * 文件下载 * 参数1:需下载文件的组名 * 参数2:需下载文件的远程文件名 * 参数3:需要保存的本地文件名(绝对路径+文件名) * 返回值:返回0则下载成功;其他值,则下载失败 */ String groupName = "group1"; String remoteFileName = "M00/00/00/wKiagWJU6gyEWTbdAAAAAD_4r6Y944.png"; String localFileName = "D:/temp/a.png"; int ret = sc.download_file(groupName, remoteFileName, localFileName); System.out.println("download========> " + ret); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } } /** * 文件删除 */ p static void delete() { try { //读取FastDFS配置文件,用于将所有的tracker的地址读取到内存中 ClientGlobal.init("fastdfs.conf"); // 使用无参构造方式创建tracker客户端对象(配合配置文件使用),用于获取tracker和storage的服务端对象 TrackerClient tc = new TrackerClient(); // 通过tracker客户端对象获取tracker和storage的服务端对象 TrackerServer ts = tc.getTrackerServer(); StorageServer ss = tc.getStoreStorage(ts); // 通过tracker和storage的服务端对象创建Storage客户端对象,来操作数据 StorageClient sc = new StorageClient(ts, ss); /** * 文件删除 * 参数1:需删除文件的组名 * 参数2:需删除文件的远程文件名 * 返回值:返回0则删除成功;其他值,则删除失败 */ String groupName = "group1"; String remoteFileName = "M00/00/00/wKiagWJU6gyEWTbdAAAAAD_4r6Y944.png"; int ret = sc.delete_file(groupName, remoteFileName); System.out.println("delete========> " + ret); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } }}

在浏览器中输入访问地址进行资源访问测试的时候注意下地址中资源拼接方式:

上传成功返回String数组中两个参数:group1M00/00/00/wKiagWJU-t-EJfOFAAAAAD_4r6Y931.png则访问地址格式为:ip/group1/M00/00/00/wKiagWJU-t-EJfOFAAAAAD_4r6Y931.png即:192.168.154.129/group1/M00/00/00/wKiagWJU-t-EJfOFAAAAAD_4r6Y931.pngFastDFS 在 web 项目中开发示例

需求:对项目进行管理,在 WEB 项目中实现对文件的上传下载和删除操作。

流程分析:将文件从本地上传到 tomcat 中,在 tomcat 中拿到文件流,将文件流传到 FastDFS 中,并将上传返回的数据存入数据库中。

步骤:

1.数据库环境搭建

创建 fastdfs 数据库

新建查询,执行下列命令,创建 creditor_info 表

示例表中:只有 id、group_name、remote_file_path、old_file_name、file_size、file_type 这几个是重要字段!

-- ------------------------------ Table structure for creditor_info-- ----------------------------DROP TABLE IF EXISTS `creditor_info`;CREATE TABLE `creditor_info` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `real_name` varchar(35) DEFAULT NULL COMMENT '债权借款人姓名', `id_card` varchar(18) DEFAULT NULL COMMENT '债权借款人身份证', `address` varchar(150) DEFAULT NULL COMMENT '债权借款人地址', `sex` int(1) DEFAULT NULL COMMENT '1男2女', `phone` varchar(11) DEFAULT NULL COMMENT '债权借款人电话', `money` decimal(10,2) DEFAULT NULL COMMENT '债权借款人借款金额', `group_name` varchar(10) DEFAULT NULL COMMENT '债权合同所在组', `remote_file_path` varchar(150) DEFAULT NULL COMMENT '债权合同所在路径', `old_file_name` varchar(255) DEFAULT NULL COMMENT '文件上传前的名字,用于下载文件时指定默认文件名使用', `file_size` bigint(20) DEFAULT NULL COMMENT '文件大小,用于下载文件啊时提供下载进度', `file_type` varchar(255) DEFAULT NULL COMMENT '文件类型,用于显示与文件类型相同的图标,作用不是很大', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;-- ------------------------------ Records of creditor_info-- ----------------------------INSERT INTO `creditor_info` VALUES ('1', '张三', '123412341', '北京', '1', '23412341', '12433.00', '1', '1', '1', '1', '1');INSERT INTO `creditor_info` VALUES ('2', '李四', '132414123', '上海', '0', '12344312', '21343.00', null, null, null, null, null);

此处用的是 Linux 中的 mysql:用户名 root,密码 123

2.Web 项目环境搭建

创建 Spring Boot 项目,选择 Spring Boot DevTools(热部署工具)、Spring Web、Thymeleaf、MySQL、MyBatis 依赖;

注意:如果配置文件中使用的是低版本的 mysql 驱动配置,pom 中的 mysql 需要添加下低版本的版本号对应;

配置 application.properties

# 配置数据库连接信息 注意mysql新旧版本配置不同(如果用的低版本的驱动,pom里需要将mysql也指定下使用低版本的版本号)spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://192.168.154.129:3306/fastdfs?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8spring.datasource.username=rootspring.datasource.password=123# 开发阶段,关闭thymeleaf的缓存,不然无法看到实时页面spring.thymeleaf.cache=false# 去掉html5的语法验证(thymeleaf对html的标签约束非常严格,所有的标签必须有开有闭,比如<br></br>或者<br/>是可以的,但是<br>会报错,# 配置spring.thymeleaf.mode=LEGACYHTML5 目的就是为了解决这个问题,可以使页面松校验。)spring.thymeleaf.mode=LEGACYHTML5#配置mapper文件路径mybatis.mapper-locations=classpath:mapper/*.xml#开启日志#mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl#文件上传大小参考配置#设置SpringMVC允许上传的单个文件大小,默认为1MB#spring.servlet.multipart.max-file-size=1MB#设置SpringMVC表单请求中允许上传文件的总大小,默认为10MB#spring.servlet.multipart.max-request-size=10MB

在 templates 下创建 creditors.html 测试页面

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"> <title>Title</title></head><body> 1111111111111111111</body></html>

创建控制器类

@Controllerpublic class CreditorInfoController { @RequestMapping("/") public String creditors() { return "creditors"; }}

运行主启动类,访问测试 localhost:8080/

3.使用mybatis生成器(逆向工程生成代码)

PS:使用 mybatis 自动代码生成器,可自动生成 model 实体类, dao 接口以及 mapper 映射文件。

此处使用 mapper 文件和 dao 接口分开管理的方式。

在 pom 的 plugins 标签下添加 mybatis 自动代码生成插件

<!--mybatis自动代码生成插件--><plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.6</version> <configuration> <!--配置文件的位置:在项目的根目录下,和src平级--> <configurationFile>GeneratorMapper.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration></plugin>

在 pom 的 build 标签下添加资源插件,处理资源文件

<!-- 处理资源文件 --><resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/**.*</include> </includes> </resource></resources>

在项目根目录下创建 GeneratorMapper.xml文件,其与 src 平级;将下列内容拷贝到文件中;依照注释修改配置,修改完后,点开右侧 maven 快捷窗口,使用当前项目下 plugins 下 mybatis-genetate 下的 mybatis 自动代码生成插件进行生成。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration> <!-- 指定连接数据库的JDBC驱动包所在位置,指定到你本机的完整路径 --> <classPathEntry location="D:\Java\tools\mysql-connector-java-8.0.28.jar"/> <!-- 配置table表信息内容体,targetRuntime指定采用MyBatis3的版本 --> <context id="tables" targetRuntime="MyBatis3"> <!-- 抑制生成注释,由于生成的注释都是英文的,可以不让它生成 --> <commentGenerator> <property name="suppressAllComments" value="true" /> </commentGenerator> <!-- 配置数据库连接信息 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://192.168.154.129:3306/fastdfs?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT%2B8" userId="root" password="123"> <!--MySQL 不支持 schema 或者 catalog 所以需要添加这个--> <!--设置原因参考:https://blog.csdn.net/qq_40233736/article/details/83314596--> <property name="nullCatalogMeansCurrent" value="true" /> </jdbcConnection> <!-- 生成model类,targetPackage指定model类的包名, targetProject指定生成的model放在eclipse的哪个工程下面--> <javaModelGenerator targetPackage="com.luis.model" targetProject="D:\1a-Projects\test-projects\fastdfs\springboot-web-fastdfs\src\main\java"> <property name="enableSubPackages" value="false" /> <property name="trimStrings" value="false" /> </javaModelGenerator> <!-- 生成MyBatis的Mapper.xml文件,targetPackage指定mapper.xml文件的包名, targetProject指定生成的mapper.xml放在eclipse的哪个工程下面 --> <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- 生成MyBatis的Mapper接口类文件,targetPackage指定Mapper接口类的包名, targetProject指定生成的Mapper接口放在eclipse的哪个工程下面 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.luis.dao" targetProject="src/main/java"> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 数据库表名及对应的Java模型类名 --> <table tableName="creditor_info" domainObjectName="CreditorInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> <table tableName="b_bid_info" domainObjectName="BidInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> <table tableName="b_income_record" domainObjectName="IncomeRecord" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> <table tableName="b_recharge_record" domainObjectName="RechargeRecord" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> <table tableName="u_user" domainObjectName="User" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> <table tableName="u_finance_account" domainObjectName="FinanceAccount" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/> </context></generatorConfiguration>

application.properties 中添加 mybatis 相关配置

#配置mapper文件路径mybatis.mapper-locations=classpath:mapper/*.xml#开启日志mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

在主启动类上添加包扫描注解@MapperScan,扫描 dao 所在的包(防止后面忘记了,先加上)

作用:扫描 dao 下的所有 mapper 类作为 Mapper 映射文件。

@SpringBootApplication@MapperScan(basePackages = "com.luis.dao")public class SpringbootWebFastdfsApplication { public static void main(String[] args) { SpringApplication.run(SpringbootWebFastdfsApplication.class, args); }}4.显示数据列表

控制器类补充查询功能

@Controllerpublic class CreditorInfoController { @Resource private CreditorInfoServer creditorInfoServer; @RequestMapping("/") public String creditors(Model model) { List<CreditorInfo> creditorInfoList = creditorInfoServer.queryAll(); model.addAttribute("creditorInfoList", creditorInfoList); return "creditors"; }}

补充 service 接口和实现类

public interface CreditorInfoServer { List<CreditorInfo> queryAll();}@Servicepublic class CreditorInfoServiceImpl implements CreditorInfoServer { @Resource private CreditorInfoMapper creditorInfoMapper; @Override public List<CreditorInfo> queryAll() { List<CreditorInfo> list = creditorInfoMapper.selectAll(); return list; }}

dao 中添加全查方法

public interface CreditorInfoMapper { int deleteByPrimaryKey(Integer id); int insert(CreditorInfo record); int insertSelective(CreditorInfo record); CreditorInfo selectByPrimaryKey(Integer id); int updateByPrimaryKeySelective(CreditorInfo record); int updateByPrimaryKey(CreditorInfo record); // 新增的全查方法 List<CreditorInfo> selectAll();}

mapper 中补充全查的 SQL

<select id="selectAll" resultMap="BaseResultMap"> select <include refid="Base_Column_List" /> from creditor_info</select>

完善显示数据的页面

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"> <title>test</title></head><body> <table> <tr> <th>序号</th> <th>姓名</th> <th>性别</th> <th>电话</th> <th>地址</th> <th></th> </tr> <tr th:each="creditorInfo:${creditorInfoList}"> <td th:text="${creditorInfo.id}">序号</td> <td th:text="${creditorInfo.realName}">姓名</td> <td th:text="${creditorInfo.sex == 1?'男':'女'}">性别</td> <td th:text="${creditorInfo.phone}">电话</th> <td th:text="${creditorInfo.address}">地址</td> <td> <span th:if="${creditorInfo.remoteFilePath == null || creditorInfo.remoteFilePath == ''}"> <a th:href="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/upload/${creditorInfo.id}|}">上传</a> </span> <span th:if="${creditorInfo.remoteFilePath != null && creditorInfo.remoteFilePath != ''}"> <a th:href="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/download|}">下载</a> <a th:href="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/delete|}">删除</a> </span> </td> </tr> </table></body></html>

运行主启动类,测试

5.Web 中操作 FastDFS 完成上传6.Web 中操作 FastDFS 完成下载7.Web 中操作 FastDFS 完成删除

由于操作不好记录,以下相关实现提供相关实现参考:

相关页面参考:

creditors.html

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"> <title>creditors.html</title></head><body> <table> <tr> <th>序号</th> <th>姓名</th> <th>性别</th> <th>电话</th> <th>地址</th> <th></th> </tr> <tr th:each="creditorInfo:${creditorInfoList}"> <td th:text="${creditorInfo.id}">序号</td> <td th:text="${creditorInfo.realName}">姓名</td> <td th:text="${creditorInfo.sex == 1?'男':'女'}">性别</td> <td th:text="${creditorInfo.phone}">电话</th> <td th:text="${creditorInfo.address}">地址</td> <td> <span th:if="${creditorInfo.remoteFilePath == null || creditorInfo.remoteFilePath == ''}"> <a th:href="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/upload/${creditorInfo.id}|}">上传</a> </span> <span th:if="${creditorInfo.remoteFilePath != null && creditorInfo.remoteFilePath != ''}"> <a th:href="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/download/${creditorInfo.id}|}">下载</a> <a th:href="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/delete/${creditorInfo.id}|}">删除</a> </span> </td> </tr> </table></body></html>

upload.html

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head> <meta charset="UTF-8"> <title>upload.html</title></head><body> <!-- 上传文件的表单,method必须为post,并且必须指定enctype属性为multipart/form-data --> <!-- enctype="multipart/form-data" 简单说明:让表单以二进制的形式传递数据,支持流文件类型 --> <form th:action="https://www.cnblogs.com/luisblog/archive/2022/11/01/@{|/upload|}" target="curPage" method="post" enctype="multipart/form-data"> 姓名:<span th:text="${creditorInfo.realName}"></span><br/> 性别:<span th:text="${creditorInfo.sex==1?'男':'女'}"></span><br/> 电话:<span th:text="${creditorInfo.phone}"></span><br/> 地址:<span th:text="${creditorInfo.address}"></span><br/> 文件:<input type="file" name="myFile" /><br/> <input type="hidden" name="id" th:value="${creditorInfo.id}" /><br/> <input type="submit" value="上传文件"><br/> </form> <!-- 嵌入式框架框架 --> <iframe name="curPage"></iframe></body></html>

success.html

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> if (confirm("[[${msg}]]")) { window.top.location.href = "[[${url}]]"; } </script></head><body></body></html>工具类参考:public class FastDFSUtil { private FastDFSUtil() { } /** * 文件上传 * * @param fileBuff 上传文件的字节数组 * @param fileExtName 上传文件的扩展名 * @return String数组 * 数组中第一个元素为文件所在组名 * 数组中第二个元素为文件所在远程路径名 */ public static String[] upload(byte[] fileBuff, String fileExtName) { try { //读取FastDFS配置文件,用于将所有的tracker的地址读取到内存中 ClientGlobal.init("fastdfs.conf"); // 使用无参构造方式创建tracker客户端对象(配合配置文件使用),用于获取tracker和storage的服务端对象 TrackerClient tc = new TrackerClient(); // 通过tracker客户端对象获取tracker和storage的服务端对象 TrackerServer ts = tc.getTrackerServer(); StorageServer ss = tc.getStoreStorage(ts); // 通过tracker和storage的服务端对象创建Storage客户端对象,来操作数据 StorageClient sc = new StorageClient(ts, ss); /** * 文件上传 * 参数1:需上传文件的字节数组 * 参数2:文件扩展名 * 参数3:文件的属性文件(通常不用上传) * 返回值:返回一个String数组,此数据非常重要,必须妥善管理,建议存入数据库 * 数组中第一个元素为文件所在组名 * 数组中第二个元素为文件所在远程路径名 */ return sc.upload_file(fileBuff, fileExtName, null); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } /** * 文件下载 * * @param groupName 需下载文件的组名 * @param remoteFileName 需下载文件的远程文件名 * @return byte[] 需下载文件的字节数组 */ public static byte[] download(String groupName, String remoteFileName) { try { //读取FastDFS配置文件,用于将所有的tracker的地址读取到内存中 ClientGlobal.init("fastdfs.conf"); // 使用无参构造方式创建tracker客户端对象(配合配置文件使用),用于获取tracker和storage的服务端对象 TrackerClient tc = new TrackerClient(); // 通过tracker客户端对象获取tracker和storage的服务端对象 TrackerServer ts = tc.getTrackerServer(); StorageServer ss = tc.getStoreStorage(ts); // 通过tracker和storage的服务端对象创建Storage客户端对象,来操作数据 StorageClient sc = new StorageClient(ts, ss); return sc.download_file(groupName, remoteFileName); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } return null; } /** * 文件删除 * @param groupName 需删除文件的组名 * @param remoteFileName 需删除文件的远程文件名 */ public static void delete(String groupName, String remoteFileName) { try { //读取FastDFS配置文件,用于将所有的tracker的地址读取到内存中 ClientGlobal.init("fastdfs.conf"); // 使用无参构造方式创建tracker客户端对象(配合配置文件使用),用于获取tracker和storage的服务端对象 TrackerClient tc = new TrackerClient(); // 通过tracker客户端对象获取tracker和storage的服务端对象 TrackerServer ts = tc.getTrackerServer(); StorageServer ss = tc.getStoreStorage(ts); // 通过tracker和storage的服务端对象创建Storage客户端对象,来操作数据 StorageClient sc = new StorageClient(ts, ss); sc.delete_file(groupName, remoteFileName); } catch (IOException e) { e.printStackTrace(); } catch (MyException e) { e.printStackTrace(); } }}控制器类参考:@Controllerpublic class CreditorInfoController { @Resource private CreditorInfoServer creditorInfoServer; @RequestMapping("/") public String creditors(Model model) { List<CreditorInfo> creditorInfoList = creditorInfoServer.queryAll(); model.addAttribute("creditorInfoList", creditorInfoList); return "creditors"; } @GetMapping("/upload/{id}") public String toUpload(@PathVariable Integer id, Model model) { CreditorInfo creditorInfo = creditorInfoServer.findById(id); model.addAttribute("creditorInfo", creditorInfo); return "upload"; } /** * 文件上传 * 参数MultipartFile:为Spring提供的一个类,专门用于封装请求中的文件数据, * 其属性名必须与表单中文件域的名字完全相同!否则无法获取文件数据! */ @PostMapping("/upload") public String upload(Integer id, MultipartFile myFile, Model model) throws IOException { // System.out.println(myFile.getBytes()); // 获取文件对应字节数组 // System.out.println(myFile.getContentType()); // 获取文件类型 // System.out.println(myFile.getInputStream()); // 获取文件对应的输入流 // System.out.println(myFile.getName()); // 获取表单元素名 // System.out.println(myFile.getOriginalFilename()); // 获取文件名 // System.out.println(myFile.getSize()); // 获取文件大小 // System.out.println(myFile.isEmpty()); //判断文件是否为空;文件没有上传或文件大小为0,这个值都是true // 获取上传文件对应的字节数组 byte[] fileBuff = myFile.getBytes(); // 获取上传文件的文件名 String fileName = myFile.getOriginalFilename(); // 获取上传文件的扩展名 // #TODO 可能会出现问题,因为有的文件有可能没有扩展名,所以必要时需要做逻辑控制 String fileExtName = fileName.substring(fileName.lastIndexOf(".") + 1); Long fileSize = myFile.getSize(); // 文件大小 String fileType = myFile.getContentType(); // 文件类型 // ================进行文件上传========上传到FastDFS文件系统中============= String[] result = FastDFSUtil.upload(fileBuff, fileExtName); CreditorInfo creditorInfo = new CreditorInfo(); creditorInfo.setId(id); // id creditorInfo.setGroupName(result[0]); // 组名 creditorInfo.setRemoteFilePath(result[1]); // 远程文件地址 creditorInfo.setOldFileName(fileName); // 文件名 creditorInfo.setFileSize(fileSize); // 文件大小 creditorInfo.setFileType(fileType); // 文件类型 // ==========更新数据库信息========== creditorInfoServer.updateFileInfo(creditorInfo); model.addAttribute("msg", "上传成功,是否返回列表页面?"); model.addAttribute("url", "/"); return "success"; } /** * 文件下载 * @param id 需要下载的文件主键 * @return ResponseEntity 表示一个响应的实体,这个类是Spring提供的一个类,是Spring响应数据时的一个对象, * 这个对象有包含着响应时的编码如404 202 等,以及响应的头文件信息,以及响应时的具体数据; * 这个对象可以是一段html代码,也可是是一段JS,也可以是一段普通字符串,也可以是一个文件的流 */ @RequestMapping("/download/{id}") public ResponseEntity<byte[]> download(@PathVariable Integer id) { // 获取响应数据(即下载后成功返回的字节数组) CreditorInfo info = creditorInfoServer.findById(id); String groupName = info.getGroupName(); String remoteFilePath = info.getRemoteFilePath(); byte[] buffFile = FastDFSUtil.download(groupName, remoteFilePath); // 设置响应时的头文件信息 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 设置响应类型为文件类型 headers.setContentLength(info.getFileSize()); // 设置响应时的文件大小,用于提供下载进度显示使用 // 设置下载时的默认文件名 headers.setContentDispositionFormData("attachment", info.getOldFileName()); /** * 创建响应实体对象,Spring会将这个对象返回给浏览器,作为响应数据;(我们需要填充数据) * 参数1:响应时的具体数据 * 参数2:响应时的头文件信息 * 参数3:响应时的状态码 */ ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(buffFile, headers, HttpStatus.OK); return responseEntity; } /** * 文件删除 * 文件删除操作选择在业务层进行,因为需要先查数据,才能进行删除,减少方法调用。 * @param id * @return */ @RequestMapping("/delete/{id}") public String delete(@PathVariable Integer id) { creditorInfoServer.deleteFileById(id); return "redirect:/"; }}service 接口实现类参考:@Servicepublic class CreditorInfoServiceImpl implements CreditorInfoServer { @Resource private CreditorInfoMapper creditorInfoMapper; @Override public List<CreditorInfo> queryAll() { List<CreditorInfo> list = creditorInfoMapper.selectAll(); return list; } @Override public CreditorInfo findById(Integer id) { CreditorInfo creditorInfo = creditorInfoMapper.selectByPrimaryKey(id); return creditorInfo; } @Override public int updateFileInfo(CreditorInfo creditorInfo) { int ret = creditorInfoMapper.updateByPrimaryKeySelective(creditorInfo); return ret; } @Override public void deleteFileById(Integer id) { CreditorInfo creditorInfo = creditorInfoMapper.selectByPrimaryKey(id); String groupName = creditorInfo.getGroupName(); String remoteFilePath = creditorInfo.getRemoteFilePath(); // 先删除远程文件 FastDFSUtil.delete(groupName, remoteFilePath); // 再修改数据库文件数据 creditorInfo.setGroupName(""); creditorInfo.setRemoteFilePath(""); creditorInfo.setOldFileName(""); creditorInfo.setFileSize(0L); creditorInfo.setFileType(""); creditorInfoMapper.updateByPrimaryKeySelective(creditorInfo); }}gitee 上完整示例项目参考:

Web 中操作 FastDFS 完成上传,下载,删除相关步骤,参考下列完整的示例项目:

https://gitee.com/lw2gitee/springboot-web-fastdfs

可克隆下来,在本地查看实现流程以及步骤。

FastDFS 分布式文件系统集群

其实之前做的集群都算是伪集群,因为之前都是在一台机器上搭建的集群服务;

下面示例的 FastDFS 分布式文件系统集群是在七个虚拟机中进行搭建,相当于七台机器,是真正的集群架构。

架构图

同一个组中数据相同,机器之间有数据备份,建议同一个组中所有机器性能和配置要相同不同组中存的数据不同如果有4台机器存储数据,每个机器有1G存储空间,那么我们文件的存储上限是2G(因为每台机器对应一个备份机器)环境搭建步骤

PS:建议如果实际操作,不要直接按照下面步骤来!其中有很多细节需要注意,建议跟着视频操作!

视频链接:https://www.bilibili.com/video/BV1ta4y1v7Kw?p=25

FastDFS分布式文件系统集群环境搭建-操作步骤手册搭建一个FastDFS分布式文件系统集群,推荐至少部署6个服务器节点;================================搭建FastDFS的集群==============================第一步:安装6个迷你版的Linux,迷你版Linux没有图形界面,占用磁盘及资源小,企业里面使用的Linux都是没有图形界面的Linux;第二步:由于迷你版Linux缺少一些常用的工具库,操作起来不方便,推荐安装如下的工具库:(不要分别安装,一次全安装)1、安装lrzsz, yum install lrzsz -y2、安装wget, yum install wget -y4、安装vim, yum install vim -y5、安装unzip,yum install unzip -y6、安装ifconfig,yum install net-tools -y一次性全部安装: yum install lrzsz wget vim unzip net-tools -y7、安装nginx及fastdfs需要的库依赖:yum install gcc perl openssl openssl-devel pcre pcre-devel zlib zlib-devel libevent libevent-devel -y第三步 安装fastdfs 1、 上传fastdfs的安装包和libfastcommon的安装包 2、 解压libfastcommon 安装libfastcommon 3、 解压fastdfs 安装fastdfs 4、 拷贝fastdfs目录中的http.conf和mime.types到/etc/fdfs 目录中注:6台机器全部执行这些操作第四步:部署两个tracker server服务器,需要做的工作: 修改两个tracker服务器的配置文件: tracker.conf: 修改一个地方: base_path=/opt/fastdfs/tracker #设置tracker的数据文件和日志目录(需预先创建) 启动tracker服务器 fdfs_trackerd /etc/fdfs/tracker.conf第五步 修改两个组中的4台storage中storage.conf文件 第一组group1的第一个storage server(修改storage.conf配置文件): group_name=group1 #组名,根据实际情况修改,值为 group1 或 group2 base_path=/opt/fastdfs/storage #设置storage的日志目录(需预先创建) store_path0=/opt/fastdfs/storage/files #存储路径 tracker_server=192.168.171.135:22122 #tracker服务器的IP地址以及端口号 tracker_server=192.168.171.136:22122 第二组group2的第一个storage server(修改storage.conf配置文件): group_name=group2 #组名,根据实际情况修改,值为 group1 或 group2 base_path=/opt/fastdfs/storage #设置storage的日志目录(需预先创建) store_path0=/opt/fastdfs/storage/files #存储路径 tracker_server=192.168.171.135:22122 #tracker服务器的IP地址以及端口号 tracker_server=192.168.171.136:22122 启动storage服务器 使用之前的Java代码测试FastDFS的6台机器是否可以上传文件注意:FastDFS默认是带有负载均衡策略的可以在tracker的2台机器中修改tracker.conf文件 store_lookup=1 0 随机存放策略 1 指定组 2 选择磁盘空间的优先存放 默认值 修改后重启服务 fdfs_trackerd /etc/fdfs/tracker.conf restart======================使用Nginx进行负载均衡==============================第六步 安装 nginx ,使用nginx 对fastdfs 进行负载均衡 上传 nginx-1.12.2.tar.gz以及 nginx的fastdfs扩展模块安装包fastdfs-nginx-module-master.zip 添加nginx的安装依赖 yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel -y 解压nginx tar -zxvf nginx-1.12.2.tar.gz 解压fastdfs扩展模块 unzip fastdfs-nginx-module-master.zip 配置nginx的安装信息 2台tracker服务器的配置信息(不需要fastdfs模块) ./configure --prefix=/usr/local/nginx_fdfs 4台storage服务器其的配置信息(需要使用fastdfs模块) ./configure --prefix=/usr/local/nginx_fdfs --add-module=/root/fastdfs-nginx-module-master/src 编译并安装nginx ./make ./make install 4台storage的服务器需要拷贝mod_fastdfs文件 将/root/fastdfs-nginx-module-master/src目录下的mod_fastdfs.conf文件拷贝到 /etc/fdfs/目录下,这样才能正常启动Nginx;第七步 配置tracker 的两台机器的nginx 进入安装目录 cd /usr/local/nginx_fdfs 添加一个location 对请求进行拦截,配置一个正则规则 拦截fastdfs的文件路径, 并将请求转发到其余的4台storage服务器(修改 conf目录下nginx.conf 文件) #nginx拦截请求路径: location ~ /group[1-9]/M0[0-9] { proxy_pass http://fastdfs_group_server; } 添加一个upstream 执行服务的IP为 另外的4台stroage 的地址 #部署配置nginx负载均衡: upstream fastdfs_group_server { server 192.168.171.137:80; server 192.168.171.138:80; server 192.168.171.139:80; server 192.168.171.140:80; }第八步 配置另外4台storage的nginx添加http访问的请求路径拦截 进入安装目录 cd /usr/local/nginx_fdfs 添加一个location 对请求进行拦截,配置一个正则规则 拦截fastdfs的文件路径,使用fastdfs的nginx模块转发请求(修改 conf目录下nginx.conf 文件) #nginx拦截请求路径: location ~ /group[1-9]/M0[0-9] { ngx_fastdfs_module; }第九步 分别修改4台storage服务器的mod_fasfdfs.conf文件(/etc/fdfs/mod_fastdfs.conf) #修改基本路径,并在指定路径创建对应文件夹 base_path=/opt/fastdfs/nginx_mod #保存日志目录 #指定两台tracker服务器的ip和端口 tracker_server=192.168.171.135:22122 #tracker服务器的IP地址以及端口号 tracker_server=192.168.171.136:22122 #指定storage服务器的端口号 storage_server_port=23000 #通常情况不需要修改 #指定当前的storage服务器所属的组名 (当前案例03和04为group1 05和06为group2) group_name=group1 #当前服务器的group名 #指定url路径中是否包含组名 (当前案例url包含组名) url_have_group_name=true #文件url中是否有group名 store_path_count=1 #存储路径个数,需要和store_path个数匹配(一般不用改) store_path0=/opt/fastdfs/storage/files #存储路径 #指定组个数,根据实际配置决定,(当前案例拥有2个组group1和group2) group_count = 2 #设置组的个数 在末尾增加2个组的具体信息: [group1] group_name=group1 storage_server_port=23000 store_path_count=1 store_path0=/opt/fastdfs/storage/files [group2] group_name=group2 storage_server_port=23000 store_path_count=1 store_path0=/opt/fastdfs/storage/files 第一个组的第二个storage按照相同的步骤操作; 另外一个组的两个storage也按照相同的步骤操作; #测试nginx的配置文件是否正确(测试全部6台服务器) /usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf -t #启动nginx服务器(全部6台服务器) /usr/local/nginx_fdfs/sbin/nginx -c /usr/local/nginx_fdfs/conf/nginx.conf测试:使用浏览器分别访问 6台 服务器中的fastdfs文件第十步:部署前端用户访问入口服务器,即访问192.168.230.128上的Nginx,该Nginx负载均衡到后端2个tracker server; 配置nginx.conf文件 location ~ /group[1-9]/M0[0-9] { proxy_pass http://fastdfs_group_server; } 添加一个upstream 执行服务的IP为 2台tracker 的地址 #部署配置nginx负载均衡: upstream fastdfs_group_server { server 192.168.171.135:80; server 192.168.171.136:80; }测试:使用浏览器访问128(唯一入口的nginx服务器)服务器中的fastdfs文件注意:由于之前128的nginx中可能拥有静态资源拦截会导致访问不到文件,这时可以注释或删除这些静态资源拦截==============================补充资料============================================最后,为了让服务能正常连接tracker,请关闭所有机器的防火墙:systemctl status firewalld 查看防火墙状态systemctl disable firewalld 禁用开机启动防火墙systemctl stop firewalld 停止防火墙systemctl restart network 重启网络systemctl start network 启动网络systemctl stop network 停止网络可能安装的linux(无图形的)没有开启网卡服务,可以修改/etc/sysconfig/network-scripts 下的网卡配置文件设置 ONBOOT=yse 表示开机启动网卡,然后启动网络服务即可Keepalived当主nginx出现故障后会自动切换到备用nginx服务器的一款软件 通常由运维人员进行使用
本文链接地址:https://www.jiuchutong.com/zhishi/304652.html 转载请保留说明!

上一篇:Java基础之变量(java基础变量字节)

下一篇:苹果CMSV10最新大橙子模板使用教程包括苹果CMSV10使用教程和宝塔自动采集教程(苹果cmsv10官网)

  • 怎么玩转微信淘客公众号系统?(怎么玩转微信淘宝号)

    怎么玩转微信淘客公众号系统?(怎么玩转微信淘宝号)

  • ipad钉钉怎么设置虚拟背景(iPad钉钉怎么设置虚拟背景)

    ipad钉钉怎么设置虚拟背景(iPad钉钉怎么设置虚拟背景)

  • 手机钉钉怎么换视频会议背景(手机钉钉怎么换行打字)

    手机钉钉怎么换视频会议背景(手机钉钉怎么换行打字)

  • 醒图怎么把图片变成视频(醒图怎么把图片弄成视频)

    醒图怎么把图片变成视频(醒图怎么把图片弄成视频)

  • qq农场怎么赚钱最快(qq农场技巧)

    qq农场怎么赚钱最快(qq农场技巧)

  • 华为p40隐藏应用图标的方法(华为P40隐藏应用的方法)

    华为p40隐藏应用图标的方法(华为P40隐藏应用的方法)

  • 卡贴机呼叫失败却能上网(卡贴机呼叫失败能上网怎么办)

    卡贴机呼叫失败却能上网(卡贴机呼叫失败能上网怎么办)

  • 探探看别人主页会有显示吗(探探谁看了我)

    探探看别人主页会有显示吗(探探谁看了我)

  • 手机qq视频怎么分享屏幕(手机qq视频怎么压缩发送)

    手机qq视频怎么分享屏幕(手机qq视频怎么压缩发送)

  • 错误码110509是什么意思(错误码110519)

    错误码110509是什么意思(错误码110519)

  • 抖音怎么看私信(抖音怎么看私信对方是否看过)

    抖音怎么看私信(抖音怎么看私信对方是否看过)

  • oppo手机忘记锁屏图案打不开手机怎么办(oppo手机忘记锁屏图案怎样解锁)

    oppo手机忘记锁屏图案打不开手机怎么办(oppo手机忘记锁屏图案怎样解锁)

  • OPPOk3和k5怎么选择(opopk3还是oppok5好)

    OPPOk3和k5怎么选择(opopk3还是oppok5好)

  • 断路器辅助节点属于什么信号(断路器辅助节点DL)

    断路器辅助节点属于什么信号(断路器辅助节点DL)

  • ppt三种放映类型(ppt的三种放映类型)

    ppt三种放映类型(ppt的三种放映类型)

  • 微信不符合辅助要求是什么意思(微信不符合辅助验证)

    微信不符合辅助要求是什么意思(微信不符合辅助验证)

  • qq的校园扩列怎么设置(qq校园扩列怎么不见了)

    qq的校园扩列怎么设置(qq校园扩列怎么不见了)

  • 给别人打电话正忙是什么意思(给别人打电话正忙是不是被拉黑了)

    给别人打电话正忙是什么意思(给别人打电话正忙是不是被拉黑了)

  • oppo手机的手电筒为什么打不开了怎么办(oppo手机的手电筒快捷关闭设置在哪)

    oppo手机的手电筒为什么打不开了怎么办(oppo手机的手电筒快捷关闭设置在哪)

  • 手机怎么让电脑下线(手机怎么让电脑主机上网)

    手机怎么让电脑下线(手机怎么让电脑主机上网)

  • 13.1怎么删除软件(苹果13怎么删除程序)

    13.1怎么删除软件(苹果13怎么删除程序)

  • 小米cc9能装内存卡吗(小米cc9外置内存卡最大可以安装多大)

    小米cc9能装内存卡吗(小米cc9外置内存卡最大可以安装多大)

  • 小米8能用多久(小米8能用多久充电)

    小米8能用多久(小米8能用多久充电)

  • 苹果出现可能不支持此配件(苹果出现可能不支持此配件怎么弄)

    苹果出现可能不支持此配件(苹果出现可能不支持此配件怎么弄)

  • 怎么看微信朋友圈详情(怎么看微信朋友圈的互动消息)

    怎么看微信朋友圈详情(怎么看微信朋友圈的互动消息)

  • vivoy3有没有无线充电功能(vivoy3支持无线充电器吗)

    vivoy3有没有无线充电功能(vivoy3支持无线充电器吗)

  • 苹果怎么把软件导入另一个手机上(苹果怎么把软件移到主屏幕)

    苹果怎么把软件导入另一个手机上(苹果怎么把软件移到主屏幕)

  • 苹果xs max的悬浮球怎么打开(苹果xsmax的悬浮球在哪里打开)

    苹果xs max的悬浮球怎么打开(苹果xsmax的悬浮球在哪里打开)

  • 苹果xs max电量百分比怎么显示在屏幕上(苹果xsmax电量百分比怎么打开)

    苹果xs max电量百分比怎么显示在屏幕上(苹果xsmax电量百分比怎么打开)

  • Win11和Win10哪个流畅 Win11和Win10系统性能流畅度对比(win11和win10哪个玩游戏好)

    Win11和Win10哪个流畅 Win11和Win10系统性能流畅度对比(win11和win10哪个玩游戏好)

  • mac如何安装dmg软件?苹果电脑安装应用程序方法介绍(mac怎么安装dmg软件)

    mac如何安装dmg软件?苹果电脑安装应用程序方法介绍(mac怎么安装dmg软件)

  • 免税收入进项税额转出比例结转法
  • 员工交通费可以税前扣除吗
  • 公司购买设备报告怎么写
  • 机耕道属于水利还是土地整治
  • 所得税多交怎么调整
  • 出口业务退税流程资料
  • 住宿发票要附清单吗
  • 会计人员必备的知识和技能
  • 商铺 公司
  • 未按规定安装使用税控装置
  • 公司给供电局转账违法吗
  • 阻止系统蓝屏后怎么恢复
  • 营业外收入冲减销售费用
  • 费用发票可以不上账吗
  • jQuery+Ajax+PHP“喜欢”评级功能实现代码
  • 预收预付不一致什么意思
  • 收益类账户的会计分录
  • csrrs.exe
  • 无线路由器wifi指示灯不亮
  • 所有者权益类的期末余额公式
  • 进货退回的会计处理
  • Pinia(二)了解和使用Store
  • 华为od机试成绩什么时候出来
  • php 进程间通信
  • 玩很多游戏的人
  • 前端页面设计
  • 自动驾驶 模块
  • 手把手教你安装技嘉b550 master主板
  • 房屋租赁需要计增值税吗
  • 支付宝对公账户怎么转账
  • 农产品进项税抵扣填报方法
  • 结转清理损失会计分录
  • 交给工会的40%的工会经费里还要再返60%吗
  • 策划费多少钱
  • 收到个人所得税汇算清缴短信
  • dedecms更新
  • Pythonround函数作用
  • 印花税都有什么类目
  • 一般纳税人报税时间每月的多少号
  • 费用没有发票先开什么
  • 固定资产盘亏盘盈
  • 机票报销属于什么科目
  • 银行承兑汇票贴现的账务处理
  • 土地勘测费收费标准
  • 房地产公司房屋租赁管理办法
  • 如果停产怎么计算成本
  • 闲置资产计提折旧
  • 100%直接控制的母子公司之间,母公司向子公司
  • 虚拟模块
  • 242104 税控盘
  • 往来账清账
  • 在查询结果中添加字母
  • sql ntext数据类型字符替换实现代码
  • mysql密码怎么找回
  • 用u盘怎么装系统win10
  • wintogo.exe
  • 怎样打开windows设置页面
  • win10周年更新版是什么意思
  • win8出现问题需要重启
  • ubuntu安装chrom
  • xp系统开机只有一个鼠标箭头
  • qq空间好友评论别人看不到
  • 删除隐藏文件命令
  • centos查看硬件设备
  • pqtray.exe - pqtray 是什么进程 有什么用
  • system的方法
  • win7系统如何查看内存条型号
  • jQuery Password Validation密码验证
  • 遮罩有什么作用
  • 置顶txt
  • AppWidgetProvider使用介绍
  • 用python写随机数
  • [置顶]从lv2开始开挂的原勇者候悠闲的异世界生活
  • js命名函数
  • 安卓自定义app
  • 四川省网上税务局申报流程
  • 构建税务系统纵向到底
  • 税务干部转正工作总结
  • 黄山市国家税务局倪国初
  • 个人所得税年申报与月申报区别
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号