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

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

简介

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

RustFS的主要特效如下:

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

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

安装

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

  • 首先使用如下命令下载RustFS的镜像;
bash 复制代码
docker pull rustfs/rustfs
  • 下载完成后使用如下命令运行RustFS的容器;
bash 复制代码
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

这或许是一个对你有用的开源项目,mall项目是一套基于SpringBoot3 + Vue 的电商系统(Github标星60K),后端支持多模块和2024最新微服务架构,采用Docker和K8S部署。包括前台商城项目和后台管理系统,能支持完整的订单流程!涵盖商品、订单、购物车、权限、优惠券、会员、支付等功能!

项目演示:

控制台使用

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

  • 选择文件浏览器功能,点击右上角的创建存储桶按钮即可创建存储桶;
  • 点击存储桶对应的配置按钮即可进行配置,例如修改下存储桶的访问策略;
  • 进入存储桶后,点击右上角上传文件按钮,即可上传文件,支持同时上传多个文件;
  • 点击文件,选择预览,即可预览上传后的文件;
  • 选择访问密钥功能,可以创建一个有过期时间的密钥,并且可以设置文件访问策略;
  • 选择用户功能,可以进行用户的管理并分配用户的访问策略;
  • 选择性能功能,可以查看当前RustFS服务器的基本信息。

结合SpringBoot实现文件上传

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

  • 首先我们需要在项目的pom.xml文件中添加AWS 33 Java SDK相关依赖;
xml 复制代码
<!--AWS 33 Java SDK相关依赖-->
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>s3</artifactId>
    <version>${aws-s3-sdk.version}</version>
</dependency>
  • 然后在application.yml配置文件中添加RustFS的连接信息配置;
yaml 复制代码
rustfs:
  endpoint: http://192.168.3.101:9000
  bucketName: simple
  accessKey: rustfsadmin
  secretKey: rustfsadmin
  • 接下来创建RustFS的Java配置类,用于读取配置文件中的连接配置,然后实例化S3 客户端对应的Bean;
java 复制代码
/**
 * @auther macrozheng
 * @description RustFS配置类
 * @date 2025/7/23
 * @github https://github.com/macrozheng
 */
@Configuration
public class 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不存在时先创建并设置访问策略为公开只读;
java 复制代码
/**
 * @auther macrozheng
 * @description RustFS对象存储管理Controller
 * @date 2025/7/22
 * @github https://github.com/macrozheng
 */
@Slf4j
@Controller
@Tag(name = "RustFSController", description = "RustFS对象存储管理")
@RequestMapping("/rustfs")
public class 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));
            return true;
        }
        catch (NoSuchBucketException exception) {
            return false;
        }
    }

    /**
     * 创建存储桶的访问策略,设置为只读权限
     */
    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配置,生成配置如下;
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
  • 上传成功后我们可以通过返回的url进行访问,由于我们设置的访问策略为公开只读策略,可以正常访问;
  • 再调用下文件删除接口,传入对应的objectName即可将文件删除。

总结

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

项目地址

github.com/rustfs/rust...

项目源码地址

github.com/macrozheng/...

相关推荐
一 乐28 分钟前
心理咨询|学生心理咨询评估系统|基于Springboot的学生心理咨询评估系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·后端·论文·毕设·学生心理咨询评估系统
anthem3738 分钟前
第三阶段_大模型应用开发-Day 4: RAG检索增强生成技术
后端
Java技术小馆39 分钟前
Gemini Storybook AI驱动的交互式故事创作
java·程序员·架构
用户4099322502121 小时前
如何让Celery任务像VIP客户一样享受优先待遇?
后端·github·trae
dylan_QAQ1 小时前
【附录】Spring 环境配置 基础及应用
后端·spring
码神本神1 小时前
(附源码)基于Spring Boot的4S店信息管理系统 的设计与实现
java·spring boot·后端
天天摸鱼的java工程师1 小时前
SpringBoot + Seata + MySQL + RabbitMQ:金融系统分布式交易对账与资金清算实战
java·后端·面试
anthem372 小时前
第三阶段_大模型应用开发-Day 3: 大模型推理优化与部署
后端
dylan_QAQ2 小时前
【附录】Spring 资源访问 基础及应用
后端·spring
别来无恙1492 小时前
Spring Boot文件上传功能实现详解
java·spring boot·文件上传