FastDFS一步步搭建存储服务器
忠告:若您不是必须要学习FastDFS(配置贼多),那么则推荐您学习Minio(简洁、功能强大),Minio是主流。
一:FastDFS简介
1:FastDFS简介
FastDFS是一个开源的轻量级分布式文件系统,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了大容量存储和负载均衡的问题。特别适合中小文件(建议范围:4KB < file_size <500MB),对以文件为载体的在线服务,如相册网站、视频网站等。

(1):单机时代 初创时期由于时间紧迫,在各种资源有限的情况下,通常就直接在项目目录下建立静态文件夹,用于用户存放项目中的文件资源。 如果按不同类型再细分,可以在项目目录下再建立不同的子目录来区分。如resources\static\file、resources\static\img等 # 优点:这样做比较便利,项目直接引用就行,实现起来也简单,无需任何复杂技术,保存数据库记录和访问起来也很方便。 # 缺点:如果只是后台系统的使用一般也不会有什么问题,但是作为一个前端网站使用的话就会存在弊端。一方面,文件和代码耦合 在一起,文件越多存放越混乱;另一方面,如果流量比较大,静态文件访问会占据一定的资源,影响正常业务进行,不利于网站 快速发展。 (2):独立文件服务器 随着公司业务不断发展,将代码和文件放在同一服务器的弊端就会越来越明显。为了解决上面的问题引入独立图片服务器,工作 流程如下:项目上传文件时,首先通过ftp或者ssh将文件上传到图片服务器的某个目录下,再通过ngnix或者apache来访问此 目录下的文件,返回一个独立域名的图片URL地址,前端使用文件时就通过这个URL地址读取。 # 优点:图片访问是很消耗服务器资源的(因为会涉及到操作系统的上下文切换和磁盘I/O操作),分离出来后,Web/App服务器 可以更专注发挥动态处理的能力;独立存储,更方便做扩容、容灾和数据迁移;方便做图片访问请求的负载均衡,方便应用各 种缓存策略(HTTP Header、Proxy Cache等),也更加方便迁移到CDN。 # 缺点:单机存在性能瓶颈,容灾、垂直扩展性稍差 (3):分布式文件系统 通过独立文件服务器可以解决一些问题,如果某天存储文件的那台服务突然down了怎么办?可能你会说,定时将文件系统备份, 这台down机的时候,迅速切换到另一台就OK了,但是这样处理需要人工来干预。另外,当存储的文件超过100T的时候怎么办? 单台服务器的性能问题?这个时候我们就应该考虑分布式文件系统了。业务继续发展,单台服务器存储和响应也很快到达了瓶颈, 新的业务需要文件访问具有高响应性、高可用性来支持系统。分布式文件系统,一般分为三块内容来配合,服务的存储、访问的 仲裁系统,文件存储系统,文件的容灾系统来构成,仲裁系统相当于文件服务器的大脑,根据一定的算法来决定文件存储的位置, 文件存储系统负责保存文件,容灾系统负责文件系统和自己的相互备份。 # 优点:扩展能力: 毫无疑问,扩展能力是一个分布式文件系统最重要的特点;高可用性: 在分布式文件系统中,高可用性包含两 层,一是整个文件系统的可用性,二是数据的完整和一致性;弹性存储: 可以根据业务需要灵活地增加或缩减数据存储以及增删 存储池中的资源,而不需要中断系统运行 # 缺点:系统复杂度稍高,需要更多服务器
2:FastDFS系统架构
FastDFS由跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client)构成。
(1)跟踪服务器Tracker Server
主要做调度工作,起到均衡的作用;负责管理所有的 storage server和 group,每个 storage 在启动后会连接 Tracker,告知自己所属 group 等信息,并保持周期性心跳。tracker根据storage的心跳信息,建立group==>[storage serverlist]的映射表。
Tracker需要管理的元信息很少,会全部存储在内存中;另外tracker上的元信息都是由storage汇报的信息生成的,本身不需要持久化任何数据,这样使得tracker非常容易扩展,直接增加tracker机器即可扩展为tracker cluster来服务,cluster里每个tracker之间是完全对等的,所有的tracker都接受stroage的心跳信息,生成元数据信息来提供读写服务。
(2)存储服务器Storage Server
主要提供容量和备份服务;以 group 为单位,每个 group 内可以有多台 storage server,数据互为备份。以group(卷)为单位组织存储能方便的进行应用隔离、负载均衡、副本数定制(group内storage server数量即为该group的副本数),比如将不同应用数据存到不同的group就能隔离应用数据,同时还可根据应用的访问特性来将应用分配到不同的group来做负载均衡;缺点是group的容量受单机存储容量的限制,同时当group内有机器坏掉时,数据恢复只能依赖group内地其他机器,使得恢复时间会很长。
group内每个storage的存储依赖于本地文件系统,storage可配置多个数据存储目录,比如有10块磁盘,分别挂载在/data/disk1-/data/disk10,则可将这10个目录都配置为storage的数据存储目录。storage接受到写文件请求时,会根据配置好的规则选择其中一个存储目录来存储文件。为了避免单个目录下的文件数太多,在storage第一次启动时,会在每个数据存储目录里创建2级子目录,每级256个,总共65536个文件,新写的文件会以hash的方式被路由到其中某个子目录下,然后将文件数据作为本地文件存储到该目录中。
(3)客户端Client
主要是上传下载数据的服务器,也就是我们自己的项目所部署在的服务器。每个客户端服务器都需要安装Nginx
Tracker相当于FastDFS的大脑,不论是上传还是下载都是通过tracker来分配资源;客户端一般可以使用ngnix等静态服务器来调用或者做一部分的缓存;存储服务器内部分为卷(或者叫做组),卷于卷之间是平行的关系,可以根据资源的使用情况随时增加,卷内服务器文件相互同步备份,以达到容灾的目的。
(4)FastDFS的存储策略
为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统中的文件容量。一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。
在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就扩大了存储系统的容量。
(5)FastDFS的上传过程
FastDFS向使用者提供基本文件访问接口,比如upload、download、append、delete等,以客户端库的方式提供给用户使用。
我们知道Storage Server会定期的向Tracker Server发送自己的存储信息。当Tracker Server Cluster中的Tracker Server不止一个时,各个Tracker之间的关系是对等的,所以客户端上传时可以选择任意一个Tracker。
当Tracker收到客户端上传文件的请求时,会为该文件分配一个可以存储文件的group,当选定了group后就要决定给客户端分配group中的哪一个storage server。当分配好storage server后,客户端向storage发送写文件请求,storage将会为文件分配一个数据存储目录。然后为文件分配一个fileid,最后根据以上的信息生成文件名存储文件。文件名的格式如下:
(6)FastDFS的文件同步
写文件时,客户端将文件写至group内一个storage server即认为写文件成功,storage server写完文件后,会由后台线程将文件同步至同group内其他的storage server。
每个storage写文件后,同时会写一份binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式进行记录,所以最好能保证集群内所有server的时钟保持同步。
storage的同步进度会作为元数据的一部分汇报到tracker上,tracke在选择读storage的时候会以同步进度作为参考。
(7)FastDFS的文件下载
客户端uploadfile成功后,会拿到一个storage生成的文件名,接下来客户端根据这个文件名即可访问到该文件。
跟upload file一样,在downloadfile时客户端可以选择任意tracker server。tracker发送download请求给某个tracker,必须带上文件名信息,tracke从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用来服务读请求。
二:搭建FastDFS环境(单机版)
1:基本准备
(1):系统准备
刚重置的腾讯云CentOS 7.6系统
(2):文件准备
①:libfastcommon:是FastDFS文件系统运行需要的公共C语言函数库。
它提供如:字符串、日志、链表、哈希表、网络通信、base64编码/解码等功能
②:libserverframe:高性能网络通信框架。
它用来替换原有的tracker nio和storage nio两个模块。
③:FastDFS:主体文件需要安装部署在Linux环境下。
④:fastdfs-nginx-module:扩展模块,集成Nginx里实现负载均衡等功能
⑤:Nginx:实现负载均衡及文件的访问是用到
⑥:fastdfs-client-java:java客户端基本代码(需maven手动编译,无需部署,它是个jar包)
(3):上传准备的文件,除fastdfs-client-java(jar包)其它全部上传
切换到根目录下上传 个人喜好 cd /home
执行上传命令:rz -y
下载的资源包:
fastdfs-V6.9.5.zip
nginx-1.22.1.tar.gz
libfastcommon-V1.0.69.zip
libserverframe-V1.1.29.zip
fastdfs-client-java-V1.30.zip
fastdfs-nginx-module-V1.23.zip
上传到服务器:
补充:依赖(gcc...)安装及压缩包解压命令说明
检查命令:
yum list installed | grep gcc
yum list installed | grep libevent
yum list installed | grep libevent-devel
安装命令,如果有新版则更新
yum install gcc libevent libevent-devel -y

