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


相关文章
|
2月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
4月前
|
XML Java UED
使用 Spring Boot 实现重试和补偿功能:从理论到实践
【6月更文挑战第17天】在分布式系统中,服务之间的调用可能会因为网络故障、服务器负载等原因偶尔失败。为了提高系统的可靠性和稳定性,我们经常需要实现重试和补偿功能。
95 6
|
15天前
|
Java 应用服务中间件 开发者
深入探索并实践Spring Boot框架
深入探索并实践Spring Boot框架
25 2
|
2月前
|
Java 开发工具 Spring
【Azure 事件中心】azure-spring-cloud-stream-binder-eventhubs客户端组件问题, 实践消息非顺序可达
【Azure 事件中心】azure-spring-cloud-stream-binder-eventhubs客户端组件问题, 实践消息非顺序可达
|
2月前
|
缓存 Java Spring
Java本地高性能缓存实践问题之在Spring Boot中启用缓存支持的问题如何解决
Java本地高性能缓存实践问题之在Spring Boot中启用缓存支持的问题如何解决
|
2月前
|
缓存 Java Spring
Java本地高性能缓存实践问题之的Spring Boot中启用缓存支持问题如何解决
Java本地高性能缓存实践问题之的Spring Boot中启用缓存支持问题如何解决
|
2月前
|
前端开发 JavaScript Java
Spring Boot应用中的资源分离与高效打包实践
通过实施资源分离和高效打包策略,不仅可以提升Spring Boot应用的开发和部署效率,还能显著提高用户体验。在实际项目中,根据项目的实际情况和团队的技术栈选择合适的工具和方案是关键。希望本文能为读者在Spring Boot项目中实现资源分离和高效打包提供一些有价值的参考。
|
4月前
|
XML 监控 Java
Spring框架的核心原理与应用实践
Spring框架的核心原理与应用实践
|
4月前
|
负载均衡 Java 开发者
细解微服务架构实践:如何使用Spring Cloud进行Java微服务治理
【6月更文挑战第30天】Spring Cloud是Java微服务治理明星框架,整合Eureka(服务发现)、Ribbon(客户端负载均衡)、Hystrix(断路器)、Zuul(API网关)和Config Server(配置中心),提供完整服务治理解决方案。通过Eureka实现服务注册与发现,Ribbon进行负载均衡,Hystrix确保服务容错,Config Server集中管理配置,Zuul则作为API入口统一处理请求。理解和使用Spring Cloud是现代Java开发者的关键技能。
125 2
|
4月前
|
Java API 网络架构
Spring Cloud Gateway的高级配置与实践
Spring Cloud Gateway的高级配置与实践
下一篇
无影云桌面