分布式文件存储与数据缓存 FastDFS(二)

简介: 分布式文件存储与数据缓存 FastDFS(二)

四、SpringBoot操作FastDFS实现文件上传(基本版)

由GitHub大牛tobato在原作者YuQing与yuqih发布的JAVA客户端基础上进行了大量重构工作,并于GitHub上发布了FastDFS-Client1.26.5。

主要特性

  1. 对关键部分代码加入了单元测试,便于理解与服务端的接口交易,提高接口质量
  2. 将以前对byte硬解析风格重构为使用对象+注解的形式,尽量增强了代码的可读性
  3. 支持对服务端的连接池管理
  4. 支持上传图片时候检查图片格式,并且自动生成缩略图
  5. 在SpringBoot当中自动导入依赖

1、创建springboot项目(2.7.0),导入FastDFS依赖jar

<dependency>
  <groupId>com.github.tobato</groupId>
  <artifactId>fastdfs-client</artifactId>
  <version>1.26.5</version>
</dependency>

2、添加配置

####分布式文件系统配置###########
fdfs:
  so-timeout: 1500
  connect-timeout: 600
  thumb-image:       #缩略图生成参数
    width: 150
    height: 150
  tracker-list:       #TrackerList参数,支持多个
    - 192.168.66.100:22122
   # - 192.168.66.101:22122

3、编写测试类实现文件上传和文件下载

package com.zj;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.*;
@SpringBootTest
class FastdfsApplicationTests {
    //通过FastDFS的客户端对象完成对文件系统的操作
    @Resource
    private FastFileStorageClient fastFileStorageClient;
    //测试上传文件
    @Test
    public void upload() throws FileNotFoundException {
        //1.先读取本地文件
        File file = new File("D:\\aaa.jpg");
        //2.创建传输文件输入流
        FileInputStream fileInputStream = new FileInputStream(file);
        //3.文件上传
        /*
         * 参数一:文件输入流
         * 参数二:文件大小
         * 参数三:文件拓展名
         * 参数四:描述文件的元数据(指定文件上传的位置)
         */
        StorePath storePath = fastFileStorageClient.uploadFile(fileInputStream, file.length(), "jpg", null);
        //4.将卷名和文件名一起打印
        System.out.println("上传文件的地址:"+storePath.getFullPath());
        System.out.println("文件卷名:"+storePath.getGroup());
        System.out.println("文件名:"+storePath.getPath());
    }
    //文件下载
    @Test
    public void download() throws IOException {
       //1.下载文件
        /*
         * 参数一:文件处于存储节点的卷名
         * 参数二:文件在存储节点的文件名
         * 参数三:下载的回调函数
         */
        byte[] downloadFile = fastFileStorageClient.downloadFile("group1", "M00/00/00/wKhCZGS2WGaAYKOuADcAPt_yJDw957.jpg", new DownloadByteArray());
         //2.创建文件输出流,并指定文件下载的位置
        FileOutputStream fileOutputStream = new FileOutputStream("d:\\aaa.jpg");
         //3.将文件输出流写文件到磁盘
        fileOutputStream.write(downloadFile);
        //4.刷新
        fileOutputStream.flush();
        //5.关闭流
        fileOutputStream.close();
    }
}

五、spring boot整合FastDFS实现文件上传(完整版)

1、引入Thymeleaf视图解析器和文件上传客户端对象

<!--fastdfs-->
        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.26.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

注意:

使用wangeditor富文本编辑器的前提是引入Thymeleaf模板。

2、通过CDN在前端页面引入wangEditor富文本编辑器

<script type="text/javascript" src="https://unpkg.com/wangeditor/dist/wangEditor.min.js"></script>

3、创建编辑器基本骨架

<div id="div1">
    <p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<script type="text/javascript">
    const E = window.wangEditor;
    const editor = new E('#div1')
    editor.create();
</script>

4、创建文件上传的Controller控制器