补充:tar.gz解压缩: 压缩:tar -zcvf demo.tar.gz /home/demo/ 解压:tar -zxvf demo.tar.gz 说明: demo.tar.gz为构建压缩包 /home/demo为要压缩的文件夹 选项说明: -c或--create:建立新的备份文件; -x或--extract或--get:从备份文件中还原文件; -v:显示指令执行过程; -f或--file:指定备份文件; -C:指定目的目录; -z:通过gzip指令处理备份文件; -j:通过bzip2指令处理备份文件。 补充:zip压缩 语法:zip [选项] 压缩包名 源文件或源目录列表 示例:zip -vr new.zip /home/ 说明: new.zip为构建压缩包 /home/为要压缩的文件夹 选项说明: -r:递归压缩目录,及将制定目录下的所有文件以及子目录全部压缩。 -m:将文件压缩之后,删除原始文件,相当于把文件移到压缩文件中。 -v:显示详细的压缩过程信息。 -q:在压缩的时候不显示命令的执行过程。 -u:更新压缩文件,即往压缩文件中添加新文件。 -级别:压缩级别是从 1~9 的数字,-1 代表压缩速度更快,-9 代表压缩效果更好。 补充:unzip解压缩 语法:unzip [选项] 压缩包名 示例:unzip -d /tmp/ ana.zip 把ana.zip压缩包解压到/tmp目录下 选项说明: -d:目录名,将压缩文件解压到指定目录下。 -n:解压时并不覆盖已经存在的文件。 -o:解压时覆盖已经存在的文件,并且无需用户确认。 -v:查看压缩文件的详细信息,包括压缩文件中包含的文件大小、文件名以及压缩比等,但并不做解压操作。 -t:测试压缩文件有无损坏,但并不解压。 -x:文件列表,解压文件,但不包含文件列表中指定的文件
2:安装libfastcommon库
libfastcommon库是FastDFS文件系统运行需要的公共C语言函数库;注意:v1.0.39和FastDFS5.11不兼容
>>解压:
unzip libfastcommon-V1.0.69.zip
>>进入解压后的目录:
cd libfastcommon-V1.0.69/
>>编译解压的文件(这里需要gcc环境)&& 安装编译后的文件
./make.sh && ./make.sh install
>>完成,查询动态链接库是否存在
ll /usr/lib64/ | grep libfastcommon.so
3:安装libserverframe库
>>解压:
unzip libserverframe-V1.1.29.zip
>>进入解压后的目录:
cd libserverframe-V1.1.29/
>>编译解压的文件(这里需要gcc环境)&& 安装编译后的文件
./make.sh && ./make.sh install
>>完成,查询动态链接库是否存在
ll /usr/lib64/ | grep libserverframe.so
4:安装FastDFS主体服务
现在FastDFS没有Windows版本,不能在Windows下使用。FastDFS需要安装部署在Linux环境下>>解压
unzip fastdfs-V6.9.5.zip
>>进入解压后的目录
cd fastdfs-V6.9.5/
>>编译解压的文件 和 安装编译的文件
./make.sh && ./make.sh install
>>检查是否安装了 (安装后命令会存在/usr/bin)
ls /usr/bin | grep fdfs
>>处理FastDFS配置文件
安装FastDFS后会生成了/etc/fdfs配置目录,存放着FastDFS配置;
注:我们需要把之前解压的fastdfs-V6.9.5/conf目录下的两个文件拷贝到安装后产生的/etc/fdfs/目录下,
否则后续会有很多奇怪问题不好解决,文件:http.conf 和 mime.types
cp /home/fastdfs-V6.9.5/conf/http.conf /etc/fdfs
cp /home/fastdfs-V6.9.5/conf/mime.types /etc/fdfs
其它说明:
一些低版本的FastDFS配置目录(/etc/fdfs)里面的配置文件可能是“.sample”结尾的,我们需要剔除这个后缀。
因为这些文件后缀都是 .sample 示例的,所有我们把 .sample后缀都去除
查询安装后的执行文件及配置:
5:修改FastDFS配置 /etc/fdfs/xx.conf
要运行FastDFS服务,就得配置必要的信息,启动tracker服务则需要配置tracker.conf,启动storage服务也需要配置对应文件
(1):负载均衡 tracker.conf 配置文件的配置修改
说明:如果不方便使用vim更改的话,可以使用 rz -y 上传 和 sz file名称 下载的到本地编辑
说明:配置 tracker 存储数据的目录(自定义配置后期tracker产生的数据和日志保存的地方)
配置:base_path = /opt/fastdfs/tracker 注:设置的路径我们必须要手动创建
命令:
# 创建目录
mkdir -p /opt/fastdfs/tracker
# 修改配置文件
vim /etc/fdfs/tracker.conf

