FastDFS的简单实践--(与Spring Boot整合)

简介: 因为项目的需要,这两天在项目中整合了FastDFS,用于大批量的上传图片。按照惯例我们先介绍整合,然后再介绍一下FastDFS的相关情况。

因为项目的需要,这两天在项目中整合了FastDFS,用于大批量的上传图片。按照惯例我们先介绍整合,然后再介绍一下FastDFS的相关情况。


FastDFS 与Spring Boot的整合


相关配置

在pom文件中添加依赖

<!-- fastdfs -->
      <dependency>
          <groupId>org.csource</groupId>
          <artifactId>fastdfs-client-java</artifactId>
          <version>1.2.RELEASE</version>
      </dependency>
      <!--对象池-->
      <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-pool2</artifactId>
          <version>2.4.2</version>
      </dependency>


配置属性文件,命名为fastdfs_client.conf,放在resources下

## fastdfs为前缀的是FastDFS的配置
connect_timeout = 2
network_timeout = 30
charset = utf-8
# TrackerServer port
http.tracker_http_port = 80
# token 防盗链功能
http.anti_steal_token = no
# 密钥
http.secret_key = FastDFS1234567890
# 文件服务器地址
http.access.url=你fastdfs的服务器
# Tracker Server
tracker_server = 你tracker的服务器
tracker_server = 你tracker的服务器


文件上传

操作文件的工具类FastDfsUtil类

public class FastDfsUtil implements Serializable{
    private static final Logger log = LoggerFactory.getLogger(FastDfsUtil.class);
    private static final long serialVersionUID = -4230645563489067923L;
    /**
     * 文件上传
     * @param is
     * @param fileName
     * @return
     */
public static String uploadFile(InputStream is, String fileName){
        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        try {
            //读取流
            byte[] content = new byte[is.available()];
            is.read(content, 0, content.length);
            //文件扩展名
            String ext = FilenameUtils.getExtension(fileName);
            //mata list是表文件的描述
            NameValuePair[] mata_list = new NameValuePair[1];
            mata_list[0] = new NameValuePair("fileName", fileName);
            // 上传
            String path  = storageClient.upload_file1(content, ext, mata_list);
            return path;
        } catch (Exception e) {
            log.error("上传图片到fastDFS失败={}", e.getMessage());
            throw new UploadException("上传图片到fastDFS失败");
        } finally{
            // 返还对象
            TrackerServerPool.returnObject(trackerServer);
        }
    }
}


此处用到了工厂模式以及对象池

4. 对象池类TrackerServerPool类

/**
 * TrackerServer 对象池
 * <p>
 *
 * @author xiang.wei
 * @version 1.0
 */
