- 分布式文件系统 (Distributed File System) 是一个软件/软件服务器,这个软件可以用来管理文件。
- 这个软件所管理的文件通常不是在一个服务器节点上,而是在多个服务器节点上,这些服务器节点通过网络相连构成一个庞大的文件存储服务器集群,这些服务器都用于存储文件资源,通过分布式文件系统来管理这些服务器上的文件。
- 常见的分布式文件系统有:FastDFS、GFS、HDFS、Lustre 、Ceph 、GridFS 、mogileFS、TFS等。
- 传统方式弊端:
- 如果用户数量多,IO操作比较多,对磁盘访问压力很大
- 如果磁盘发生故障,会造成数据丢失
- 存储容量有限
- FastDFS是一个开源的轻量级分布式文件系统,为互联网应用量身定做,简单、灵活、高效
- 采用C语言开发,由阿里巴巴开发并开源。
- FastDFS对文件进行管理,功能包括:
- 文件存储、文件同步、文件访问(文件上传、文件下载、文件删除)等,
- 解决了大容量文件存储的问题,
- 特别适合以文件为载体的在线服务,如相册网站、文档网站、图片网站、视频网站等等。
- FastDFS充分考虑了冗余备份、线性扩容等机制,并注重高可用、高性能等指标
- 使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。
- FastDFS代码托管在github上:https://github.com/happyfish100/fastdfs
- FastDFS文件系统由两大部分构成,一个是客户端,一个是服务端
- 客户端通常指我们的程序,比如我们的Java程序去连接FastDFS、操作FastDFS,那我们的Java程序就是一个客户端
- 服务端由两个部分构成:一个是跟踪器(tracker),一个是存储节点(storage)
- 跟踪器(tracker)主要做调度工作,在内存中记录集群中存储节点storage的状态信息,是前端Client和后端存储节点storage的枢纽。因为相关信息全部在内存中,Tracker server的性能非常高,一个较大的集群(比如上百个group)中有3台就足够了。
- 存储节点(storage)用于存储文件,包括文件和文件属性(meta data)都保存到存储服务器磁盘上,完成文件管理的所有功能:文件存储、文件同步和提供文件访问等。
- 检查Linux上是否安装了 gcc、libevent、libevent-devel,没有安装需进行安装(yum install gcc libevent libevent-devel -y)
- 安装 libfastcommon 库(libfastcommon 库是 FastDFS 文件系统运行需要的公共 C 语言函数库):
- 解压下载下来的tar.gz压缩包到当前目录——tar -zxvf libfastcommon-1.0.36.tar.gz
- 切换到解压后的libfastcommon目录——cd libfastcommon-1.0.36
- 执行make脚本进行编译——./make.sh
- 执行make install进行安装——./make.sh install
- FastDFS没有Windows版本,不能在Windows下使用,FastDFS需要安装部署在Linux环境下
- 解压下载下来的tar.gz压缩包到当前目录——tar -zxvf fastdfs-5.11.tar.gz
- 切换到解压后FastDFS的目录
- 执行make脚本进行编译——./make.sh
- 执行make install进行安装——./make.sh install
- FastDFS服务启动需要启动两个脚本:
- 在任意目录下执行:fdfs_trackerd /etc/fdfs/tracker.conf
- 在任意目录下执行:fdfs_storaged /etc/fdfs/storage.conf
- fdfs_trackerd /etc/fdfs/tracker.conf restart
- 在任意目录下执行:fdfs_trackerd /etc/fdfs/tracker.conf stop
- 没有搭建集群默认只有一个组group1
- 后缀名包含-m的为属性文件(meta)
- 在Linux中并没有磁盘一说,是虚拟的
二、分布式文件系统FastDFS的HTTP访问
- FastDFS提供了一个Nginx扩展模块,利用该模块,我们可以通过Nginx访问已经上传到FastDFS上的文件
-
将Fastdfs的Nginx扩展模块源代码上传到Linux上
-
解压下载下来的fastdfs-nginx-module-master.zip 文件——unzip fastdfs-nginx-module-master.zip
-
切换至解压后的Nginx主目录,执行配置操作
- cd nginx-1.14.2
- ./configure --prefix=/usr/local/nginx_fdfs --add-module=/home/soft/fastdfs-nginx-module-master/src
- –prefix是指定nginx安装路径
- –add-module指定fastDFS的nginx模块的源代码路径
-
执行命令进行编译——make
-
执行命令进行安装——make install
-
将/home/soft/fastdfs-nginx-module-master/src(自己实际存放Nginx扩展模块的目录)目录下的mod_fastdfs.conf文件拷贝到 /etc/fdfs/目录下,这样才能正常启动Nginx
- cp /home/soft/fastdfs-nginx-module-master/src/mod_fastdfs.conf /etc/fdfs/
-
修改mod_fastdfs.conf配置文件
- base_path=/opt/fastdfs/nginx_mod
- tracker_server=192.168.235.128:22122
- url_have_group_name = true
- store_path0=/opt/fastdfs/storage/files
-
配置Nginx的配置文件:
- #拦截请求路径中包含 /group[1-9]/M0[0-9] 的请求,用 fastdfs的Nginx 模块进行转发
location ~ /group[1-9]/M0[0-9] { ngx_fastdfs_module; } //ngx_fastdfs_module; #这个指令不是Nginx本身提供的,是扩展模块提供的,根据这个指令找到FastDFS提供的Nginx模块配置文件,然后找到Tracker,最终找到Stroager
三、FastDFS在Java项目中开发示例
- 在实际项目开发中,FastDFS提供的主要功能:
- upload:上传文件
- download:下载文件
- delete:删除文件
- FastDFS文件系统的Java客户端是指采用Java语言编写的一套程序,专门用来访问fastDFS文件系统,其实就是一个jar包。
- 在pom.xml文件中添加FastDFS本地仓库的jar包(FastDFS的java客户端依赖)
org.csource fastdfs-client-java 1.27-SNAPSHOT
- resources目录下,在里面主要配置tracker地址:
tracker_server=192.168.42.128:22122
- 代码
public static void upload(){
TrackerServer ts = null;
StorageServer ss = null;
try {
//读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
ClientGlobal.init("fastdfs.conf");
TrackerClient tc = new TrackerClient();
ts = tc.getConnection();
ss = tc.getStoreStorage(ts);
//定义Storage的客户端对象,需要使用这个对象来完成具体的文件的上传、下载、删除
StorageClient sc = new StorageClient(ts,ss);
String[] result = sc.upload_file("d:/1.jpg","jpg",null);
for(String str : result){
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}finally{
if(ss != null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ts != null) {
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(二)文件下载
public static void download(){
TrackerServer ts = null;
StorageServer ss = null;
try {
//读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
ClientGlobal.init("fastdfs.conf");
TrackerClient tc = new TrackerClient();
ts = tc.getConnection();
ss = tc.getStoreStorage(ts);
//定义Storage的客户端对象,需要使用这个对象来完成具体的文件的上传、下载、删除
StorageClient sc = new StorageClient(ts,ss);
String group = "group1";
String fileName = "M00/00/00/wKgqgGJ-BbyAVOM9ABKAocfYGyk468.jpg";
int result = sc.download_file(group,fileName,"d:/2.jpg");
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}finally{
if(ss != null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ts != null) {
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 返回值为0表示下载成功,其他数字均为下载失败
public static void delete(){
TrackerServer ts = null;
StorageServer ss = null;
try {
//读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
ClientGlobal.init("fastdfs.conf");
TrackerClient tc = new TrackerClient();
ts = tc.getConnection();
ss = tc.getStoreStorage(ts);
//定义Storage的客户端对象,需要使用这个对象来完成具体的文件的上传、下载、删除
StorageClient sc = new StorageClient(ts,ss);
String group = "group1";
String fileName = "M00/00/00/wKgqgGJ-BbyAVOM9ABKAocfYGyk468.jpg";
int result = sc.delete_file(group,fileName);
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}finally{
if(ss != null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ts != null) {
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
(四)改造
- 因为使用FastDFS进行文件操作代码大多都是通用的,所以我们这里在FastDFS类中将通用的功能进行封装,并提供上传、下载、删除文件的方法
- 注意:这里只是简单的封装,如果多线程会有问题
public static StorageClient getStorageClient() throws IOException, MyException {
//1.加载配置文件,默认去classpath下加载
ClientGlobal.init("fdfs_client.conf");
//2.创建TrackerClient对象
TrackerClient trackerClient = new TrackerClient();
//3.创建TrackerServer对象
trackerServer = trackerClient.getConnection();
//4.创建StorageServler对象
storageServer = trackerClient.getStoreStorage(trackerServer);
//5.创建StorageClient对象,这个对象完成对文件的操作
StorageClient storageClient = new StorageClient(trackerServer,storageServer);
return storageClient;
}
2、定义两个全局变量
private static TrackerServer trackerServer = null; private static StorageServer storageServer = null;3、抽取关闭资源的方法
public static void closeFastDFS() {
if (storageServer != null) {
try {
storageServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (trackerServer != null) {
try {
trackerServer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、改造文件上传的方法
public static void fileUpload(){
try {
//1. 获取StorageClient对象
StorageClient storageClient = getStorageClient();
//2.上传文件 第一个参数:本地文件路径 第二个参数:上传文件的后缀 第三个参数:文件信息
String [] uploadArray = storageClient.upload_file("D:/aa.txt","txt",null);
for (String str:uploadArray) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
}
5、下载文件
//下载文件的方法
public static void fileDownload(){
try {
//1. 获取StorageClient对象
StorageClient storageClient = getStorageClient();
//2.下载文件 返回0表示成功,其它均表示失败
int num = storageClient.download_file("group1",
"M00/00/00/wKjrgFxOqueAAPWKAAAAKAM14xY563.txt","E:/bb.txt");
System.out.println(num);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
}
6、删除文件
//删除文件的方法
public static void fileDelete(){
try {
//1. 获取StorageClient对象
StorageClient storageClient = getStorageClient();
//2.删除文件 返回0表示成功,其它均表示失败
int num = storageClient.delete_file("group1",
"M00/00/00/wKjrgFxOqueAAPWKAAAAKAM14xY563.txt");
System.out.println(num);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
closeFastDFS();
}
四、FastDFS在web项目中的应用
- 对P2P项目合同进行管理,在WEB项目中实现对文件的上传下载和删除操作
- 债权是债务的对应词,但是在P2P项目中,我们管理的债权,以及合同一般指的是借款人的信息,所以在我们下面创建的creditor_info表中存的是借款人信息
- 合同是pdf文件
- 创建表
CREATE TABLE `creditor_info` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键', `realName` varchar(35) DEFAULT NULL COMMENT '债权借款人姓名', `idCard` 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 '债权借款人借款金额', `groupName` varchar(10) DEFAULT NULL COMMENT '债权合同所在组', `remoteFilePath` varchar(150) DEFAULT NULL COMMENT '债权合同所在路径', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf82、开发环境搭建 (1)创建springboot工程
- 添加spring依赖
- 添加mybatis依赖
- 添加web依赖
- 添加Thymeleaf依赖
- 添加MySQL依赖
#数据库的连接配置信息 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.235.128:3306/fastdfs?useUnicode=true&characterEncoding=utf8&useSSL=false #开发阶段,建议关闭thymeleaf的缓存,不然没有办法看到实时页面 spring.thymeleaf.cache=false #去掉HTML5的语法验证 spring.thymeleaf.mode=LEGACYHTML5 #设置SpringMVC允许上传的单个文件大小 默认值为 1M #spring.servlet.multipart.max-file-size=1M #设置SpringMVC允许的表单请求中上传文件总大小 默认为 10M #spring.servlet.multipart.max-request-size=10M
- 指定编译位置以及添加mybatis逆向工程
org.springframework.boot spring-boot-maven-plugin org.mybatis.generator mybatis-generator-maven-plugin 1.3.6 GeneratorMapper.xml true true src/main/java ** @PostMapping("/upload") public String upload(Integer id, MultipartFile myFile, Model model) throws IOException { // System.out.println(myFile.getBytes());//获取文件对应字节数组 // System.out.println(myFile.getInputStream());//获取文件对应的输入流 // System.out.println(myFile.getContentType());//获取文件类型 // System.out.println(myFile.getName());//获取表单元素名 // System.out.println(myFile.getOriginalFilename());//获取文件名 // System.out.println(myFile.getSize());//获取文件大小 // System.out.println(myFile.isEmpty());//判断文件是否为空 如果没有上传文件或文件大小为0 这个值都是true //收集用户请求信息,即上传的文件数据 //获取文件对应的字节数组 byte[] buffFile = myFile.getBytes(); //获取文件名 String fileName = myFile.getOriginalFilename(); Long fileSize = myFile.getSize(); String fileType = myFile.getContentType(); //可能会出现问题因为有些文件可能没有扩展名,因此必要时需要做逻辑控制 String fileExtName = fileName.substring(fileName.lastIndexOf(".")+1); //调用工具类 String[] result = FastDFSUtil.upload(buffFile,fileExtName); CreditorInfo creditorInfo=new CreditorInfo(); creditorInfo.setId(id); creditorInfo.setFileSize(fileSize); creditorInfo.setFileType(fileType); creditorInfo.setOldFilename(fileName); creditorInfo.setGroupName(result[0]); creditorInfo.setRemoteFilePath(result[1]); creditorService.updateFileInfo(creditorInfo); model.addAttribute("message","文件上传成功,点击确定返回列表页面!"); model.addAttribute("url","/"); return "success"; }
- 工具类
public class FastDFSUtil {
public static String [] upload(byte[] buffFile,String fileExtName) {
TrackerServer ts=null;
StorageServer ss=null;
try {
//读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
ClientGlobal.init("fastdfs.conf");
TrackerClient tc=new TrackerClient();
ts=tc.getConnection();
ss=tc.getStoreStorage(ts);
//定义Storage的客户端对象,需要使用这个对象来完成具体的文件上传 下载和删除操作
StorageClient sc=new StorageClient(ts,ss);
String[] result= sc.upload_file(buffFile,fileExtName,null);
return result;
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
if(ss!=null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static byte [] download(String groupName,String remoteFilename) {
TrackerServer ts=null;
StorageServer ss=null;
try {
//读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
ClientGlobal.init("fastdfs.conf");
TrackerClient tc=new TrackerClient();
ts=tc.getConnection();
ss=tc.getStoreStorage(ts);
//定义Storage的客户端对象,需要使用这个对象来完成具体的文件上传 下载和删除操作
StorageClient sc=new StorageClient(ts,ss);
byte [] buffFile=sc.download_file(groupName,remoteFilename);
return buffFile;
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
if(ss!=null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static void delete(String groupName,String remoteFilename) {
TrackerServer ts=null;
StorageServer ss=null;
try {
//读取FastDFS的配置文件用于将所有的tracker的地址读取到内存中
ClientGlobal.init("fastdfs.conf");
TrackerClient tc=new TrackerClient();
ts=tc.getConnection();
ss=tc.getStoreStorage(ts);
//定义Storage的客户端对象,需要使用这个对象来完成具体的文件上传 下载和删除操作
StorageClient sc=new StorageClient(ts,ss);
int result=sc.delete_file(groupName,remoteFilename);
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
} finally {
if(ss!=null){
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ts!=null){
try {
ts.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
service
@Override
public CreditorInfo selectById(Integer id) {
return creditorInfoMapper.selectByPrimaryKey(id);
}
@Override
public void updateFileInfo(CreditorInfo creditorInfo) {
creditorInfoMapper.updateByPrimaryKeySelective(creditorInfo);
}
Dao层
3、文件下载 Controllerupdate creditor_info where id = #{id,jdbcType=INTEGER} real_name = #{realName,jdbcType=VARCHAR}, id_card = #{idCard,jdbcType=VARCHAR}, address = #{address,jdbcType=VARCHAR}, sex = #{sex,jdbcType=INTEGER}, phone = #{phone,jdbcType=VARCHAR}, money = #{money,jdbcType=DECIMAL}, group_name = #{groupName,jdbcType=VARCHAR}, remote_file_path = #{remoteFilePath,jdbcType=VARCHAR}, old_filename = #{oldFilename,jdbcType=VARCHAR}, file_size = #{fileSize,jdbcType=BIGINT}, file_type = #{fileType,jdbcType=VARCHAR},
@RequestMapping("/download/{id}")
public ResponseEntity download(@PathVariable Integer id){
CreditorInfo creditorInfo=creditorService.selectById(id);
byte [] buffFile=FastDFSUtil.download(creditorInfo.getGroupName(),creditorInfo.getRemoteFilePath());
HttpHeaders headers=new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);//设置响应类型为文件类型
headers.setContentLength(creditorInfo.getFileSize());//设置响应时的文件大小用于自动提供下载进度
//设置下载时的默认文件名
headers.setContentDispositionFormData("attachment",creditorInfo.getOldFilename());
ResponseEntity responseEntity=new ResponseEntity(buffFile,headers, HttpStatus.OK);
return responseEntity;
}
4、文件删除
- 需要思考是在controller层删除还是service层删除
- 删除是需要根据组名和远程地址进行删除。
- controller层中只能拿到文件的主键值,并拿不到组名和远程地址,需要先进行数据库文件查询,再进行删除,比较麻烦
- 所以选择在业务层删除
@RequestMapping("/delete/{id}")
public String delete(@PathVariable Integer id){
creditorService.deleteFileById(id);
return "redirect:/";
}
service
@Override
public void deleteFileById(Integer id) {
//拿数据
CreditorInfo creditorInfo = creditorInfoMapper.selectByPrimaryKey(id);
//删除文件,建议优先删除文件,避免过程中出现问题的时候,导致fastDFS中永远无法删除文件
FastDFSUtil.delete(creditorInfo.getGroupName(),creditorInfo.getRemoteFilePath());
//修改数据
creditorInfo.setRemoteFilePath("");
creditorInfo.setGroupName("");
creditorInfo.setOldFilename("");
creditorInfo.setFileType("");
creditorInfo.setFileSize(0L);
creditorInfoMapper.updateByPrimaryKeySelective(creditorInfo);
}
Dao
delete from creditor_info where id = #{id,jdbcType=INTEGER}
五、FastDFS分布式文件系统集群
- 架构图
- Nginx 192.168.230.129和Nginx 192.168.230.130负责负载均衡
- group1和group2的Nginx负责访问Fastdfs中的文件
- 修改两个tracker服务器的配置文件:
- tracker.conf: 修改一个地方:base_path=/opt/fastdfs/tracker #设置tracker的数据文件和日志目录(需预先创建)
- 启动tracker服务器 fdfs_trackerd /etc/fdfs/tracker.conf
- 每两个storage server为一组,共两个组(group1 和 group2),一个组内有两个storage server
- 第一个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.230.131:22122 #tracker服务器的IP地址以及端口号
tracker_server=192.168.230.132:22122
2、group2
- 第二组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.230.133:22122 #tracker服务器的IP地址以及端口号 tracker_server=192.168.230.134:22122(三)负载均衡 1、Java负载均衡操作
- tracker.conf中:
- store_lookup= 一般选择0或者2
- 当store_lookup=1时,store_group=group2指定的组进行上传文件
#the method of selecting group to upload files #0:round robin #1:sepcify group #2:load balance,select the max free space group to upload file store_lookup=2 #which group to upload file #when store_lookup set to 1,must set store_lookup to the group name store_group=group22、使用Nginx进行负载均衡 (1)安装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; - 以上配置也需要根据自身安装情况(安装目录等)进行配置
- 进入安装目录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.230.131:80;
server 192.168.230.132:80;
server 192.168.230.133:80;
server 192.168.230.134:80;
}
(3)配置另外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)分别修改4台storage服务器的mod_fasfdfs.conf文件(/etc/fdfs/mod_fastdfs.conf)
#修改基本路径,并在指定路径创建对应文件夹
base_path=/opt/fastdfs/nginx_mod #保存日志目录
#指定两台tracker服务器的ip和端口
tracker_server=192.168.230.129:22122 #tracker服务器的IP地址以及端口号
tracker_server=192.168.230.130: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执行相同的操作
- #测试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
-
即访问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.230.129:80;
server 192.168.230.130: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服务器的一款软件,通常由运维人员进行使用