# 配置tracker.conf 文件是否生效 false生效 true屏蔽 disabled = false # 程序的监听地址,如果不设定则监听所有地址(0.0.0.0) bind_addr = # tracker监听的端口 port = 22122 # 连接超时时间(秒)。 # 默认值为30。 # 注意:在内网(LAN)中,2秒就足够了。 connect_timeout = 5 # 发送和接收的网络超时时间(秒)。 # 默认值为30 # tracker server的网络超时,单位为秒。发送或接收数据时,如果在超时时间后还不能发送 # 或接收数据,则本次网络通信失败。 network_timeout = 60 # ------------------------------------------------------ # base_path 目录地址(根目录必须存在,子目录会自动创建) # 附目录说明: # tracker server目录及文件结构: # ${base_path} # |__data # | |__storage_groups.dat:存储分组信息 # | |__storage_servers.dat:存储服务器列表 # |__logs # |__trackerd.log:tracker server日志文件 # 数据文件storage_groups.dat和storage_servers.dat中的记录之间以换行符(\n)分隔,字段之间以西文逗号(,)分隔。 # storage_groups.dat中的字段依次为: # 1. group_name:组名 # 2. storage_port:storage server端口号 # # storage_servers.dat中记录storage server相关信息,字段依次为: # 1. group_name:所属组名 # 2. ip_addr:ip地址 # 3. status:状态 # 4. sync_src_ip_addr:向该storage server同步已有数据文件的源服务器 # 5. sync_until_timestamp:同步已有数据文件的截至时间(UNIX时间戳) # 6. stat.total_upload_count:上传文件次数 # 7. stat.success_upload_count:成功上传文件次数 # 8. stat.total_set_meta_count:更改meta data次数 # 9. stat.success_set_meta_count:成功更改meta data次数 # 10. stat.total_delete_count:删除文件次数 # 11. stat.success_delete_count:成功删除文件次数 # 12. stat.total_download_count:下载文件次数 # 13. stat.success_download_count:成功下载文件次数 # 14. stat.total_get_meta_count:获取meta data次数 # 15. stat.success_get_meta_count:成功获取meta data次数 # 16. stat.last_source_update:最近一次源头更新时间(更新操作来自客户端) # 17. stat.last_sync_update:最近一次同步更新时间(更新操作来自其他storage server的同步) base_path = /home/yuqing/fastdfs # 此服务器支持的最大并发连接数。 # 默认值为256 max_connections = 1024 # 接受线程数。 # 默认值为1,推荐使用。 # 从V4.07开始 # 该参数决定接收客户端连接的线程数,默认值为1,适当放大该参数可改善Storage处理连接的能力,改 # 成2[线上环境cpu为32核心可支持足够多的线程数]。 accept_threads = 1 # 工作线程数。 # 处理网络IO的工作线程数。 # 默认值为4。 # 从V2.00开始 # 工作线程用来处理网络IO,默认值为4,该参数影响Stroage可以同时处理的连接数 work_threads = 4 # 最小网络缓冲区大小。 # 默认值8KB # 接收/发送数据的buff大小,必须大于8KB min_buff_size = 8KB # 最大网络缓冲区大小。 # 默认值128KB # 接收/发送数据的buff大小必须小于128KB max_buff_size = 128KB # 在存储文件时选择group的策略。 # 0:轮询。 # 1:指定组。 # 2:负载均衡,选择上传文件的最大可用空间组 store_lookup = 2 # 上传文件到哪组。 # 当 store_lookup设置为1时,必须将 store_group设置为指定上传的组名 store_group = group2 # 上传文件到哪台存储服务器。 # 0:循环(默认)。 # 1:第一台按IP地址排序的服务器。 # 2:根据优先级排序,第一个(最小)。 # 注意:如果 use_trunk_file设置为 true,则必须将 set store_server设置为1或2 store_server = 0 # 选择文件上传到storage中的哪个(目录/挂载点),storage可以有多个存放文件的base # path 0:轮训策略 2:负载均衡,选择空闲空间最大的 store_path = 0 # 选择那个storage作为主下载服务器, # 0:轮训策略 1:主上传storage作为主下载服务器 download_server = 0 # 系统预留空间,当一个group中的任何storage的剩余空间小于定义的值,整个group就不能上传文件了 reserved_storage_space = 20% # 设置日志级别 ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # 进程以那个用户/用户组运行,不指定默认是当前用户 run_by_group= run_by_user = # 允许那些机器连接tracker默认是所有机器 allow_hosts = * # 定时将日志缓冲区同步到磁盘。 # 默认值为10秒 sync_log_buff_interval = 1 # 检测 storage server 存活的时间隔,单位为秒。 # storage server定期向 tracker server 发心跳,如果tracker server在一个check_active_interval # 内还没有收到storage server的一次心跳,那就认为该storage server已经下线。所以本参数值必须大于 # storage server配置的心跳时间间隔。通常配置为storage server心跳时间间隔的2倍或3倍。 check_active_interval = 120 # 线程栈的大小。FastDFS server端采用了线程方式。更正一下, # tracker server线程栈不应小于64KB,不是512KB。 thread_stack_size = 256KB # 存储服务器IP地址更改时自动调整。 # 默认值为true # storage的ip改变后服务端是否自动调整,storage进程重启时才自动调整 storage_ip_changed_auto_adjust = true # 存储同步文件最大延迟秒数。 # 默认值为86400秒(一天)。 # 从V2.00开始 storage_sync_file_max_delay = 86400 # 文件同步最大存储时间。 # 默认值为300秒。 # 从V2.00开始 # 就是存储服务器同步一个文件需要消耗的最大时间,单位为300s,即5分钟。 storage_sync_file_max_time = 300 # 是否使用小文件合并存储特性 [false代表关闭] use_trunk_file = false # 最小插槽大小,应<=4KB。 # 默认值为256字节。 # 从V3.00开始 # trunk file分配的最小字节数。比如文件只有16个字节,系统也会分配 slot_min_size个字节。 slot_min_size = 256 # 最大插槽大小,应>插槽最小大小。 # 当上传文件大小<=此值时,将上传文件存储到主干文件。 # 默认值为16MB。 # 从V3.00开始 # 只有文件大小<=这个参数值的文件,才会合并存储。 # 如果一个文件的大小大于这个参数值,将直接保存到一个文件中(即不采用合并存储方式) slot_max_size = 1MB # 对齐大小越大,磁盘碎片的可能性越小,但浪费的空间也更多。 trunk_alloc_alignment_size = 256 # 是否合并中继文件的连续可用空间 # since V6.05 trunk_free_space_merge = true # files 删除/回收未使用的中继文件 # since V6.05 delete_unused_trunk_files = false # trunk file 大小 # since V3.00 trunk_file_size = 64MB # 是否提前创建 trunk file # since V3.06 trunk_create_file_advance = false # 提前创建trunk file的起始时间点(基准时间),02:00表示第一次创建的时间点是凌晨2点 trunk_create_file_time_base = 02:00 # 创建 trunk file 时间间隔, 86400 即隔一天 trunk_create_file_interval = 86400 # 提前创建trunk file时,需要达到的空闲trunk大小 # 比如本参数为20G,而当前空闲trunk为4GB,那么只需要创建16GB的trunk file即可。 trunk_create_file_space_threshold = 20G # trunk初始化时,是否检查可用空间是否被占用 trunk_init_check_occupying = false # 是否无条件从trunk binlog中加载trunk可用空间信息 # FastDFS缺省是从快照文件storage_trunk.dat中加载trunk可用空间, # 该文件的第一行记录的是trunk binlog的offset,然后从binlog的offset开始加载 trunk_init_reload_from_binlog = false # 压缩 trunk binlog 文件的最小间隔 trunk_compress_binlog_min_interval = 86400 # 压缩 trunk binlog 文件的间隔时间 (默认1天) trunk_compress_binlog_interval = 86400 # 压缩 trunk binlog 文件的时间点 trunk_compress_binlog_time_base = 03:00 # trunk binlog 文件最大备份数 trunk_binlog_max_backups = 7 # 是否使用server ID作为storage server标识 use_storage_id = false # 指定存储ID文件名,可以使用相对路径或绝对路径。 # 只有当use_storage_id设置为true时,该参数才有效。 storage_ids_filename = storage_ids.conf # 文件名中存储服务器的#id类型,值为: ## IP:存储服务器的IP地址。 ## id:存储服务器的服务器id。 # 仅当use_storage_id设置为true时,此参数才有效。 # 默认值为ip。 # since V4.03 id_type_in_filename = id # 存储从文件是否使用符号链接 store_slave_file_use_link = false # 是否定期轮转error log,目前仅支持一天轮转一次 rotate_error_log = false # error log定期轮转的时间点,只有当rotate_error_log设置为true时有效 error_log_rotate_time = 00:00 # 是否压缩旧的错误日志 compress_old_error_log = false # 压缩几天前的错误日志 (compress_old_error_log = false本参数不生效) compress_error_log_days_before = 7 # 当日志文件超过此大小时轮换错误日志。 # 设置为0表示不按文件大小轮转,否则当error log达到该大小,就会轮转到新文件中 rotate_error_log_size = 0 # 日志文件保留几天(0代表永久保留) log_file_keep_days = 0 # 是否使用连接池 use_connection_pool = true # 连接空闲时长,超过则连接被关闭 (单位秒) connection_pool_max_idle_time = 3600 # 此跟踪器服务器上的HTTP端口 http.server_port = 8080 # 检查存储HTTP服务器活动间隔秒数。 # <=0表示从不检查。 # 默认值为30 http.check_alive_interval = 30 # 检查存储HTTP服务器活动类型,值为: # TCP:仅使用HTTP端口连接到存储服务器。 # 不请求,不获取响应。 # http:存储检查活动url必须返回http状态200。 # 默认值为tcp http.check_alive_type = tcp # 检查存储HTTP服务器活动uri/url。 # 注意:Storage Embedded HTTP服务器支持uri:/status.html http.check_alive_uri = /status.html
(2):文件存储服务器 storage.conf 配置文件的配置修改
配置storage.conf是指定后期运行产生的数据和真实的文件存储位置,注:设置的路径我们必须手动创建 需要更改的配置: ①:配置storage存储数据的目录(我这里随便自定义) base_path = /opt/fastdfs/storage ②:配置真正存放文件的目录(我这里随便自定义) store_path0 = /opt/fastdfs/storage/files ③:配置当前存储节点的跟踪器地址(就是tracker的地址) tracker_server = 49.235.99.193:22122 命令: # 创建目录 mkdir -p /opt/fastdfs/storage mkdir -p /opt/fastdfs/storage/files # 修改配置文件 vim /etc/fdfs/storage.conf

