换掉MinIO!全新一代分布式文件系统来了,功能很强大!

云存储数据库容器

在开发项目的时候,我们经常会遇到需要文件存储的场景,比较流行的解决方案有OSS、MinIO、FastDFS这些。最近有小伙伴反馈MinIO的控制台屏蔽了很多之前已有的功能,就剩下查看的功能。今天给大家分享一款最近刚开源的分布式文件系统RustFS,自带管理控制台,功能很强大!

最近建了一些工作内推群,各大城市都有,欢迎各位HR和找工作的小伙伴进群交流,群里目前已经收集了不少的工作内推岗位。

扫码加苏三的微信:li_su223,备注:所在城市,即可进群。

picture.image

简介

RustFS是一个基于Rust语言开发的高性能分布式对象存储软件,开源不到一个月就收获了6k+star。与MinIO一样,它具有使用简单、兼容AWS S3协议、开源等优势,它采用Apache开源协议。

RustFS的主要特效如下:

  • 高性能:基于Rust构建,具有较高的性能和响应速度。
  • 分布式架构:可扩展且容错的设计,适用于大规模部署。
  • AWS S3 兼容性:可使用AWS S3 SDK来管理它。
  • 数据湖支持:针对大数据和AI工作负载进行了优化。
  • 开源:采用Apache 2.0许可证,鼓励社区贡献和透明度。
  • 用户友好:具有可视化管理控制台,方便管理。

下面是RustFS使用过程中的效果图,功能还是很强大的!

picture.image

安装

使用Docker来安装RustFS是非常方便的,我们将采用此种方式来安装。

  • 首先使用如下命令下载RustFS的镜像;
  
docker pull rustfs/rustfs  

  • 下载完成后使用如下命令运行RustFS的容器;
  
docker run -p 9000:9000 --name rustfs \  
-e RUSTFS\_ACCESS\_KEY=rustfsadmin \  
-e RUSTFS\_SECRET\_KEY=rustfsadmin \  
-v /mydata/rustfs/data:/data \  
-v /etc/localtime:/etc/localtime \  
-d rustfs/rustfs  

  • 运行成功后就可以访问RustFS的管理控制台了,默认账号密码为 rustfsadmin:rustfsadmin ,访问地址:http://192.168.3.101:9000

picture.image

控制台使用

接下来讲解下RustFS管理控制台的使用,用户界面还是挺友好的!

  • 选择 文件浏览器 功能,点击右上角的 创建存储桶 按钮即可创建存储桶;

picture.image

  • 点击存储桶对应的 配置 按钮即可进行配置,例如修改下存储桶的访问策略;

picture.image

  • 进入存储桶后,点击右上角 上传文件 按钮,即可上传文件,支持同时上传多个文件;

picture.image

  • 点击文件,选择 预览 ,即可预览上传后的文件;

picture.image

  • 选择 访问密钥 功能,可以创建一个有过期时间的密钥,并且可以设置文件访问策略;

picture.image

  • 选择 用户 功能,可以进行用户的管理并分配用户的访问策略;

picture.image

  • 选择 性能 功能,可以查看当前RustFS服务器的基本信息。

picture.image

结合SpringBoot实现文件上传

下面我们就创建一个SpringBoot应用,来实现RustFS的文件上传和文件删除功能。

  • 首先我们需要在项目的 pom.xml 文件中添加AWS 33 Java SDK相关依赖;
  
<!--AWS 33 Java SDK相关依赖-->  
<dependency>  
    <groupId>software.amazon.awssdk</groupId>  
    <artifactId>s3</artifactId>  
    <version>${aws-s3-sdk.version}</version>  
</dependency>  

  • 然后在 application.yml 配置文件中添加RustFS的连接信息配置;
  
rustfs:  
  endpoint: http://192.168.3.101:9000  
  bucketName: simple  
  accessKey: rustfsadmin  
  secretKey: rustfsadmin  

  • 接下来创建RustFS的Java配置类,用于读取配置文件中的连接配置,然后实例化S3 客户端对应的Bean;
  
/**  
 * @auther macrozheng  
 * @description RustFS配置类  
 * @date 2025/7/23  
 * @github https://github.com/macrozheng  
 */  
@Configuration  
publicclass RustFSConfig {  
  
    @Value("${rustfs.endpoint}")  
    private String ENDPOINT;  
    @Value("${rustfs.accessKey}")  
    private String ACCESS\_KEY;  
    @Value("${rustfs.secretKey}")  
    private String SECRET\_KEY;  
  
    @Bean  
    public S3Client s3Client(){  
        // 初始化 S3 客户端  
        return S3Client.builder()  
                .endpointOverride(URI.create(ENDPOINT)) // RustFS 地址  
                .region(Region.US\_EAST\_1) // 可写死,RustFS 不校验 region  
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(ACCESS\_KEY, SECRET\_KEY)))  
                .forcePathStyle(true) // 关键配置!RustFS 需启用 Path-Style  
                .build();  
    }  
}  

  • 然后创建RustFSController实现文件上传和删除功能,当Bucket不存在时先创建并设置访问策略为公开只读;
  
/**  
 * @auther macrozheng  
 * @description RustFS对象存储管理Controller  
 * @date 2025/7/22  
 * @github https://github.com/macrozheng  
 */  