public class TrackerServerPool {
    /**
     * org.slf4j.Logger
     */
    private static Logger logger = LoggerFactory.getLogger(TrackerServerPool.class);
    /**
     * TrackerServer 配置文件路径
     */
    private static final String FASTDFS_CONFIG_PATH = "fastdfs_client.conf";
    /**
     * 最大连接数 default 8.
     * 需要在application.properties中配置
     */
    @Value("${max_storage_connection}")
    private static int maxStorageConnection;
    /**
     * TrackerServer 对象池.
     * GenericObjectPool 没有无参构造
     */
    private static GenericObjectPool<TrackerServer> trackerServerPool;
    private TrackerServerPool(){};
    private static synchronized GenericObjectPool<TrackerServer> getObjectPool(){
        if(trackerServerPool == null){
            try {
                // 加载配置文件
                ClassPathResource resource = new ClassPathResource(FASTDFS_CONFIG_PATH);
                ClientGlobal.init(resource.getClassLoader().getResource(FASTDFS_CONFIG_PATH).getPath());
            } catch (IOException e) {
                logger.info("加载fastDFS配置文件出错={}",e.getMessage());
            } catch (Exception e) {
                logger.info("加载fastDFS配置文件出错={}",e.getMessage());
            }
            // Pool配置
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            poolConfig.setMinIdle(2);
            if(maxStorageConnection > 0){
                poolConfig.setMaxTotal(maxStorageConnection);
            }
            trackerServerPool = new GenericObjectPool<>(new TrackerServerFactory(), poolConfig);
        }
        return trackerServerPool;
    }
    /**
     * 获取 TrackerServer
     * @return TrackerServer
     * @throws FastDFSException
     */
    public static TrackerServer borrowObject(){
        TrackerServer trackerServer = null;
        try {
            trackerServer = getObjectPool().borrowObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return trackerServer;
    }
    /**
     * 回收 TrackerServer
     * @param trackerServer 需要回收的 TrackerServer
     */
    public static void returnObject(TrackerServer trackerServer){
        getObjectPool().returnObject(trackerServer);
    }
}


工厂类 TrackerServerFactory类

public class TrackerServerFactory extends BasePooledObjectFactory<TrackerServer> {
    @Override
    public TrackerServer create() throws Exception {
        // TrackerClient
        TrackerClient trackerClient = new TrackerClient();
        // TrackerServer
        TrackerServer trackerServer = trackerClient.getConnection();
        return trackerServer;
    }
    @Override
    public PooledObject<TrackerServer> wrap(TrackerServer trackerServer) {
        return new DefaultPooledObject<TrackerServer>(trackerServer);
    }
}


以上就配置完了,可以传入有效的图片测试下。


FastDFS 的介绍


FastDFS是一个开源的高性能分布式文件系统(DFS)。它的主要功能包括:文件存储,文件同步和文件访问,以及高容量和负载均衡。主要解决了海量数据存储问题,特别适合以中小文件(建议范围:4KB < file_size < 500MB) 为载体的在线服务。

FastDFS系统有三个角色:跟踪服务器(Tracker Server)、存储服务器(Storage Server)和客户端(Client) 。

Tracker Server: 跟踪服务器,主要做调度工作,起到均衡的作用;负责管理所有的storage server和group,每个storage在启动后会连接Tracker,告知自己所属group等信息,并保持周期性心跳。

Storage Server:存储服务器,主要提供容量和备份服务;以group为单位,每个group内有多台storage server,数据互为备份。

Client:客户端,上传下载数据的服务器,也就是我们自己的项目所部署在的服务器。

49180aa114dd9b526e07df6ec67e9b78_70.png



FastDFS的存储策略

为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式。存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的。所有卷的文件容量累加就是存储系统中的文件容量。一个卷可以由一台或者多台存储服务器组成,一个卷下的存储服务器中的文件都是相同的,卷中的多台存储服务器起到了冗余备份和负载均衡的作用。

在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务。当存储空间不足或即将耗尽时,可以动态添加卷。只需要增加一台或多台服务器,并将它们配置为一个新的卷,这样就可以扩大了存储系统的容量。


FastDFS的上传过程

FastDFS向使用者提供基本文件访问接口,不如upload,download等等,以客户端库的方式提供给用户使用。

storage server会定期的向Tracker Server发送自己的存储信息。当Tracker Server Cluster中的Tracker Server不止一个时,各个Tracker之间的关系是对等的。所以客户端上传时可以选择任意一个Tracker。

当Tracker收到客户端上传文件的请求时,会为该文件分配一个可以存储文件的group,当选定了group后就要决定给客户端分配group中的哪一个storage server。当分配好storage server后,客户端向stroage发送写文件请求,storage 将会为文件分配一个数据存储目录。然后为文件分配一个 field,最后根据以上的信息生成文件名存储文件。

1f9c325a18f581d2e761ffa23d4f9bd6_SouthEast.png

生成文件名:

当文件存储到某个子目录后,即认为该文件存储成功,接下来会为该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid、文件后缀名拼接而成。

例如:

group1/M00/02/1E/wKjScFs8PP6AOeKAAAFQYpr9pVQ027.jpg
组名  磁盘    目录   文件名


FastDFS的文件同步

写文件时,客户端将文件写至group内一个storage server即认为写文件成功,storage server写完文件后,会由后台线程将文件同步至同group内其他的storage server。

每个storage写文件后,同时会写一份 binlog,binlog里不包含文件数据,只包含文件名等元信息,这份binlog用于后台同步,storage会记录向group内其他storage同步的进度,以便重启后能接上次的进度继续同步;进度以时间戳的方式记录,所以最好能保持集群内所有server的时钟保持同步。

storage的同步进度会作为元数据的一部分汇报到tracker上,tracker在选择读storage的时候以同步进度作为参考。


FastDFS的文件下载

客户端uploadfile成功后,会拿到一个storage生成的文件名,接下来客户端更加这个文件名即可访问到该文件。

12525b2b996c64fdf6f10eb762b848ed_SouthEast.png


引用

https://www.cnblogs.com/chiangchou/p/fastdfs.html#_label0_0

https://blog.csdn.net/u013378306/article/details/74852355


相关文章
|
1天前
|
人工智能 自然语言处理 Java
Spring Cloud Alibaba AI 入门与实践
本文将介绍 Spring Cloud Alibaba AI 的基本概念、主要特性和功能,并演示如何完成一个在线聊天和在线画图的 AI 应用。
53 7
|
5月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
133 1
|
20天前
|
XML Java 数据格式
🌱 深入Spring的心脏:Bean配置的艺术与实践 🌟
本文深入探讨了Spring框架中Bean配置的奥秘,从基本概念到XML配置文件的使用,再到静态工厂方式实例化Bean的详细步骤,通过实际代码示例帮助读者更好地理解和应用Spring的Bean配置。希望对你的Spring开发之旅有所助益。
84 3
|
1月前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
57 14
|
1月前
|
缓存 Java 数据库连接
Spring框架中的事件机制:深入理解与实践
Spring框架是一个广泛使用的Java企业级应用框架,提供了依赖注入、面向切面编程(AOP)、事务管理、Web应用程序开发等一系列功能。在Spring框架中,事件机制是一种重要的通信方式,它允许不同组件之间进行松耦合的通信,提高了应用程序的可维护性和可扩展性。本文将深入探讨Spring框架中的事件机制,包括不同类型的事件、底层原理、应用实践以及优缺点。
66 8
|
1月前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
143 5
|
1月前
|
XML 前端开发 安全
Spring MVC:深入理解与应用实践
Spring MVC是Spring框架提供的一个用于构建Web应用程序的Model-View-Controller(MVC)实现。它通过分离业务逻辑、数据、显示来组织代码,使得Web应用程序的开发变得更加简洁和高效。本文将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring MVC,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
79 2
|
2月前
|
安全 Java 数据安全/隐私保护
如何使用Spring Boot进行表单登录身份验证:从基础到实践
如何使用Spring Boot进行表单登录身份验证:从基础到实践
54 5
|
2月前
|
监控 Java 数据安全/隐私保护
如何用Spring Boot实现拦截器:从入门到实践
如何用Spring Boot实现拦截器:从入门到实践
57 5
|
2月前
|
Java 测试技术 数据库连接
使用Spring Boot编写测试用例:实践与最佳实践
使用Spring Boot编写测试用例:实践与最佳实践
106 0