# 配置storage.conf 文件是否生效 false生效 true屏蔽 disabled = false # 该存储服务器所属的组名。 # 注释或删除此项目以从跟踪器服务器获取, # 在这种情况下,tracker.conf中的use_storage_id必须设置为true。 # 和storage_ids.conf必须正确配置。 group_name = group1 # 程序的监听地址,如果不设定则监听所有地址(0.0.0.0) bind_addr = # bind_addr通常是针对server的。当指定bind_addr时,本参数才有效。 # 本storage server作为client连接其他服务器(如tracker server、 # 其他storage server),是否绑定bind_addr。 client_bind = true # storage 默认端口 port = 23000 # 连接超时时间(秒)。 # 默认值为30。 # 注意:在内网(LAN)中,2秒就足够了。 connect_timeout = 5 # 发送和接收的网络超时时间(秒)。 # 默认值为30 network_timeout = 60 # 心跳间隔(秒)。 # 存储服务器定期向Tracker服务器发送心跳。 # 默认值为30 heart_beat_interval = 30 # 磁盘使用情况报告间隔(秒)。 # 存储服务器定期向Tracker服务器发送磁盘使用情况报告。 # 默认值为300 stat_report_interval = 60 # 数据存储目录地址 base_path = /home/yuqing/fastdfs # 最大连接数 max_connections = 1024 # 设置队列结点的buffer大小。工作队列消耗的内存大小 = buff_size * max_connections # 设置得大一些,系统整体性能会有所提升。 buff_size = 256KB # 接收数据的线程数 accept_threads = 1 # 工作线程数,一般为cpu个数,当然CPU核数太多的话可以稍小一点。如我们是12CPU,这里设置为8 work_threads = 4 # 磁盘IO读写是否分离。磁盘读/写分离为false则为混合读写, # 如果为true则为分离读写的。默认值为V2.00以后为true。 disk_rw_separated = true # 针对单个存储路径的读线程数,默认值为1。 # 读写分离时: # 系统中的读线程数 = disk_reader_threads * store_path_count # 读写混合时: # 系统中的读写线程数 = (disk_reader_threads + disk_writer_threads) * store_path_count disk_reader_threads = 1 # 针对单个存储路径的写线程数,默认值为1。 # 读写分离时: # 系统中的写线程数 = disk_writer_threads * store_path_count # 读写混合时: # 系统中的读写线程数 = (disk_reader_threads + disk_writer_threads) * store_path_count disk_writer_threads = 1 # 同步文件时,如果从binlog中没有读到要同步的文件,休眠N毫秒后重新读取。0表示不休眠,立即再次尝试读取。 # 出于CPU消耗考虑,不建议设置为0。如何希望同步尽可能快一些,可以将本参数设置得小一些,比如设置为10ms sync_wait_msec = 50 # 同步上一个文件后,再同步下一个文件的时间间隔,单位为毫秒,0表示不休眠,直接同步下一个文件。 sync_interval = 0 # 下面二个一起解释。允许系统同步的时间段 (默认是全天) 。一般用于避免高峰同步产生一些问题而设定 sync_start_time = 00:00 sync_end_time = 23:59 # 同步 N 个文件后就写入标记文件 write_mark_file_freq = 500 # 硬盘恢复线程数 disk_recovery_threads = 3 # storage在存储文件时支持多路径,默认只设置一个 store_path_count = 1 # store_path(0~⚮),根据0配置存储文件的存储路径。 # 如果store_path0不存在,则取值为base_path(不推荐)。 # 路径必须存在 store_path0 = /home/yuqing/fastdfs #store_path1 = /home/yuqing/fastdfs2 # subdir_count * subdir_count个目录会在store_path下创建,采用两级存储 subdir_count_per_path = 256 # 设置tracker_server 服务器地址 多个代表多个Tracker集群 tracker_server = 192.168.209.121:22122 tracker_server = 192.168.209.122:22122 # 日志级别 ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # 进程以那个用户/用户组运行,不指定默认是当前用户 run_by_group = run_by_user = # 允许那些机器连接tracker默认是所有机器 allow_hosts = * # 文件分发到数据路径的方式。 # 0: 轮流存放,在一个目录下存储设置的文件数后 #(参数file_distribute_rotate_count中设置文件数),使用下一个目录进行存储。 # 1: 随机存储,根据文件名对应的hash code来分散存储。 file_distribute_path_mode = 0 # 当上面的参数file_distribute_path_mode配置为0(轮流存放方式)时,本参数有效。 # 当一个目录下的文件存放的文件数达到本参数值时,后续上传的文件存储到下一个目录中。 file_distribute_rotate_count = 100 # 当写入大文件时,每写入N个字节,调用一次系统函数fsync将内容强行同步到硬盘。0表示从不调用fsync fsync_after_written_bytes = 0 # 同步或刷新日志信息到硬盘的时间间隔,单位为秒 # 注意:storage server 的日志信息不是时时写硬盘的,而是先写内存。 sync_log_buff_interval = 1 # 同步binglog(更新操作日志)到硬盘的时间间隔,单位为秒 # 本参数会影响新上传文件同步延迟时间 sync_binlog_buff_interval = 1 # 把storage的stat文件同步到磁盘的时间间隔,单位为秒。 # 注:如果stat文件内容没有变化,不会进行同步 sync_stat_file_interval = 300 # 线程栈大小,线程栈越大,一个线程占用的系统资源就越多。 thread_stack_size = 512KB # 本storage server作为源服务器,上传文件的优先级,可以为负数。值越小, # 优先级越高。这里就和 tracker.conf 中store_server= 2时的配置相对应了 upload_priority = 10 # 网卡别名,用ifconfig -a可以看到很多本机的网卡别名,类似eth0,eth0:0等等。 # 多个网卡别名使用逗号分割,默认为空,让系统自动选择。 if_alias_prefix = # 是否检测上传文件已经存在。如果已经存在,则不存在文件内容,建立一个符号链接以节省磁盘空间。 # 这个应用要配合FastDHT 使用,所以打开前要先安装FastDHT # 1或yes 是检测,0或no 是不检测 check_file_duplicate = 0 # 文件去重时,文件内容的签名方式: ## hash:4个hash code ## md5:MD5 file_signature_method = hash #当check_file_duplicate设置为1时,此值必须设置 key_namespace = FastDFS # FastDHT建立连接的方式 0:短连接 1:长连接 keep_alive = 0 # 是否将文件操作记录到access log use_access_log = false # 是否定期轮转access log,目前仅支持一天轮转一次 rotate_access_log = false # access log定期轮转的时间点,只有当rotate_access_log设置为true时有效 access_log_rotate_time = 00:00 # 是否压缩旧的访问日志 compress_old_access_log = false # 压缩几天前的访问日期 compress_access_log_days_before = 7 # 是否每天轮转错误日志 rotate_error_log = false # 错误日志轮转时间 error_log_rotate_time = 00:00 # 压缩旧的错误日志 compress_old_error_log = false # 压给它几天前的错误日志 compress_error_log_days_before = 7 # access log按文件大小轮转 # 设置为0表示不按文件大小轮转,否则当access log达到该大小,就会轮转到新文件中 rotate_access_log_size = 0 # error log按文件大小轮转 # 设置为0表示不按文件大小轮转,否则当error log达到该大小,就会轮转到新文件中 rotate_error_log_size = 0 # 保留日志文件的日期0表示不删除旧的日志文件 log_file_keep_days = 0 # 文件同步的时候,是否忽略无效的binlog记录 file_sync_skip_invalid_record = false # 是否使用连接池 use_connection_pool = true # 连接的空闲时间超过这个时间将被关闭,单位:秒 connection_pool_max_idle_time = 3600 # 是否使用gzip压缩二进制日志文件 compress_binlog = true # 压给它二进制日志时间点 compress_binlog_time = 01:30 # 是否检查存储路径的标记以防止混淆,建议开启,如果两个服务使用 # 一个相同的存储路径,此参数要设置为 false check_store_path_mark = true # 服务域名, 如果为空则表示使用 IP 地址 http.domain_name = # http 端口 http.server_port = 8888
5:启动FastDFS服务
我们修改好配置后,并且在配置文件配置的文件路径也被我们手动创建后就可以来启动服务了
(1):关于启动关闭的一些命令
①:启动Tracker追踪器服务
fdfs_trackerd /etc/fdfs/tracker.conf
②:启动Storage存储服务器服务
fdfs_storaged /etc/fdfs/storage.conf
③:重启
fdfs_trackerd /etc/fdfs/tracker.conf restart
fdfs_storaged /etc/fdfs/storage.conf restart
④:关闭
fdfs_trackerd /etc/fdfs/tracker.conf stop
fdfs_storaged /etc/fdfs/storage.conf stop
(2):查询tracker文件下是否被自动创建了data和log文件
(3):查询storage文件下是否自动创建了data和log和files具体文件路径
ls /opt/fastdfs/tracker/
ls /opt/fastdfs/storage/
ls /opt/fastdfs/storage/files/
ls /opt/fastdfs/storage/files/data/
6:FastDFS测试上传、删除
我们完成了上面的配置后并且也可以运行服务后,就可以来测试我们的FastDFS是否存在问题了。
在测试前我们需要配置一个/etc/fdfs/client.conf的文件,后期用这个配置文件测试
需要更改的配置:
配置client存储数据的目录(我这里随便自定义):
base_path = /opt/fastdfs/client 注:别忘了把文件夹创建出来
配置当前存储节点的跟踪器地址(就是tracker):
tracker_server = 49.235.99.193:22122
配置Nginx访问端口,若未改变则无需设置,默认80端口了;(用作上传成功后生成具体的http访问地址)
http.tracker_server_port = 80
命令:
# 创建目录
mkdir -p /opt/fastdfs/client
# 修改配置文件
vim /etc/fdfs/client.conf