package com.zj.controller;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
@RestController
public class uploadController {
    @Resource
    private FastFileStorageClient fastFileStorageClient;
    //图片上传
    @PostMapping("/upload")
    public void upload(MultipartFile file) throws IOException {
      //1.判断文件是否为空
        if(file != null){
            //2.获取上传的图片的名字
            String originalFilename = file.getOriginalFilename();
            //3.获取上传的图片的扩展名
            String suffix = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
            //4.上传图片
            StorePath storePath = fastFileStorageClient.uploadFile(file.getInputStream(), file.getSize(), suffix, null);
            System.out.println("上传的文件的路径:"+storePath.getFullPath());
            //5.上传的文件路径需要保存到数据库中
            //……
        }
    }
}

文件上传的请求方式必须是post

5、完整的index.html页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
    <script type="text/javascript" src="https://unpkg.com/wangeditor/dist/wangEditor.min.js"></script>
</head>
<body>
<div id="div1">
    <p>欢迎使用 <b>wangEditor</b> 富文本编辑器</p>
</div>
<script type="text/javascript">
    const E = window.wangEditor;
    const editor = new E('#div1');
    //指定文件上传的服务路径
    editor.config.uploadImgServer = "/upload";
    //文件参数名
    editor.config.uploadFileName = "file";
    //限制文件上传的大小和类型 2M
    editor.config.uploadImgMaxSize = 2 * 1024 * 1024;
    //文件上传的类型
    editor.config.uploadImgAccept = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
    editor.create();
</script>
</body>
</html>

6、启动项目,上传图片即可

六、FastDFS整合Nginx

 Nginx服务器是一个高性能的web服务器与反向代理服务器。

FastDFS集成Nginx的2个原因

  1. 为分布式文件系统提供Http服务支持

通过Nginx的web服务代理访问分布式文件系统的存储节点,从而实现通过http请求访问存储节点资源。

注意:

src 属性值图像文件的 URL。也就是引用该图像的文件的的绝对路径或相对路径。

 2.解决复制延迟问题

由于FastDFS的同卷的存储节点之间需要同步,当文件尚未同步完成时,访问请求到达改节点,获取的数据将是未同步完的不完整数据,即为复制延迟问题。通过Nginx检测请求的存储节点的数据,若该存储节点的数据尚未同步完成,则将请求转发至数据的原存储节点,从而解决复制延迟问题。

环境搭建

下载Fastdfs的Nginx模块包

#选择安装位置
cd /usr/local
#下载文件(或者使用本文章已经下载好的文件)
wget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.22.tar.gz
#解压文件
tar -zxvf V1.22.tar.gz

在ginx-1.20.2目录下安装Nginx依赖文件

yum install -y gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel gd-devel epel-release

配置Nginx服务器

#建立Makefile文件,检查Linux系统环境以及相关的关键属性。添加fastdfs-nginx-module-1.22模块到nginx
./configure --add-module=/usr/local/fastdfs-nginx-module-1.22/src/
#编译项目,主要将gcc源代码编译成可执行的目标文件
make
#根据上一步骤编译完成的数据安装到预定的目录中。之前安装过ngxin的话不需要再安装
make install

注意:

  • –add-module:为nginx添加一个fastdfs-nginx-module模块,值为该模块在当前系统的路径
  • –prefix:指定nginx安装位置

将Fastdfs软件包里面的http.conf和mime.types拷贝到/etc/fdfs目录下

cp /usr/local/fastdfs-6.06/conf/mime.types /etc/fdfs/
cp /usr/local/fastdfs-6.06/conf/http.conf /etc/fdfs/

配置Nginx的fastdfs模块,并编辑文件

