zoukankan      html  css  js  c++  java
  • FastDFS 分布式文件系统

    FastDFS两个主要的角色:Tracker Server 和 Storage Server 。

    • Tracker Server:跟踪服务器,主要负责调度storage节点与client通信,在访问上起负载均衡的作用,和记录storage节点的运行状态,是连接client和storage节点的枢纽。

    • Storage Server:存储服务器,保存文件和文件的meta data(元数据),每个storage server会启动一个单独的线程主动向Tracker cluster中每个tracker server报告其状态信息,包括磁盘使用情况,文件同步情况及文件上传下载次数统计等信息

    • Group:文件组,多台Storage Server的集群。上传一个文件到同组内的一台机器上后,FastDFS会将该文件即时同步到同组内的其它所有机器上,起到备份的作用。不同组的服务器,保存的数据不同,而且相互独立,不进行通信。

    • Tracker Cluster:跟踪服务器的集群,有一组Tracker Server(跟踪服务器)组成。

    • Storage Cluster :存储集群,有多个Group组成。

    上传 

    1. Client通过Tracker server查找可用的Storage server。

    2. Tracker server向Client返回一台可用的Storage server的IP地址和端口号。

    3. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并进行文件上传。

    4. 上传完成,Storage server返回Client一个文件ID,文件上传结束。

    下载 

    1. Client通过Tracker server查找要下载文件所在的的Storage server。

    2. Tracker server向Client返回包含指定文件的某个Storage server的IP地址和端口号。

    3. Client直接通过Tracker server返回的IP地址和端口与其中一台Storage server建立连接并指定要下载文件。

    4. 下载文件成功。

    引入依赖 

    <fastDFS.client.version>1.26.2</fastDFS.client.version> //父工程中管理版本 


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

    java配置 

    @Configuration
    @Import(FdfsClientConfig.class)
    // 解决jmx重复注册bean的问题
    @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
    public class FastClientImporter {
        
    }

    yml文件 

    fdfs:
      so-timeout: 1501 # 超时时间
      connect-timeout: 601 # 连接超时时间
      thumb-image: # 缩略图
         60
        height: 60
      tracker-list: # tracker地址:你的虚拟机服务器地址+端口(默认是22122)
        - 192.168.56.101:22122

    测试  

    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class FastDFSTest {
    
        @Autowired
        private FastFileStorageClient storageClient;
    
        @Autowired
        private ThumbImageConfig thumbImageConfig;
    
        @Test
        public void testUpload() throws FileNotFoundException {
            // 要上传的文件
            File file = new File("C:\Users\Pictures\test.jpg");
            // 上传并保存图片,参数:1-上传的文件流 2-文件的大小 3-文件的后缀 4-可以不管他
            StorePath storePath = this.storageClient.uploadFile(
                    new FileInputStream(file), file.length(), "jpg", null);
            // 带分组的路径
            System.out.println(storePath.getFullPath());
            // 不带分组的路径
            System.out.println(storePath.getPath());
        }
    
        @Test
        public void testUploadAndCreateThumb() throws FileNotFoundException {
            File file = new File("C:\Users\Pictures\test.jpg");
            // 上传并且生成缩略图
            StorePath storePath = this.storageClient.uploadImageAndCrtThumbImage(
                    new FileInputStream(file), file.length(), "png", null);
            // 带分组的路径
            System.out.println(storePath.getFullPath());
            // 不带分组的路径
            System.out.println(storePath.getPath());
            // 获取缩略图路径
            String path = thumbImageConfig.getThumbImagePath(storePath.getPath());
            System.out.println(path);
        }
    }

    测试结果

    group1/M00/00/00/wKg4ZVsWl5eAdLNZAABAhya2V0c424.jpg
    M00/00/00/wKg4ZVsWl5eAdLNZAABAhya2V0c424.jpg

    上传逻辑 

    @Service
    public class UploadService {
    
        @Autowired
        private FastFileStorageClient storageClient;
    
        private static final List<String> CONTENT_TYPES = Arrays.asList("image/jpeg", "image/gif");
    
        private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);
    
        public String upload(MultipartFile file) {
    
            String originalFilename = file.getOriginalFilename();
            // 校验文件的类型
            String contentType = file.getContentType();
            if (!CONTENT_TYPES.contains(contentType)){
                // 文件类型不合法,直接返回null
                LOGGER.info("文件类型不合法:{}", originalFilename);
                return null;
            }
    
            try {
                // 校验文件的内容
                BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
                if (bufferedImage == null){
                    LOGGER.info("文件内容不合法:{}", originalFilename);
                    return null;
                }
    
                // 保存到服务器
                // file.transferTo(new File("C:\test\images\" + originalFilename));
                String ext = StringUtils.substringAfterLast(originalFilename, ".");
                StorePath storePath = this.storageClient.uploadFile(file.getInputStream(), file.getSize(), ext, null);
    
                // 生成url地址,返回
                return "http://image.test.com/" + storePath.getFullPath();
            } catch (IOException e) {
                LOGGER.info("服务器内部错误:{}", originalFilename);
                e.printStackTrace();
            }
            return null;
        }
    }

      

  • 相关阅读:
    模态弹出框
    bootstrap导入JavaScript插件
    面板
    列表组
    媒体对象
    进度条
    sql面试题
    mysql 全连接 报错1051的原因
    Java 类加载体系之 ClassLoader 双亲委托机制
    如何找到JAVA_HOME?
  • 原文地址:https://www.cnblogs.com/qin1993/p/12642669.html
Copyright © 2011-2022 走看看