# 连接的超时时间 connect_timeout = 5 # 网络超时(秒),默认值 60s network_timeout = 60 # 存储日志文件的基本路径 base_path = /home/yuqing/fastdfs # tracker server的列表 多个tracker就设置多个 tracker_server = 192.168.0.196:22122 tracker_server = 192.168.0.197:22122 # 日志级别 ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # 是否使用连接池 use_connection_pool = false # 连接的空闲时间超过这个时间将被关闭,单位:秒 connection_pool_max_idle_time = 3600 # 是否加载来自跟踪服务器的FastDFS参数,默认值为false。这里可以设置为true。 load_fdfs_parameters_from_tracker = false # 是否使用storage id替换ip作为storage server标识,默认为false use_storage_id = false # 在文件中设置组名、server ID和对应的IP地址 storage_ids_filename = storage_ids.conf # 端口 http.tracker_server_port = 80
测试需要使用到 fdfs_test 命令来完成测试:
①:上传文件:
命令语法:fdfs_test /etc/fdfs/client.conf upload 上传的文件名称
示例:fdfs_test /etc/fdfs/client.conf upload demo.txt
②:查询目录(我上传的文件在./00/00目录里):
ll /opt/fastdfs/storage/files/data/00/00/
打印:
-rw-r--r-- 1 root root 0 9月 6 21:58 MetjwWT4hZyATCumAAAAAAAAAAA699_big.txt
-rw-r--r-- 1 root root 49 9月 6 21:58 MetjwWT4hZyATCumAAAAAAAAAAA699_big.txt-m
-rw-r--r-- 1 root root 0 9月 6 21:58 MetjwWT4hZyATCumAAAAAAAAAAA699.txt
-rw-r--r-- 1 root root 49 9月 6 21:58 MetjwWT4hZyATCumAAAAAAAAAAA699.txt-m
说明:
在FastDFS中,这些后缀通常用于标识不同的文件副本,如下说明:
MetjwWT4hZyATCumAAAAAAAAAAA699_big.txt -- 从文件
MetjwWT4hZyATCumAAAAAAAAAAA699_big.txt-m -- 从属性文件
MetjwWT4hZyATCumAAAAAAAAAAA699.txt -- 主文件(就是我们上传的原文件)
MetjwWT4hZyATCumAAAAAAAAAAA699.txt-m -- 主属性文件
③:查询上传的文件信息
目录语法:fdfs_file_info /etc/fdfs/client.conf 存储成功的文件路径
示例:fdfs_file_info /etc/fdfs/client.conf group1/M00/00/00/MetjwWT4hZyATCumAAAAAAAAAAA699_big.txt
打印:
GET FROM SERVER: true -- 表示从服务器获取的值为true
file type: slave -- 这里标识为从节点(slave)
source storage id: 0 -- 由于这是一个从节点,源存储ID为0。
source ip address: 49.235.99.193 -- 指示文件所在的源IP地址
file create timestamp: 2023-09-06 21:58:52 -- 文件创建时间戳
file size: 0 -- 文件的大小为0,因为我创建的是空文件
file crc32: 0 (0x00000000) -- 文件的CRC32校验值为0(0x00000000)
④:删除文件:
命令语法:fdfs_delete_file /etc/fdfs/client.conf 要删除的文件名称
示例删除主文件和从文件:
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/MetjwWT4hZyATCumAAAAAAAAAAA699.txt
fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/MetjwWT4hZyATCumAAAAAAAAAAA699_big.txt
三:分布式文件系统之FastDFS的HTTP访问
在文件上传的时候,上传成功的信息中有提示我们可以通过某个路径去访问上传的文件,但是我们直接访问这个路径,却不可以,那么已经上传到FastDFS文件系统中的文件,我们如何在浏览器中访问呢?FastDFS提供了一个Nginx扩展模块,利用该模块,我们可以通过Nginx访问已经上传到FastDFS上的文件
1:安装Nginx并添加fastDFS第三方模块
安装Nginx环境检查:
gcc编译器是否安装
检查是否安装:yum list installed | grep gcc
执行安装:yum install gcc -y
openssl库是否安装
检查是否安装:yum list installed | grep openssl
执行安装:yum install openssl openssl-devel -y
pcre库是否安装
检查是否安装:yum list installed | grep pcre
执行安装:yum install pcre pcre-devel -y
zlib库是否安装
检查是否安装:yum list installed | grep zlib
执行安装:yum install zlib zlib-devel -y
全安装:
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y
>>解压集成Nginx的负载均衡压缩包
unzip fastdfs-nginx-module-V1.23.zip
>>解压Nginx压缩包:
tar -zxvf nginx-1.22.1.tar.gz
>>进入Nginx目录
cd nginx-1.22.1/
>>生成Makefile可编译文件
./configure --with-http_ssl_module --add-module=/home/fastdfs-nginx-module-V1.23/src
说明:
--prefix=PATH:指定nginx的安装目录(默认/usr/local/nginx)
--with-http_ssl_module:启动SSL的支持
--add-module=PATH:添加第三方外部模块(这里添加了FastDFS集成Nginx负载均衡模块)
>>编译源码&&安装
make && make install
>>关于Nginx的服务配置(这里可以参考这篇Nginx安装)
注:执行此命令前面不能存在空格
cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx reload
ExecStop=/usr/local/nginx/sbin/nginx quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
2:配置Nginx访问设置
①:拷贝模块文件到/etc/fdfs
把扩展模块fastdfs-nginx-module-master/src里的mod_fastdfs.conf文件拷贝到/etc/fdfs/目录下,才可以正常启动Nginx
拷贝文件:
cp /home/fastdfs-nginx-module-V1.23/src/mod_fastdfs.conf /etc/fdfs
②:修改拷贝过来的配置文件
配置存储运行产生的日志数据等等 注:文件路径必须存在
base_path = /opt/fastdfs/nginx_mod
设置tracker服务地址
tracker_server = 49.235.99.193:22122
设置文件url中是否有group名
url_have_group_name = true
文件数据存储路径
store_path0 = /opt/fastdfs/storage/files
命令:
# 构建目录及修改文件
mkdir -p /opt/fastdfs/nginx_mod
vim /etc/fdfs/mod_fastdfs.conf
③:修改Nginx配置文件
完成上面,我们就得开始配置我们的Nginx配置了,Nginx配置默认在/usr/local/nginx/conf/nginx.conf
命令:
vim /usr/local/nginx/conf/nginx.conf
添加如下配置:
#拦截请求路径中包含 /group[1-9]/M[0-9][0-9] 的请求,用 fastdfs的Nginx 模块进行转发
location ~ /group[1-9]/M[0-9][0-9] {
ngx_fastdfs_module;
}
说明ngx_fastdfs_module:这个指令不是Nginx本身提供的,是扩展模块提供的,根据这个指令找到FastDFS提供
的Nginx模块配置文件,然后找到Tracker,最终找到Stroager
④:运行Nginx服务
systemctl enable nginx.service # 加入到开机自启动(必须先执行)
systemctl status nginx # 查询状态
systemctl start nginx # 启动
systemctl stop nginx # 关闭
systemctl restart nginx # 重启
Nginx启动后上传一个文件后,上传成功后会在最后一行给我们返回一个带http的URL,我们直接在浏览器就可以访问,但须开启80端口;如返回的URL:http://49.235.99.193/group1/M00/00/00/MetjwWT4qqCARMnIAAAAKdxQoRw870_big.txt

