搭建高性能分布式存储-minio
文章目录
- 搭建高性能分布式存储-minio
- Docker搭建minio(单机部署+纠删码模式)⭐
- 创建minio的bucket(桶)⭐
- SpringBoot+minio项目实战 ⭐
- 1:导入minio的maven依赖
- 2:编写MinioProperties.class
- 3:application.yml:
- 4:MinioConfig.class配置类
- 5:ResponseResult(统一响应结果)
- 6:ResponseType(响应类型枚举类)
- 7:UploadController.class(上传接口)
- 8:上传service接口
- 9:上传service接口实现类:
搭建高性能分布式存储-minio
Docker搭建minio(单机部署+纠删码模式)⭐
- 1:使用minio Docker镜像,在在单机中使用EC纠删码模式部署,8块盘中启动minio服务:
- 注意:MINIO_ROOT_PASSWORD初始化默认密码长度必须要达到8位。
docker run --name minio -d \-p 9000:9000 \-p 50000:50000 \-v /mnt/minio/data1:/data1 \-v /mnt/minio/data2:/data2 \-v /mnt/minio/data3:/data3 \-v /mnt/minio/data4:/data4 \-v /mnt/minio/data5:/data5 \-v /mnt/minio/data6:/data6 \-v /mnt/minio/data7:/data7 \-v /mnt/minio/data8:/data8\-e MINIO_ROOT_USER="root" \-e MINIO_ROOT_PASSWORD="12345678" \minio/minio:latest server /data{1...8} --console-address ":50000"
- 2:访问minio控制台:(http://服务器ip:50000/)
创建minio的bucket(桶)⭐







SpringBoot+minio项目实战 ⭐
1:导入minio的maven依赖
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.4.3</version>
</dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version>
</dependency>
2:编写MinioProperties.class
package com.boot.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;/*** 高性能分布式存储-minio属性类** @author youzhengjie* @date 2022/10/28 00:22:48*/
@Component
@Data
@ConfigurationProperties(prefix = "minio")
@EnableConfigurationProperties({MinioProperties.class
})
public class MinioProperties {/*** minio的通信端点(url),和控制台端点不一样*/private String endpoint;/*** 说白了就是minio的帐号*/private String accessKey;/*** 说白了就是minio的密码*/private String secretKey;/*** 指定操作哪一个桶*/private String bucketName;
}
3:application.yml:
- 注意:记得把下面的配置属性修改成你自己的!
minio:endpoint: http://192.168.184.123:9000access-key: rootsecret-key: 12345678bucket-name: security-jwt2-bucket
4:MinioConfig.class配置类
- 作用是将MinioClient交给Spring管理,方便后续直接@AutoWired注入即可使用)
package com.boot.config;import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** minio配置类** @author youzhengjie* @date 2022/10/28 00:30:31*/
@Configuration
public class MinioConfig {@Autowiredprivate MinioProperties minioProperties;/*** minio-client bean** @return {@link MinioClient}*/@Beanpublic MinioClient minioClient(){return MinioClient.builder()//配置minio的通信端点(url),和控制台端点不一样.endpoint(minioProperties.getEndpoint())//配置minio的帐号密码.credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey()).build();}}
5:ResponseResult(统一响应结果)
package com.boot.data;import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 统一响应结果*/
@JsonInclude(JsonInclude.Include.NON_NULL) //为null的字段不进行序列化
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ResponseResult<T> {/*** 响应状态码*/private Integer code;/*** 响应状态码对应的信息提示*/private String msg;/*** 返回给前端的数据*/private T data;public ResponseResult(Integer code, String msg) {this.code = code;this.msg = msg;}public ResponseResult(Integer code, T data) {this.code = code;this.data = data;}}
6:ResponseType(响应类型枚举类)
package com.boot.enums;/*** 响应类型枚举类* @author youzhengjie* @date 2022-09-22 22:47:21*/
public enum ResponseType {/*** 文件操作状态*/IMAGE_UPLOAD_SUCCESS(901,"图片上传成功"),IMAGE_UPLOAD_ERROR(902,"图片上传失败"),FILE_FORMAT_UNSUPPORT(903,"不支持该文件格式,上传失败"),FILE_DELETE_SUCCESS(904,"文件删除成功"),FILE_DELETE_ERROR(905,"文件删除失败"),;private int code;private String message;ResponseType(int code, String message) {this.code = code;this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}
7:UploadController.class(上传接口)
@RestController
@Api("上传接口")
@RequestMapping(path = "/upload")
@Slf4j
public class UploadController {@Autowired@Qualifier("minioUploadServiceImpl") //指定spring注入的实现类private OssUploadService ossUploadService;/*** 上传头像** @param avatarFile 头像文件(名字一定要和el-upload的:name属性一致)* @return {@link ResponseResult}*/@OperationLog("上传头像")@PostMapping(path = "/avatar")@ApiOperation("上传头像")public ResponseResult uploadAvatar(MultipartFile avatarFile){ResponseResult result = ossUploadService.imageUpload(avatarFile);return result;}/*** 文件删除** @param fileFullName 文件名* @return {@link ResponseResult}*/@OperationLog("文件删除")@DeleteMapping(path = "/fileDelete")@ApiOperation("文件删除")public ResponseResult fileDelete(@RequestParam("fileFullName") String fileFullName){return ossUploadService.fileDelete(fileFullName);}/*** 文件下载** @param fileName 文件名称* @param response 响应*/@GetMapping(path = "/fileDownload")@ApiOperation("文件下载")public void fileDownload(@RequestParam("fileName") String fileName, HttpServletResponse response){ossUploadService.fileDownload(fileName,response);}
}
8:上传service接口
package com.boot.service;import com.boot.data.ResponseResult;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;/*** oss上传service接口* @author youzhengjie* @date 2022-10-06 23:13:28*/
public interface OssUploadService {/*** oss图片上传* @param imageFile* @return 上传结果*/ResponseResult imageUpload(MultipartFile imageFile);/*** oss文件删除* @param fileFullName 文件全名,** @return 删除结果*/ResponseResult fileDelete(String fileFullName);/*** 文件下载** @param fileName 文件名称* @param response 响应*/default void fileDownload(String fileName, HttpServletResponse response){throw new UnsupportedOperationException("该实现类暂不支持文件下载操作,请切换到其他实现类!");}}
9:上传service接口实现类:
package com.boot.service.impl;import com.boot.config.MinioProperties;
import com.boot.data.ResponseResult;
import com.boot.enums.ResponseType;
import com.boot.service.OssUploadService;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;/*** minio上传服务service impl** @author youzhengjie* @date 2022/10/28 13:59:35*/
@Service("minioUploadServiceImpl")
@Slf4j
public class MinioUploadServiceImpl implements OssUploadService {@Autowiredprivate MinioProperties minioProperties;/*** 注入MinioClient,用于操作minio*/@Autowiredprivate MinioClient minioClient;/*** 检查文件是否是图片类型* @param originalFilename* @return true代表是图片,false则不是图片*/private boolean isImage(String originalFilename){//将文件名全部变小写String lowerOriginalFilename = originalFilename.toLowerCase();return lowerOriginalFilename.endsWith(".jpg") ||lowerOriginalFilename.endsWith(".png") ||lowerOriginalFilename.endsWith(".jpeg");}/*** minio图片上传** @param imageFile 图像文件* @return {@link ResponseResult}*/@Overridepublic ResponseResult imageUpload(MultipartFile imageFile) {//封装响应结果ResponseResult<Object> result = new ResponseResult<>();try {//获取上传前的文件原名String oldFileName = imageFile.getOriginalFilename();//如果不是图片则直接返回if(!isImage(oldFileName)){result.setCode(ResponseType.FILE_FORMAT_UNSUPPORT.getCode());result.setMsg(ResponseType.FILE_FORMAT_UNSUPPORT.getMessage());return result;}//以日期作为目录,每一天的图片都会放到不同的目录下,方便管理String fileDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/"));//UUID文件名String uuidFileName = UUID.randomUUID().toString().replaceAll("-", "");//获取文件后缀名 .jpgString fileSuffix= oldFileName.substring(oldFileName.lastIndexOf("."));//上传到minio中的新的图片文件名String newFileName = new StringBuilder().append(fileDir).append(uuidFileName).append(fileSuffix).toString();//获取文件流InputStream inputStream = imageFile.getInputStream();//获取文件大小long size = imageFile.getSize();//获取内容类型String contentType = imageFile.getContentType();//构建文件上传所需要的东西(PutObjectArgs)PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(minioProperties.getBucketName()).object(newFileName).stream(inputStream, size, -1).contentType(contentType).build();//开始进行minio文件上传minioClient.putObject(putObjectArgs);//获取该上传到minio的文件的url(使外网可以访问)String fileUrl=minioProperties.getEndpoint()+"/"+minioProperties.getBucketName()+"/"+newFileName;result.setCode(ResponseType.IMAGE_UPLOAD_SUCCESS.getCode());result.setMsg(ResponseType.IMAGE_UPLOAD_SUCCESS.getMessage());result.setData(fileUrl);return result;}catch (Exception e){e.printStackTrace();result.setCode(ResponseType.IMAGE_UPLOAD_ERROR.getCode());result.setMsg(ResponseType.IMAGE_UPLOAD_ERROR.getMessage());return result;}}/*** minio文件删除** @param fileFullName 文件全名 。格式例如:2022/10/28/4f74aa358a4548d4860c110ebec3831f.jpg* @return {@link ResponseResult}*/@Overridepublic ResponseResult fileDelete(String fileFullName) {//封装响应结果ResponseResult<Object> result = new ResponseResult<>();try {RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileFullName).build();minioClient.removeObject(removeObjectArgs);result.setCode(ResponseType.FILE_DELETE_SUCCESS.getCode());result.setMsg(ResponseType.FILE_DELETE_SUCCESS.getMessage());return result;}catch (Exception e){e.printStackTrace();result.setCode(ResponseType.FILE_DELETE_ERROR.getCode());result.setMsg(ResponseType.FILE_DELETE_ERROR.getMessage());return result;}}/*** minio文件下载。** @param fileName 文件名称 。格式例如:2022/10/28/4f74aa358a4548d4860c110ebec3831f.jpg* @param response 响应*/@Overridepublic void fileDownload(String fileName, HttpServletResponse response) {try {// 获取对象信息StatObjectArgs statObjectArgs = StatObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileName).build();StatObjectResponse statObject = minioClient.statObject(statObjectArgs);/*** 描述: content-type 指示响应内容的格式* content-disposition 指示如何处理响应内容。* 一般有两种方式:* inline:直接在页面显示-预览* attachment:以附件形式下载-下载*/response.setContentType(statObject.contentType());
// response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(fileName, "UTF-8"));response.setHeader("Content-Disposition", "attachment; filename=" +URLEncoder.encode(fileName, "UTF-8"));InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minioProperties.getBucketName()).object(fileName).build());IOUtils.copy(inputStream,response.getOutputStream());}catch (Exception e){throw new RuntimeException("文件下载失败");}}
}
相关文章:
搭建高性能分布式存储-minio
文章目录 搭建高性能分布式存储-minioDocker搭建minio(单机部署纠删码模式)⭐创建minio的bucket(桶)⭐SpringBootminio项目实战 ⭐1:导入minio的maven依赖2:编写MinioProperties.class3:applica…...
leetCode 137. 只出现一次的数字 II(拓展篇) + 模5加法器 + 真值表(数字电路)
leetCode 137. 只出现一次的数字 II 题解可看我的往期文章 leetCode 137. 只出现一次的数字 II 位运算 模3加法器 真值表(数字电路) 有限状态机-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/134138112?spm1001.2014.3001.5501…...
docker导致root空间满进入不了系统解决方案
由于docker建立镜像会产生很多缓存文件,最终导致root目录满,进入不了系统 df -h docker默认路径是在/var/lib/docker下 可以通过命令查看docker占用空间 docker system df 如果占用空间太大 可用以下命令清理 $ docker image prune -h Flag shorth…...
uni-app遮罩遮住小程序tabbar
uni-app遮罩遮住小程序tabbar 1、用uni-app自带的方法显示隐藏 //通过弹窗显隐控制导航栏的显示和隐藏 const popupChange e >{if(e.show){//隐藏tabbaruni.hideTabBar()}else{//显示tabbaruni.showTabBar()}state.searchIcon e.show } //通过弹窗显隐控制导航栏的显示和…...
Flink on yarn 加载失败plugins失效问题解决
Flink on yarn 加载失败plugins失效问题解决 flink版本:1.13.6 1. 问题 flink 任务运行在yarn集群,plugins加载失效,导致通过扩展资源获取任务参数失效 2. 问题定位 yarn容器的jar包及插件信息,jar包是正常上传 源码定位 加载plugins入口,TaskMana…...
显卡服务器的特点和优势在哪里
随着科技的发展以及人们对于计算机性能的需求提高,显卡服务器是主要使用图形处理器进行计算和运算,拥有更加强大的计算能力,今天小编就来给大家讲一讲显卡服务器的特点和优势是什么! 1.高可靠性:显卡服务器采用高品质的…...
c++设计模式二:原型模式
使用场景:当需要构建多个相同的类对象时,而且该类对象结构较为复杂,如果每个都重新组织构建会很麻烦。 其实,就是写一个拷贝构造函数,或者写一个拷贝每个成员变量的clone()方法。 举例说明:比如一个相亲网站…...
【Qt控件之QMessageBox】详解
Qt控件之QMessageBox 描述基于属性的API富文本和文本格式属性严重程度以及图标和Pixmap属性静态函数API 高级用法默认按钮和退出按钮示例使用场景 描述 QMessageBox类提供了一个模态对话框,用于通知用户或向用户提问并接收答案。 消息框显示一个主要文本以提醒用户…...
SSH安全登录远程主机
SSH服务器简介 SSH即Security SHell的意思,它可以将连线的封包进行加密技术,之后进行传输,因此相当的安全。 SSH是一种协议标准,其目的是实现安全远程登录以及其它安全网络服务。 SSH协定,在预设的状态下,…...
揭秘!产品经理提升效率的秘密武器:10款AI生成PPT工具
AI的爆炸式增长表现令人惊艳,现有的各类AI工具正在重塑各行各业,不同程度地提高人们的工作效率,并有望创造新的职业机会。但是,面对市面上数量众多的AI工具,且每周都会蹦出新的产品,即便是以好奇心富称的产…...
Oracle修改带数据的字段类型
insert into TNW_FUND_SELORG(TFDINFOID,TSOINFOID) select TFD_INFO_ID,TSO_INFO_ID from TFD_SEL_FUNDLINK_TO_OLDFUNDWEB_DB /*修改原字段名*/ ALTER TABLE 表名 RENAME COLUMN 字段名 TO 字段名1; /*添加一个和原字段同名的字段*/ ALTER TABLE 表名 ADD 字段名 VARCHAR…...
WebService接口方式和Restful接口这两者有什么区别和相同点
WebService和RESTful接口都是用于在网络上进行通信和数据交换的技术,但它们在设计和使用上有一些重要的区别和相似之处。 相同点: 基于HTTP协议:无论是WebService还是RESTful接口,它们都是通过HTTP协议进行通信的。 支持多种数据…...
jenkins自动化操作步骤(gitblit)
1、登陆地址: http://xxxxxxxxx.org:xxxx/ admin/xxxx 2、创建任务 选择构建一个maven项目 3、配置 最多只保留一天一个任务 选择git仓库和账号密码 选择代码对应分支 build项: 1)使用父项目的pom文件:k56-boot/pom.xml 2&…...
centos中mongodb设置服务自启动并 允许远程IP访问
安装mongodb参考 注意的是配置文件需要把journal设置为true 制作为系统服务 创建MongoDB服务文件。运行以下命令创建服务文件/etc/systemd/system/mongod.service: vi /etc/systemd/system/mongod.service [Unit] DescriptionMongoDB Database Server Documenta…...
实时定位和配送追踪:开发万岳同城外卖APP的关键技术特性
随着生活节奏的不断加快,外卖服务已经成为许多人日常生活中不可或缺的一部分。无论是工作日的午餐,还是周末的家庭聚会,外卖APP已经成为满足各种美食需求的首选方式。然而,同城外卖APP的成功不仅仅取决于美味的食物选择࿰…...
数据库强化(3.存储过程)
1.什么是存储过程? 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。MySQL 5.0 版本开始支持存储过程。 它是为了完成特定功能的SQL语句集,经编译创建并保存在数据库中&a…...
雅思小作文笔记
mostly from Simon’s methods and techniques remember the task is describe what you see, not give an opinion. Just write a report.no conclusion, just a summary(the overview) Question type 小作文的题目类型大致如上 Simon所述,在描述数字的时候&…...
Java List Set Map
一、List 1.1 ArrayList 1.2 LinkedList 二、Set 2.1 HashSet 2.2 TreeSet 2.3 LinkedHashSet 三、Map 3.1 HashMap 3.2 TreeMap 3.3 LinkedHashMap 四、对比 类型底层结构重复null值场景备注查询删除新增ListArrayList动态数组可允许快速随机访问元素0(1)0(n)尾部增加0&a…...
【数据结构】数组和字符串(十三):链式字符串的基本操作(串长统计、查找、复制、插入、删除、串拼接)
文章目录 4.3 字符串4.3.1 字符串的定义与存储4.3.2 字符串的基本操作(链式存储)1. 结构体2. 初始化3. 判空4. 串尾添加5. 打印6. 串长统计7. 查找8. 复制9. 插入10. 删除11. 串拼接12. 销毁13. 主函数14. 代码整合 4.3 字符串 字符串(String)是由零个或…...
Python3 获取当前服务器公网 IP 地址
有同学问我如何使用 Python 获取服务器公网的 IP 地址呢?我测试几个发现,方法有很多,好用的就发现一种,即直接使用 Python 自带的 socket 包。 代码示例: # 获取主机 IP dgram socket.socket(socket.AF_INET, socke…...
终极指南:用WinDiskWriter在Mac上制作Windows启动盘,简单三步搞定
终极指南:用WinDiskWriter在Mac上制作Windows启动盘,简单三步搞定 【免费下载链接】windiskwriter 🖥 A macOS app that creates bootable USB drives for Windows. 🛠 Patches Windows 11 to bypass TPM and Secure Boot require…...
芯片验证工程师必备:SVA断言中的assert/cover/assume核心区别与典型误用案例
芯片验证工程师必备:SVA断言中的assert/cover/assume核心区别与典型误用案例 在芯片验证领域,SystemVerilog Assertion(SVA)是验证工程师不可或缺的利器。对于1-3年经验的验证工程师而言,深入理解assert、cover和assum…...
用Python脚本让Crazyflie 2.X无人机动起来:手把手教你写第一个自主飞行程序
用Python脚本让Crazyflie 2.X无人机动起来:从零编写自主飞行程序 当第一次看到Crazyflie这个巴掌大的无人机在桌面上悬停时,我意识到微小型飞行器的编程控制远比想象中更有趣。与传统无人机不同,Crazyflie 2.X系列通过Python脚本就能实现毫米…...
3分钟上手!AI驱动的代码学习助手完全指南
3分钟上手!AI驱动的代码学习助手完全指南 【免费下载链接】Tutorial-Codebase-Knowledge Turns Codebase into Easy Tutorial with AI 项目地址: https://gitcode.com/gh_mirrors/tu/Tutorial-Codebase-Knowledge Tutorial-Codebase-Knowledge是一款AI驱动的…...
基于DWS构建RAG框架生成行业调研报告
1. 前言 适用版本:【DWS 9.1.1.200(及以上)】 在信息爆炸的时代,行业调研报告的生成正面临数据规模庞大、信息碎片化、人工处理效率低等多重挑战。检索增强生成(RAG, Retrieval-Augmented Generation)作为…...
DanKoe 视频笔记:通用时代崛起:如何通过多种兴趣茁壮成长
在本教程中,我们将探讨为何在当今的“创作者经济”中,拥有广泛兴趣和技能的“通才”比只精通一门的“专家”更具优势。我们将分析背后的原因,并提供一套实用的步骤,帮助你作为一名通才,在数字世界中建立个人品牌、吸引…...
YOLOv8安全帽检测实战:如何用自定义数据集提升模型在复杂工地场景的识别率?
YOLOv8安全帽检测实战:从100张样本到工业级部署的优化全流程 在建筑工地、电力巡检等高危作业场景中,安全帽佩戴检测系统正逐渐从"可有可无"的辅助工具转变为"不可或缺"的合规刚需。但当我们把实验室里准确率90%的模型部署到真实工地…...
Linux用户管理全攻略:从创建到权限配置
1. Linux用户管理基础入门 刚接触Linux系统的朋友,经常会遇到这样的困惑:为什么有些命令普通用户不能执行?为什么新建的用户连基本的命令补全都没有?其实这些都是用户管理的问题。作为一个用了10年Linux的老鸟,今天我就…...
终极鸣潮工具箱:3大核心功能让游戏体验翻倍的完整指南
终极鸣潮工具箱:3大核心功能让游戏体验翻倍的完整指南 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools WaveTools(鸣潮工具箱)是一款专为《鸣潮》玩家设计的开源游戏辅助…...
全新升级:基于Vue3新标准的企业级后台综合解决方案实战(附源码课件)
先放资源:https://pan.quark.cn/s/a99f364f3e28 引言:后台前端开发的工程化跃迁之路 在当前互联网行业的技术迭代周期中,Web前端大厂工程师的能力模型正在经历从"页面仔"到"工程架构师"的深刻变革。单纯掌握Vue2选项式API和基础CRUD开发已无法满足阿里…...