@Slf4j  
@Controller  
@Tag(name = "RustFSController", description = "RustFS对象存储管理")  
@RequestMapping("/rustfs")  
publicclass RustFSController {  
  
    @Autowired  
    private S3Client s3Client;  
    @Value("${rustfs.bucketName}")  
    private String BUCKET\_NAME;  
    @Value("${rustfs.endpoint}")  
    private String ENDPOINT;  
  
    @Operation(summary = "文件上传")  
    @RequestMapping(value = "/upload", method = RequestMethod.POST,consumes = MediaType.MULTIPART\_FORM\_DATA\_VALUE)  
    @ResponseBody  
    public CommonResult upload(@RequestPart("file") MultipartFile file) {  
        // 判断Bucket是否存在  
        if(!bucketExists(BUCKET\_NAME)){  
            // 创建Bucket  
            s3Client.createBucket(CreateBucketRequest.builder()  
                    .bucket(BUCKET\_NAME)  
                    .build());  
            log.info("Bucket created: {}",BUCKET\_NAME);  
            // 添加Bucket的访问策略  
            String policy = JSONUtil.toJsonStr(createBucketPolicyConfigDto(BUCKET\_NAME));  
            log.info(policy);  
            PutBucketPolicyRequest policyReq = PutBucketPolicyRequest.builder()  
                    .bucket(BUCKET\_NAME)  
                    .policy(policy)  
                    .build();  
            s3Client.putBucketPolicy(policyReq);  
        }else{  
            log.info("Bucket already exists.");  
        }  
        // 上传文件  
        try {  
            s3Client.putObject(PutObjectRequest.builder()  
                    .bucket(BUCKET\_NAME)  
                    .key(file.getOriginalFilename())  
                    .contentType(file.getContentType())  
                    .build(), RequestBody.fromInputStream(file.getInputStream(),file.getSize()));  
            RustFSUploadResult uploadResult = new RustFSUploadResult();  
            uploadResult.setName(file.getOriginalFilename());  
            uploadResult.setUrl(ENDPOINT + "/" + BUCKET\_NAME + "/" + file.getOriginalFilename());  
            return CommonResult.success(uploadResult);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return CommonResult.failed();  
    }  
  
    @Operation(summary = "文件删除")  
    @RequestMapping(value = "/delete", method = RequestMethod.POST)  
    @ResponseBody  
    public CommonResult delete(@RequestParam("objectName") String objectName) {  
        // 删除对象  
        s3Client.deleteObject(DeleteObjectRequest.builder()  
                .bucket(BUCKET\_NAME)  
                .key(objectName)  
                .build());  
        return CommonResult.success(null);  
    }  
  
    /**  
     * 判断Bucket是否存在  
     */  
    private boolean bucketExists(String bucketName) {  
        try {  
            s3Client.headBucket(request -> request.bucket(bucketName));  
            returntrue;  
        }  
        catch (NoSuchBucketException exception) {  
            returnfalse;  
        }  
    }  
  
    /**  
     * 创建存储桶的访问策略,设置为只读权限  
     */  
    private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) {  
        BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder()  
                .Effect("Allow")  
                .Principal(BucketPolicyConfigDto.Principal.builder().AWS(new String[]{"*"}).build())  
                .Action(new String[]{"s3:GetObject"})  
                .Resource(new String[]{"arn:aws:s3:::"+bucketName+"/*"}).build();  
        return BucketPolicyConfigDto.builder()  
                .Version("2012-10-17")  
                .Statement(CollUtil.toList(statement))  
                .build();  
    }  
}  

  • 上述代码中 添加Bucket的访问策略 的逻辑,主要是通过实体类BucketPolicyConfigDto生成了策略对应的JSON配置,生成配置如下;
  
{  
  "Version": "2012-10-17",  
"Statement": [  
    {  
      "Effect": "Allow",  
      "Principal": {  
        "AWS": [  
          "*"  
        ]  
      },  
      "Action": [  
        "s3:GetObject"  
      ],  
      "Resource": [  
        "arn:aws:s3:::simple/*"  
      ]  
    }  
  ]  
}  

  • 由于我们的项目中集成了Swagger,可以直接通过接口文档进行测试,选择好文件后调用 文件上传 接口,访问地址:http://localhost:8088/swagger-ui.html

picture.image

  • 上传成功后我们可以通过返回的url进行访问,由于我们设置的访问策略为 公开只读 策略,可以正常访问;

picture.image

  • 再调用下 文件删除 接口,传入对应的objectName即可将文件删除。

picture.image

总结

今天给大家分享了RustFS的控制台使用和结合SpringBoot的使用,对比MinIO它的控制台功能确实更强大,感兴趣的小伙伴可以尝试下它!

项目地址

https://github.com/rustfs/rustfs


最后欢迎加入苏三的星球,你将获得:100万QPS短链系统、复杂的商城微服务系统、苏三AI项目、刷题吧小程序、秒杀系统、商城系统、秒杀系统、代码生成工具等8个项目的源代码、开发教程和技术答疑。

系统设计、性能优化、技术选型、底层原理、Spring源码解读、工作经验分享、痛点问题、面试八股文等多个优质专栏。

还有1V1免费修改简历、技术答疑、职业规划、送书活动、技术交流。

扫描下方二维码,可以优惠30元:

picture.image

只有20张优惠券,数量有限,先到先得。

目前星球已经更新了5800+篇优质内容,还在持续爆肝中.....

星球已经被官方推荐了3次,收到了小伙伴们的一致好评。戳我加入学习,已有1900+小伙伴加入学习。

picture.image

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
基于 Ray 的大模型离线推理
大模型离线推理,是指在具有数十亿或数万亿参数的大规模模型上进行分布式推理的过程。相较于常规模型推理,在模型切分、数据处理和数据流、提升 GPU 利用率方面面临了很大挑战。本次分享将介绍如何利用 Ray 及云原生优势助力大模型离线推理。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论