# 连接超时(秒)默认值为30s connect_timeout=2 # 网络接收和发送超时(秒)默认值为30s network_timeout=30 # 存储日志文件的基本路径 base_path=/opt/fastdfs/nginx_mod # 是否从tracket服务器读取信息 load_fdfs_parameters_from_tracker=true # 当load_fdfs_parameters_from_tracker设置为false时, 本参数生效。 # 同步文件最大延迟时间, 与tracker.conf文件中参数相同, 默认是一天。 storage_sync_file_max_delay = 86400 # 当load_fdfs_parameters_from_tracker设置为false时, 本参数生效。是否使用storage_id use_storage_id = false # 当load_fdfs_parameters_from_tracker设置为false时, 本参数生效。是否使用storage_id storage_ids_filename = storage_ids.conf # 配置一个或者多个tracker服务器, 从tracker服务器读取信息。 # 当load_fdfs_parameters_from_tracker设置为true时, 本参数生效。 tracker_server=www.antladdie.asia:22122 # storage服务器端口号 storage_server_port=23000 # 卷/组名 group_name=group1 # url链接中是否包含组名 url_have_group_name = true # 存储路径数量, 必须和storage.conf文件一致 store_path_count=1 # 存储路径地址、必须和storage.conf文件一致 store_path0=/opt/fastdfs/storage/files #store_path1=/home/yuqing/fastdfs1 # 标准日志级别为syslog,不区分大小写,值列表: ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level=info # 设置日志文件名,例如 /usr/local/apache2/logs/mod_fastdfs.log # 设置日志的名称, 为空则记录到 http服务的错误日志里 log_filename= # 当文件在本地不存在时怎样回应 # proxy代理, 从其它存储服务器获取内容, 然后发送给客户 # redirect重定向原始存储服务器的http头 response_mode=proxy # 多种别名用逗号分隔, 空值表示自动设置系统类型。这个参数用于得到本机的所有ip。 if_alias_prefix= # 用#include指令, 包含http配置文件。注意: #include这是一个包含指令, 不要删除include前面的 # #include http.conf # 是否支持flv文件,默认不支持 flv_support = true # flv文件的扩展名, 默认是flv flv_extension = flv # 设置组的数量 # 设置非0,支持多个group组在这个存储服务器上 # 设置0为只有一个组 # 如果服务器上多个组, 组的设置, 就像这样: [group1], [group2], ..., [groupN] # 默认是0,一组 group_count = 0 # 当在此存储服务器上支持多组时,请取消对以下部分的注释 # 组1的设置 #[group1] #group_name=group1 #storage_server_port=23000 #store_path_count=2 #store_path0=/home/yuqing/fastdfs #store_path1=/home/yuqing/fastdfs1 # 组2的设置 #[group2] #group_name=group2 #storage_server_port=23000 #store_path_count=1 #store_path0=/home/yuqing/fastdfs
3:在已经存在的Nginx上配置FastDFS插件
话说,上面的第1是基于Nginx服务不存在的情况下进行安装配置,在安装的时候并添加第三方插件的,但是大部分服务器上都是已经存在Nginx服务的,这时我们就需要在已经存在的Nginx上配置第三方插件。
对已经安装的Nginx进行一些特殊配置,添加第三方模块:--add-module属性
①:找到之前已经解压的Nginx目录(若删除了就需要再解压一个Nginx)
# 我的解压后Nginx位置
cd /home/nginx-1.22.1/
②:执行命令
# 解压第三方要安装的模块,我的模块解压位置:/home/fastdfs-nginx-module-V1.23/src/
./configure --add-module=/home/fastdfs-nginx-module-V1.23/src/
③:执行编译
# 编译(注意这样就不用make install了)
make
④:复制编译后的可执行文件到Nginx安装目录
# 注意路径
# /home/nginx-1.22.1/objs/nginx为新编译的可执行文件,需要替换之前的可执行文件
# 注意:替换前先备份之前的nginx可执行文件,以防失败
# 记得还得关闭Nginx,否则会提示文件被占用
cp /home/nginx-1.22.1/objs/nginx /usr/local/nginx/sbin/
最后一步就是按照上面的第2节:配置Nginx访问设置 来配置一遍
四:使用域名+SSL配置方式
从上面的案例中我们都是使用的IP方式,但是没人能保证后期的IP改变而需要依次修改我们之前配置的IP;所以下面我将使用域名的方式来配置,但在演示之前需要提前申请域名和SSL证书(证书推荐申请正规的CA证书;但是自己生成的签名证书也行,但就是不安全)
1:申请域名和SSL证书
关于这些信息申请我都使用的腾讯云,其它的云服务器厂商申请都差不多,我在这里只是简单提一下大概申请。
①:这里我提前注册了一个测试域名,并已经备案,备案大概5天左右
②:添加域名解析,把域名绑定到云服务器上。
③:关于SSL证书申请,我们可以申请免费的,有免费名额
2:配置FastDFS已经Nginx绑定SSL访问
①:修改Linux的域名解析,修改文件/etc/hosts
vim /etc/hosts
把ip和域名设置到底部:
49.235.99.193 www.antladdie.asia
②:修改storage.conf配置文件
# 修改配置文件
vim /etcfs/storage.conf
把tracker_server修改带域名的方式,如:
tracker_server = www.antladdie.asia:22122
③:修改client.conf配置文件(主要用于Linux上命令测试)
# 修改配置文件
vim /etcfs/client.conf
把tracker_server修改带域名的方式,如:
tracker_server = www.antladdie.asia:22122
④配置Nginx的https方式(注意下面的配置设置在http{...}里面)
server {
# SSL访问端口号为443
listen 443 ssl;
# 填写绑定证书的域名
server_name cloud.tencent.com;
# 证书文件名称(一般crt或pem格式...)和私钥文件名称(一般key格式...)
ssl_certificate /usr/localinx/ssl/antladdie.asia_bundle.crt;
ssl_certificate_key /usr/localinx/ssl/antladdie.asia.key;
ssl_session_timeout 5m;
# 请按照以下协议配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# 请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
#网站主页路径。此路径仅供参考,具体请您按照实际目录操作。
root html;
index index.html index.htm;
}
# 拦截请求路径中包含 /group[1-9]/M[0-9][0-9] 的请求,用 fastdfs的Nginx 模块进行转发
location ~ /group[1-9]/M[0-9][0-9] {
ngx_fastdfs_module;
}
}
重启上面的FastDFS服务和Nginx服务并访问测试地址:
http://49.235.99.193:8888/group1/M00/00/00/MetjwWUbtxOAODIvAFPt9uDrhUk639.mp4
http://www.antladdie.asia:8888/group1/M00/00/00/MetjwWUbtxOAODIvAFPt9uDrhUk639.mp4
https://www.antladdie.asia/group1/M00/00/00/MetjwWUbtxOAODIvAFPt9uDrhUk639.mp4
五:FastDFS在Java项目中开发
在真实开发中我们肯定不会使用如 fdfs_test 命令来上传文件,通常使用java代码来编写指定的上传代码,但是我们想使用得要一个jar工具包,就是我们最初下载的 fastdfs-client-java-V1.30.zip ,由于下载的是源码,我们要使用 maven 的 mvn 命令编译一下即可
1:编译源码来生成jar包
安装过后就会出现到你的maven仓库了..\org\csource\fastdfs-client-java
2:基本代码编写
导入之前编译的jar包
<!--导入FastDFS客户端jar包,这个jar包是根据源码编译的--> <dependency> <groupId>org.csource</groupId> <artifactId>fastdfs-client-java</artifactId> <version>1.30-SNAPSHOT</version> </dependency>
完成了pom.xml文件的编写,我们就去resource下创建一个fastdfs.conf的配置文件指定tracker地址
tracker_server = 49.235.99.193:22122