#拷贝文件
[root@localhost opt]cp /usr/local/fastdfs-nginx-module-1.22/src/mod_fastdfs.conf /etc/fdfs/
[root@localhost fdfs] vim mod_fastdfs.conf
#保存日志目录
base_path=/data/fastdfs/storage   
#tracker 服务器的 IP 地址以及端口号
tracker_server=192.168.66.100:22122 
#文件url中是否有group 名
url_have_group_name = true      
#存储路径
store_path0=/data/fastdfs/storage  
group_count = 1            #设置组的个数
#然后在末尾添加分组信息,目前只有一个分组,就只写一个
[group1]
group_name=group1
storage_server_port=23000
store_path_count=1
store_path0=/data/fastdfs/storage

配置Nginx

server {
  listen    80;
  server_name  localhost;
  location ~ /group[1-3]/M00 {
    alias /data/fastdfs/storage/data;
     ngx_fastdfs_module;
   }
  # 根目录下返回403
  location = / {
     return 403;
   }
  # log file
  access_log  logs/img_access.log access;
}

启动Ningx服务

# 进入sbin目录
[root@tracker nginx]# cd sbin/
# 启动服务 -c:指定配置文件
[root@tracker sbin]# ./nginx -c /usr/local/nginx/conf/nginx.conf

查看服务启动情况

[root@tracker sbin]# ps -ef | grep nginx

启动追踪服务与存储节点服务

[root@tracker sbin]# fdfs_trackerd /etc/fdfs/tracker.conf start
[root@tracker sbin]# fdfs_storaged /etc/fdfs/storage.conf start

上传图片测试

将图片上传至linux系统后,使用指令上传至分布式文件系统

[root@localhost /]# fdfs_upload_file /etc/fdfs/client.conf pdx.jpg
group1/M00/00/00/wKhCZGS6zneAUxGKAANsTCZQKGY401.jpg

通过浏览器远程访问

http://192.168.66.100/group1/M00/00/00/wKhCZGS6zneAUxGKAANsTCZQKGY401.jpg


相关文章
|
1月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
2月前
|
缓存 NoSQL Java
Redis 缓存与数据库数据不一致问题
Redis 缓存与数据库数据不一致问题
68 3
|
6天前
|
缓存 NoSQL Java
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
缓存与分布式锁、Redisson分布式锁、缓存数据一致性【必须满足最终一致性】
谷粒商城笔记+踩坑(12)——缓存与分布式锁,Redisson+缓存数据一致性
|
27天前
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
|
1月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
22天前
|
数据采集 分布式计算 并行计算
Dask与Pandas:无缝迁移至分布式数据框架
【8月更文第29天】Pandas 是 Python 社区中最受欢迎的数据分析库之一,它提供了高效且易于使用的数据结构,如 DataFrame 和 Series,以及大量的数据分析功能。然而,随着数据集规模的增大,单机上的 Pandas 开始显现出性能瓶颈。这时,Dask 就成为了一个很好的解决方案,它能够利用多核 CPU 和多台机器进行分布式计算,从而有效地处理大规模数据集。
47 1
|
27天前
|
运维 安全 Cloud Native
核心系统转型问题之分布式数据库和数据访问中间件协作如何解决
核心系统转型问题之分布式数据库和数据访问中间件协作如何解决
|
1月前
|
存储 缓存 分布式计算
|
2月前
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
20天前
|
Java 数据库连接 微服务
揭秘微服务架构下的数据魔方:Hibernate如何玩转分布式持久化,实现秒级响应的秘密武器?
【8月更文挑战第31天】微服务架构通过将系统拆分成独立服务,提升了可维护性和扩展性,但也带来了数据一致性和事务管理等挑战。Hibernate 作为强大的 ORM 工具,在微服务中发挥关键作用,通过二级缓存和分布式事务支持,简化了对象关系映射,并提供了有效的持久化策略。其二级缓存机制减少数据库访问,提升性能;支持 JTA 保证跨服务事务一致性;乐观锁机制解决并发数据冲突。合理配置 Hibernate 可助力构建高效稳定的分布式系统。
37 0