在项目开发中,文件存储是一个常见的需求。除了主流的OSS服务,MinIO等自建方案也备受青睐。近期,一款名为RustFS的全新开源分布式对象存储软件进入了开发者视野。它自带功能完善的管理控制台,并提供与AWS S3协议的兼容性,为开发者提供了又一个强大的存储选择。
简介
RustFS是一个基于Rust语言开发的高性能分布式对象存储软件。它采用Apache 2.0开源协议,在开源后短时间内就获得了广泛的关注。与MinIO类似,它具有部署简单、性能高、兼容S3等优点。
RustFS的主要特性如下:
- 高性能:基于Rust构建,具有较高的性能和响应速度。
- 分布式架构:可扩展且容错的设计,适用于大规模部署。
- AWS S3 兼容性:可使用AWS S3 SDK来管理它。
- 数据湖支持:针对大数据和AI工作负载进行了优化。
- 开源:采用Apache 2.0许可证,鼓励社区贡献。
- 用户友好:具有可视化管理控制台,方便管理。
以下是RustFS管理控制台的界面效果图:

安装
使用Docker是部署RustFS最便捷的方式。
-
拉取镜像
首先,使用以下命令拉取RustFS的Docker镜像:
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
命令说明:
-p 9000:9000: 将容器的9000端口映射到宿主机。
-e: 设置环境变量,此处指定了默认的管理员账号和密码。
-v: 挂载数据卷和时区文件。
-
访问控制台
容器启动成功后,即可通过浏览器访问管理控制台。默认访问地址为 http://<你的服务器IP>:9000,默认账号密码为 rustfsadmin / rustfsadmin。

控制台使用
RustFS的控制台界面直观,功能清晰。
-
创建存储桶(Bucket)
在“文件浏览器”页面,点击右上角的“创建存储桶”按钮即可创建新的存储空间。

-
配置存储桶
点击存储桶对应的“配置”按钮,可以修改其访问策略等设置。

-
上传与预览文件
进入存储桶后,点击“上传文件”可上传单个或多个文件。上传完成后,点击文件即可选择“预览”功能。


-
访问密钥与用户管理
在“访问密钥”功能中,可以创建具有过期时间和特定策略的临时密钥。
在“用户”功能中,可以管理用户并为其分配访问策略。


-
系统监控
“性能”页面提供了服务器的基本运行信息概览。

结合SpringBoot实现文件上传
下面演示如何在一个SpringBoot应用中集成RustFS,实现文件的上传与删除功能。
-
添加依赖
在项目的 pom.xml 中添加AWS S3 Java SDK依赖。
<!-- AWS S3 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: springboot-bucket
accessKey: rustfsadmin
secretKey: rustfsadmin
-
配置S3客户端
创建一个配置类,读取配置并初始化S3客户端。
@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() {
return S3Client.builder()
.endpointOverride(URI.create(ENDPOINT))
.region(Region.US_EAST_1) // RustFS不校验region,可写死
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY)))
.forcePathStyle(true) // 关键配置!RustFS需启用Path-Style访问
.build();
}
}
-
实现文件上传与删除Controller
创建控制器,实现文件上传(自动创建Bucket并设置公开读策略)和删除功能。
@Slf4j
@RestController
@RequestMapping("/rustfs")
public class RustFSController {
@Autowired
private S3Client s3Client;
@Value("${rustfs.bucketName}")
private String BUCKET_NAME;
@Value("${rustfs.endpoint}")
private String ENDPOINT;
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public CommonResult upload(@RequestPart("file") MultipartFile file) {
// 判断并创建Bucket
if (!bucketExists(BUCKET_NAME)) {
s3Client.createBucket(CreateBucketRequest.builder().bucket(BUCKET_NAME).build());
log.info("Bucket created: {}", BUCKET_NAME);
// 设置Bucket策略为公开只读
String policy = JSONUtil.toJsonStr(createBucketPolicyConfigDto(BUCKET_NAME));
PutBucketPolicyRequest policyReq = PutBucketPolicyRequest.builder()
.bucket(BUCKET_NAME)
.policy(policy)
.build();
s3Client.putBucketPolicy(policyReq);
}
// 上传文件
try {
s3Client.putObject(PutObjectRequest.builder()
.bucket(BUCKET_NAME)
.key(file.getOriginalFilename())
.contentType(file.getContentType())
.build(),
RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
RustFSUploadResult result = new RustFSUploadResult();
result.setName(file.getOriginalFilename());
result.setUrl(ENDPOINT + "/" + BUCKET_NAME + "/" + file.getOriginalFilename());
return CommonResult.success(result);
} catch (IOException e) {
e.printStackTrace();
return CommonResult.failed("上传失败");
}
}
@PostMapping("/delete")
public CommonResult delete(@RequestParam 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 e) {
return false;
}
}
// 生成公开只读策略JSON
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策略JSON配置如下:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::springboot-bucket/*"]
}
]
}
-
接口测试
启动应用后,可以通过Swagger UI(或使用Postman等工具)测试接口。
- 文件上传:调用上传接口,成功后返回文件访问URL。

由于设置了公开读策略,可以直接通过返回的URL访问文件。

- 文件删除:调用删除接口,传入文件名即可删除指定文件。

总结
本文介绍了新兴的分布式对象存储系统RustFS,涵盖了其Docker部署、控制台功能详解以及与SpringBoot应用的整合实战。相比MinIO,RustFS提供了一个功能更为丰富的管理界面。对于正在寻找高性能、可扩展且易于管理的自建存储方案的开发者来说,RustFS是一个值得尝试的选择。
项目地址
|