public class Test { public static void main(String[] args) { //上传 //upload(); //下载 //download(); //删除 delete(); } //上传方法 //注意22122 23000端口的开放 public static void upload() { try { //加载配置文件 ClientGlobal.init("fastdfs.conf"); //创建 TrackerClient跟踪器客户端 TrackerClient trackerClient = new TrackerClient(); //通过 TrackerClient跟踪器客户端 获取 TrackerServer跟踪器服务端 TrackerServer trackerServer = trackerClient.getTrackerServer(); //通过 TrackerClient跟踪器客户端 获取 StorageServer存储服务器服务端 StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer); //创建存储服务器客户端 StorageClient storageClient = new StorageClient(trackerServer, storeStorage); //开始上传 // 第一个参数文件路径,也可以是二进制数组 // 第二个参数是文件类型 String[] strings = storageClient.upload_file("h:\\1.jpg", "jpg", null); for (String str : strings) { System.out.println(str); //打印: // group1 // M00/00/00/dx1E0WArsfeAWVTvAAEoDtcZimw368.jpg } //关闭资源 storageClient.close(); } catch (IOException | MyException e) { e.printStackTrace(); } } //下载 public static void download() { try { //加载配置文件 ClientGlobal.init("fastdfs.conf"); //创建 TrackerClient跟踪器客户端 TrackerClient trackerClient = new TrackerClient(); //通过 TrackerClient跟踪器客户端 获取 TrackerServer跟踪器服务端 TrackerServer trackerServer = trackerClient.getTrackerServer(); //通过 TrackerClient跟踪器客户端 获取 StorageServer存储服务器服务端 StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer); //创建存储服务器客户端 StorageClient storageClient = new StorageClient(trackerServer, storeStorage); //开始下载 byte[] bytes = storageClient.download_file("group1", "M00/00/00/dx1E0WArsfeAWVTvAAEoDtcZimw368.jpg"); //写出文件 new FileOutputStream("H:\\downloadfile.jpg").write(bytes); //关闭资源 storageClient.close(); } catch (IOException | MyException e) { e.printStackTrace(); } } //删除 public static void delete() { try { //加载配置文件 ClientGlobal.init("fastdfs.conf"); //创建 TrackerClient跟踪器客户端 TrackerClient trackerClient = new TrackerClient(); //通过 TrackerClient跟踪器客户端 获取 TrackerServer跟踪器服务端 TrackerServer trackerServer = trackerClient.getTrackerServer(); //通过 TrackerClient跟踪器客户端 获取 StorageServer存储服务器服务端 StorageServer storeStorage = trackerClient.getStoreStorage(trackerServer); //创建存储服务器客户端 StorageClient storageClient = new StorageClient(trackerServer, storeStorage); //开始删除 int result = storageClient.delete_file("group1", "M00/00/00/dx1E0WArsfeAWVTvAAEoDtcZimw368.jpg"); System.out.println(result == 0 ? "删除成功" : "删除失败"); //0成功,返回其它数字都是失败 //关闭资源 storageClient.close(); } catch (IOException | MyException e) { e.printStackTrace(); } } }
六:开启token认证(防盗链)
在之前我们上传文件后会发现,任何人拿到地址都可以在浏览器上访问,但是我不想让任何人都可以访问,那么我们就可以对地址进行加签(加token);每个地址都有请求的URL参数,一旦过期,那么之前的地址将无法访问到具体的资源文件。

# HTTP默认内容类型 http.default_content_type = application/octet-stream # MIME类型映射文件名;默认MIME类型文件格式:mime.types扩展名 http.mime_types_filename = mime.types # 设置为true表示开启token验证 http.anti_steal.check_token = true # 设置token失效的时间单位为秒(s) http.anti_steal.token_ttl = 900 # 密钥,跟java客户端配置文件的fastdfs.http_secret_key保持一致 http.anti_steal.secret_key = FastDFS1234567890 # 如果token检查失败,返回的页面(可以自定义一个无权限的http页面) http.anti_steal.token_check_fail = /home/yuqing/fastdfs/conf/anti-steal.jpg # HTTP范围是否支持多个区域,则默认值为true http.multi_range.enabed = true
修改如下的配置(添加权限校验)
修改http.conf配置文件(修改完重启Nginx): # 修改配置文件 vim /etc/fdfs/http.conf 如下修改: # 开启token验证 http.anti_steal.check_token = true # token密钥 http.anti_steal.secret_key = FastDFS1234567890 # 权限校验失败跳转的资源 http.anti_steal.token_check_fail = /etc/fdfs/403.html # 403.html <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>403 html</title> </head> <body> <h1 style="color:#f00;text-align: center">您无权限访问当前资源!</h1> </body> </html>
上传一个资源使用普通无token的方式访问则会显示400,下面我们就使用java方式生成带token的链接:
public static void main(String[] args) { try { // 地址信息 String group = "group1"; String uri = "M00/00/00/MetjwWUb4PqAViNQAFPt9uDrhUk324.mp4"; // 获取时间秒信息 int lts = (int) (System.currentTimeMillis() / 1000); // 对url进行加签操作 String token = ProtoCommon.getToken(uri, lts, "FastDFS1234567890"); System.out.println(group + "/" + uri + "?token=" + token + "&ts=" + lts); } catch (UnsupportedEncodingException | NoSuchAlgorithmException | MyException e) { throw new RuntimeException(e); } } // 打印:group1/M00/00/00/MetjwWUb4PqAViNQAFPt9uDrhUk324.mp4?token=bd584018d76611c4af691300407c1773&ts=1696326376 // 拼接前缀:https://www.antladdie.asia/
生成的后缀不可随意修改,若修改或token过期则会弹出之前配置的无权限页面
七:二次工具类封装
针对FastDFS官方提供的JavaClient工具虽然好用,但是我基于我们的项目对官方提供的工具类二次封装,在这里我将分析出来;具体使用介绍请参考Gitee内的介绍。
https://gitee.com/antLaddieStudy/FastDFS-Tools(FastDFS工具类)
八:FastDFS集群方式搭建
我们在熟练搭建单机的FastDFS后,再搭建集群,本次搭建集群采用6台服务器,2台tracker和4台storage(双组),搭建集群的步骤和搭建单机的步骤是一样的,只是把tracker的IP地址换成集群的IP,然后把storage的IP地址换成集群的IP,这样就搭建了集群。
在搭建集群时我们会参考之前单机的搭建方式,只是在一些配置上进行一些修改,下面就是搭建集群时使用的机器IP说明:
FastDFS服务器规划:
(1): 192.168.153.170 跟踪服务器1(Tracker-01)
(2): 192.168.153.182 跟踪服务器2(Tracker-02)
(3): 192.168.153.183 存储服务器1(Storage-group1-01)
(4): 192.168.153.184 存储服务器2(Storage-group1-02)
(5): 192.168.153.185 存储服务器3(Storage-group2-01)
(6): 192.168.153.186 存储服务器4(Storage-group2-02)
本次集群部署采用Centos7.6系统
正式安装FastDFS集群方式:
注意防火墙需要放行指定端口:
直接关闭防火墙:systemctl stop firewalld
查看防火墙状态:systemctl status firewalld
Ⅰ:相关安装包准备并上传到服务器
这里我准备的安装包名称(我默认都放在/home目录下):
fastdfs-V6.9.5.zip
nginx-1.22.1.tar.gz
libfastcommon-V1.0.69.zip
libserverframe-V1.1.29.zip
fastdfs-nginx-module-V1.23.zip
Ⅱ:服务器环境准备(保证如gcc编译环境存在)
yum install gcc openssl openssl-devel pcre pcre-devel zlib zlib-devel –y
Ⅲ:6台服务器都安装libfastcommon、libserverframe、fastDFS程序
具体安装作用请参考上面的单机搭建介绍
①:libfastcommon安装
cd /home
unzip libfastcommon-V1.0.69.zip
cd libfastcommon-V1.0.69/
./make.sh && ./make.sh install
ll /usr/lib64/ | grep libfastcommon.so
②:libserverframe安装
cd /home
unzip libserverframe-V1.1.29.zip
cd libserverframe-V1.1.29/
./make.sh && ./make.sh install
ll /usr/lib64/ | grep libserverframe.so
③:fastDFS安装
cd /home
unzip fastdfs-V6.9.5.zip
cd fastdfs-V6.9.5/
./make.sh && ./make.sh install
ls /usr/bin | grep fdfs
cp /home/fastdfs-V6.9.5/conf/http.conf /etc/fdfs
cp /home/fastdfs-V6.9.5/conf/mime.types /etc/fdfs
Ⅳ:配置tracker服务器(此集群我们打算使用两台服务器当tracker服务器)
tracker服务器(192.168.153.170、192.168.153.182)
修改这两台服务器的配置(配置都是一样的):
mkdir -p /opt/fastdfs/tracker
vim /etc/fdfs/tracker.conf
修改配置:
disabled=false # 启用配置文件
port=22122 # tracker服务器端口(默认22122)
base_path=/opt/fastdfs/tracker # 存储日志和数据的根目录
store_lookup=0 # 0轮询、1指定组(需要配置store_group属性)、2负载均衡
启动、关闭tracker服务器:
fdfs_trackerd /etc/fdfs/tracker.conf restart
fdfs_trackerd /etc/fdfs/tracker.conf stop
查看tracker服务器状态:
/usr/bin/fdfs_monitor /etc/fdfs/storage.conf
Ⅴ:配置storage服务器(此集群我们打算使用四台服务器当storage服务器,两个为一组)
storage服务器(192.168.153.183、192.168.153.184、192.168.153.185、192.168.153.186)
修改配置(这四台服务器配置都是一样的):
mkdir -p /opt/fastdfs/storage
mkdir -p /opt/fastdfs/storage/files
vim /etc/fdfs/storage.conf
修改相同配置:
disabled=false # 启用配置文件
port=23000 # storage的端口号,同一个组的storage端口号必须相同
base_path=/opt/fastdfs/storage # 存储日志和数据的根目录
store_path0=/opt/fastdfs/storage/files # 第一个存储目录
store_path_count=1 # 存储路径个数,需要和store_path个数匹配
tracker_server=192.168.153.170:22122 # tracker服务器的IP地址和端口
tracker_server=192.168.153.182:22122 # 多个tracker直接添加多条配置
修改不同配置:
# 组名(192.168.153.183、192.168.153.184)为group1(组1)
# 组名(192.168.153.185、192.168.153.186)为group2(组2)
group_name=group1
启动、关闭tracker服务器:
fdfs_storaged /etc/fdfs/storage.conf restart
fdfs_storaged /etc/fdfs/storage.conf stop
Ⅵ:检查这六台服务器的tracker服务和storage是否正常启动:
ps -ef | grep fdfs
若所有的Storage服务都启动后则可以在任一Storage节点上使用如下命令查看集群信息:
fdfs_monitor /etc/fdfs/storage.conf
如打印信息:
DEBUG - base_path=/opt/fastdfs/storage, connect_timeout=5, network_timeout=60, tracker_server_count=2, ...
server_count=2, server_index=1 # 当前tracker服务存在2个,并且当前使用的是第一个
tracker server is 192.168.153.182:22122
group count: 2 # 当前group存在2个组分别如下
Group 1:
group name = group1
disk total space = 17,394 MB
disk free space = 12,572 MB
...
Storage 1:
id = 192.168.153.183
ip_addr = 192.168.153.183 ACTIVE
...
Storage 2:
id = 192.168.153.184
ip_addr = 192.168.153.184 ACTIVE
...
Group 2:
group name = group2
disk total space = 17,394 MB
disk free space = 12,536 MB
...
Storage 1:
...
Storage 2:
...
Ⅶ:修改Tracker服务器客户端配置文件(两台tracker服务器随便找一台测试文件上传)
mkdir -p /opt/fastdfs/client
vim /etc/fdfs/client.conf
修改配置:
base_path = /opt/fastdfs/client
tracker_server=192.168.153.170:22122
tracker_server=192.168.153.182:22122
测试文件上传:
fdfs_test /etc/fdfs/client.conf upload abc.mp4
现象:在轮询的上传模式时,若系统选择上传服务器为group1,那么就会在group1这2台服务器内轮询上传,若group1的2台断线了则会切换到group2
注意:group1里的多台服务器会相互备份group1内的数据
Ⅷ:配置Nginx访问(所有的storage节点都需要安装Nginx),命令如下:
注意:命令不是特别理解的请参考上面的单机详细部署
cd /home
unzip fastdfs-nginx-module-V1.23.zip
tar -zxvf nginx-1.22.1.tar.gz
cd nginx-1.22.1/
./configure --with-http_ssl_module --add-module=/home/fastdfs-nginx-module-V1.23/src
make && make install
## 这下面的这段命令复制时不要在前面加空格
cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=nginx
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx reload
ExecStop=/usr/local/nginx/sbin/nginx quit
PrivateTmp=true
[Install]
WantedBy=multi-user.target
EOF
补充:fastdfs-nginx-module 作用说明:
FastDFS通过Tracker服务器,将文件放在Storage服务器存储,但是同组存储服务器之间需要进入文件复制,有同步延迟的问题。
假设Tracker服务器将文件上传到了192.168.153.183,上传成功后文件ID已经返回给客户端。此时FastDFS存储集群机制会将这个
文件同步到同组存储192.168.153.184,在文件还没有复制完成的情况下,客户端如果用这个文件ID在 192.168.153.183上取文件,
就会出现文件无法访问的错误。而fastdfs-nginx-module可以重定向文件连接到源服务器取文件,避免客户端由于复制延迟导致的
文件无法访问错误。(解压后的fastdfs-nginx-module在nginx安装时使用)
修改mod_fastdfs.conf的配置文件:
拷贝文件并创建个文件:
cp /home/fastdfs-nginx-module-V1.23/src/mod_fastdfs.conf /etc/fdfs
mkdir -p /opt/fastdfs/nginx_mod
修改mod_fastdfs配置文件:
vim /etc/fdfs/mod_fastdfs.conf
base_path = /opt/fastdfs/nginx_mod # 配置存储运行产生的日志数据等等
tracker_server=192.168.153.170:22122 # tracker服务器IP1和端口
tracker_server=192.168.153.182:22122 # tracker服务器IP2和端口
group_name=group1 # 当前服务器的group名;(若是group1就设置group1,若是group2就设置为group2)
url_have_group_name=true # url中包含group名称
store_path0=/opt/fastdfs/storage/files # storage的存储路径
group_count=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
修改Nginx配置:
vim /usr/local/nginx/conf/nginx.conf
添加标红的配置:
server {
listen 80;
server_name localhost;
#拦截请求路径中包含 /group[1-9]/M[0-9][0-9] 的请求,用 fastdfs的Nginx 模块进行转发
location ~ /group[1-9]/M[0-9][0-9] {
ngx_fastdfs_module;
}
location / {
root html;
index index.html index.htm;
}
}
启动Nginx服务:
# 加入到开机自启动(必须先执行)
systemctl enable nginx.service
# 启动Nginx服务:
systemctl start nginx
访问之前上传的链接(若可以访问则大功告成)
http://192.168.153.189/group2/M00/00/00/wKiZvWUoFriAbMGVAFPt9uDrhUk619.mp4
注意说明:
FastDFS集群上传文件后,若上传到group1中任意一个节点,那么group1周围所有节点都会同步该文件,
若上传到group2中任意一个节点,那么group2周围所有节点都会同步该文件。
所以后期获取文件时需要看group1中有哪几个节点服务器,任意一个节点服务都可以访问。
.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)