minio简单使用

news2024/10/10 3:07:44

文章目录

  • 简介
  • 官方地址
  • Linux下载安装
    • 安装服务
    • 启动
    • 关闭
    • 帮助命令
  • java开发minio
    • 依赖包
    • 新建项目
      • pom
      • 配置文件
      • 配置类
      • Service
      • 测试类
      • 运行测试
    • Api使用前言
    • 针对桶的操作
      • 查看某个桶是否存在
      • 创建一个桶
      • 返回桶列表
      • 删除一个桶
    • 针对文件的操作
      • 上传文件到桶中(本地文件上传)
      • 上传文件到桶中(基于io流上传)
      • Controller上传文件到minio
      • 检查某文件的状态
      • 生成文件访问的URL
      • 从指定的桶中下载文件
      • 列出桶中所有文件
      • 删除指定桶中的文件
  • 纠删码模式单机部署
    • 纠删码介绍
    • 单机多磁盘部署准备
    • 纠删码模式启动

简介

MinIO 是使用 Go (Golang) 开发的一个高性能的开源对象存储服务,专为处理海量非结构化数据(如图片、视频、日志文件、备份等)而设计,且兼容 Amazon S3 的 API。这使得它可以与现有的 S3 客户端、工具和应用程序集成。以下是 MinIO 的详细介绍:

MinIO 的主要特点

  • S3 兼容:MinIO 完全兼容 Amazon S3 API,任何支持 S3 的客户端和应用都可以无缝切换到 MinIO。
  • 高性能:MinIO 可以处理大规模的对象存储需求,能够提供非常高的吞吐量。它使用高效的内存管理和网络层,适合数据密集型应用程序,如大数据、AI/ML、日志分析等。
  • 轻量级设计:MinIO 的二进制文件仅几十 MB,且非常轻量级。它可以在本地计算机、虚拟机、容器和 Kubernetes 等多种环境中轻松部署和运行。
  • 分布式架构:MinIO 支持分布式存储,可以将多个服务器或节点组成集群,实现数据的冗余、容错和高可用性。
  • 企业级功能
    • 多租户:MinIO 支持多租户架构,可将一个集群拆分为多个租户,满足复杂的权限管理和隔离需求。
    • 对象锁定:支持对象的不可变性设置,适合合规性存储需求,如金融和医疗等领域的数据存档。
    • 数据加密:支持静态和传输中数据的加密,确保数据安全。
    • 纠删码:MinIO 使用纠删码技术来分散和保护数据,提供高度的容错能力,同时减少存储开销。

架构与技术细节

  • 单节点与多节点模式:MinIO 可以在单节点部署,也支持多节点、分布式部署模式。在分布式模式下,数据会自动跨多个节点进行复制或通过纠删码保护,保证系统的高可用性。
  • 高扩展性:MinIO 的分布式模式使得它能够在大规模对象存储中处理数十亿个对象。它的设计能够动态扩展,并且提供了线性扩展能力。
  • 对象锁定与生命周期管理:MinIO 支持对象的生命周期策略和锁定机制,允许定义数据存储的保留期和删除策略,适用于日志、备份等长期存储需求。

MinIO 的典型应用场景

  • 私有云存储:许多企业使用 MinIO 构建内部的私有云对象存储,替代昂贵的公共云存储解决方案。
  • 大数据分析和机器学习:MinIO 高性能的数据传输能力非常适合需要处理大量数据的分析平台和 AI/ML 项目。
  • 备份和恢复:由于其高度可靠的存储和高效的数据保护功能,MinIO 常用于备份、归档和恢复数据的解决方案。
  • 混合云与多云架构:MinIO 的轻量级和兼容性使它能够轻松部署在多个云环境中,支持多云架构。

MinIO 的部署方式

  • 容器化部署:MinIO 可通过 Docker 容器部署,简单且快速。
  • Kubernetes 集成:MinIO 可以与 Kubernetes 集成,支持动态存储卷、持久化存储和自动扩展。

使用 MinIO 的好处

  • 简化存储管理:MinIO 的 S3 API 兼容性和简单的架构设计使得它能够快速集成到现有的基础设施中,减少管理复杂度。
  • 降低存储成本:作为开源软件,MinIO 没有许可费用,且其轻量和高效的特性可以减少基础设施开销。
  • 灵活性:MinIO 支持多种部署方式,用户可以根据需要灵活选择在本地、私有云或多云环境中部署。

MinIO发布了以下软件开发工具包(SDK), 用于通过Api操作minio

  • Go
  • Python
  • Java
  • .NET
  • JavaScript
  • Haskell
  • C++

官方地址

官网地址

英文:https://min.io/
中文:https://www.minio.org.cn/

下载地址

https://min.io/download?license=agpl&platform=docker

image-20240918100548227


Linux下载安装

Centos7下载安装minio

访问下载地址

https://min.io/download?license=agpl&platform=linux

先下载Server,再下载客户端


安装服务

linux版本下载方法如下图,使用Binary或RPM的命令下载即可:

dba3172cde6786542e267d07547d103

这里演示使用Binary二进制,执行上图命令中的wget安装命令:

wget https://dl.min.io/server/minio/release/linux-amd64/minio

后面两条命令分别为修改权限启动minio服务:

chmod +x minio
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"

开始执行安装下载

创建新目录

[root@Centos7 ~]# mkdir /home/minio

下载

[root@Centos7 ~]# cd /home/minio
[root@Centos7 minio]# wget https://dl.min.io/server/minio/release/linux-amd64/minio
--2024-09-18 13:58:35--  https://dl.min.io/server/minio/release/linux-amd64/minio
正在解析主机 dl.min.io (dl.min.io)... 178.128.69.202, 138.68.11.125
正在连接 dl.min.io (dl.min.io)|178.128.69.202|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:103944344 (99M) [application/octet-stream]
正在保存至: “minio”

100%[=========================================================================================================================================>] 103,944,344  195KB/s 用时 4m 13s 

2024-09-18 14:02:49 (401 KB/s) - 已保存 “minio” [103944344/103944344])

改权限并查看

[root@Centos7 minio]# chmod +x minio
[root@Centos7 minio]# ll
总用量 131008
-rwxr-xr-x. 1 root root 103944344 914 20:53 minio

启动

启动minio服务命令解释

MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001" --address ":9000" &

或者

./minio server /mnt/data --console-address ":9001" --address ":9000" &

MINIO_ROOT_USER:指定访问minio的用户名

MINIO_ROOT_PASSWORD:指定访问minio的密码

./minio server:启动minio服务,./代表当前处于存放minio的目录位置,如果在其他目录执行启动,则使用minio存放目录/minio server即可

/mnt/data:指定minio服务器用于存储数据的目录

--console-address ":9001":指定minio控制台的监听地址和端口,冒号不能去掉,它相当于省略了ip,即可以使用任何ip访问minio服务

--address ":9000":指定用于数据API服务的端口,比如java连接minio进行操作时使用此端口

&:后台启动

执行启动

157832b0ccff68249649ffc70227a64

出现黄色信息时,按下回车即可出现[root@Centos7 minio]# ,并且不会停止minio服务。然后记得开放防火墙的9000与9001端口:

  • firewall-cmd --zone=public --add-port=9000/tcp --permanent:开放9000端口
  • firewall-cmd --reload:重启防火墙
[root@Centos7 minio]# firewall-cmd --zone=public --add-port=9000/tcp --permanent
success
[root@Centos7 minio]# firewall-cmd --reload
success
[root@Centos7 minio]# 

开放防火墙端口后后访问上面图片信息中的WebUI来访问控制台页面(API地址用于客户端调用访问,比如java操作minio):

http://192.168.137.200:9001

0b6a2f787b6a20d676f1f069ef2f135

使用命令中的用户名密码adminpassword登录:

asdf123


关闭

关闭minio服务

先查minio服务状态:ps -ef|grep minio,如下信息即为minio服务正在运行

[root@Centos7 minio]# ps -ef|grep minio
root      44109  44055  0 14:47 pts/0    00:00:00 ./minio server /mnt/data --console-address :9001
root      44810  44055  0 14:54 pts/0    00:00:00 grep --color=auto minio

关闭minio服务,只需要kill杀掉上面的进程即可,进程号使用第一行第一个端口号:

[root@Centos7 minio]# kill 44109
INFO: Exiting on signal: TERMINATED
[1]+  完成                  MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"

再查看,minio已关闭:

[root@Centos7 minio]# ps -ef|grep minio
root      45035  44055  0 14:56 pts/0    00:00:00 grep --color=auto minio

帮助命令

执行./minio,查看启动帮助命令:

[root@Centos7 ~]# ./minio
NAME:
  minio - High Performance Object Storage

DESCRIPTION:
  Build high performance data infrastructure for machine learning, analytics and application data workloads with MinIO

USAGE:
  minio [FLAGS] COMMAND [ARGS...]

COMMANDS:
  server  start object storage server
  
FLAGS:
  --certs-dir value, -S value  path to certs directory (default: "/root/.minio/certs")
  --quiet                      disable startup and info messages
  --anonymous                  hide sensitive information from logging
  --json                       output logs in JSON format
  --help, -h                   show help
  --version, -v                print the version
  
VERSION:
  RELEASE.2024-09-13T20-26-02Z

如上,启动命令格式为:minio [FLAGS] COMMAND [ARGS...],其中FLAGSARGS为可选,可不填

USAGE,使用的启动命令格式

格式为:minio [FLAGS] COMMAND [ARGS...],其中FLAGSARGS为可选,可不填

COMMANDS,对应minio [FLAGS] COMMAND [ARGS...]中的COMMAND

只有一个server,代表启动对象存储服务

FLAGS可用的命令如下

对应上面的命令输出:

--certs-dir value, -S value  path to certs directory (default: "/root/.minio/certs")
--quiet                      disable startup and info messages
--anonymous                  hide sensitive information from logging
--json                       output logs in JSON format
--help, -h                   show help
--version, -v                print the version


java开发minio

依赖包

在官网文档出找到SDK–>java快速指南,可以找到maven依赖

b10d35aa7bb785e8996b9aecda1489e

370ec3806a8e36e6ba0208c88080c56

<dependency>
	<groupId>io.minio</groupId>
	<artifactId>minio</artifactId>
	<version>8.5.12</version>
</dependency>

新建项目

建立一个springboot的项目

项目结构

85e7268a257588e9f5a7e3612a19185


pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>minio-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.10</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.5.12</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

配置文件

application.yaml

server:
  port: 8080

#设置文件上传大小
spring:
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 10MB

#自定义minio配置
minio:
  endpoint: http://192.168.137.200:9000 #你的minio地址
  accessKey: admin
  secretKey: password

配置类

读取yaml的MinioProperties

package com.minio.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties {

    private String endpoint;
    private String accessKey;
    private String secretKey;

}

配置minio客户端

package com.minio.config;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {

    @Autowired
    private MinioProperties minioProperties;

    //单例下的 MinioClient 是线程安全的,可以多个请求使用同一个客户端来调用
    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint()) //地址
                .credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey()) //用户名密码
                .build();
    }

}

Service

package com.minio.service;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MinioService {

    @Autowired
    private MinioClient minioClient;

    public void testMinio(){
        System.out.println(minioClient);
    }

}

测试类

package com.minio;

import com.minio.service.MinioService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * 要与上面的主启动类处于同名包内
 *
 * */
@SpringBootTest
public class MinioTest {

    @Autowired
    private MinioService minioService;

    @Test
    public void testOne(){
        minioService.testMinio();
    }
}

运行测试

运行测试方法testOne,输出MinioClient:

io.minio.MinioClient@26c89563


Api使用前言

先介绍minio中的BucketObject,代码中主要操作的就是二者

Bucket:桶,是存储Object的逻辑空间,每个Bucket之间的数据是相互隔离的,对用户而言,相当于存放文件的顶层文件夹

Object:对象,是存放到minio的基本对象,对用户而言,相当于文件

可能遇到的问题

如果出现报错:

error occurred
ErrorResponse(code = RequestTimeTooSkewed, message = The difference between the request time and the server's time is too large.

原因是因为客户端与minio所在服务器时间差距过大导致。服务端linux同步北京时间的方法,安装ntpdate

yum -y install ntp ntpdate

安装后执行同步命令:

ntpdate cn.pool.ntp.org

执行后用date查看当前时间:

[root@Centos7 minio]# ntpdate cn.pool.ntp.org
19 Sep 10:31:39 ntpdate[24198]: step time server 84.16.73.33 offset -0.534266 sec
[root@Centos7 minio]# date
2024年 09月 19日 星期四 10:31:42 CST

其他注意点

重复上传到一个桶的文件会被覆盖,即将同名文件多次上传到同一个桶中,会将原来的文件覆盖


针对桶的操作

查看某个桶是否存在

MinioClient的bucketExists()方法,用于查看某个桶是否存在,返回布尔值:true-存在,false-不存在

示例代码:

package com.minio;

import io.minio.BucketExistsArgs;
import io.minio.MinioClient;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * 要与上面的主启动类处于同名包内
 *
 * */
@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;

    // bucketExists方法,判断某个桶是否存在
    @Test
    public void testBucketExists() throws Exception {

      boolean exists = Client.bucketExists(
                BucketExistsArgs.builder()
                        .bucket("mybucket") //参数为桶的名字,需要小写,可包含数字
                        .build());
      System.out.println(exists);
    }

}

如果你没有建立过名为mybucket的桶,则输出结果为false。这里注意桶名字英文要小写,.bucket("mybucket")内部有正则表达式进行了判断,不符合规则会报错


创建一个桶

makeBucket(): 创建一个新的存储桶

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;

    // makeBucket(): 创建一个的存储桶
    @Test
    public void testMakeBucket() throws Exception {

        boolean exists = Client.bucketExists(BucketExistsArgs.builder().bucket("mybucket").build());
        
        //如果mybucket不存在则创建
        if(!exists){
            Client.makeBucket(
                    MakeBucketArgs
                            .builder()
                            .bucket("mybucket")//参数为创建的桶的名字
                            .build()
            );
        }else{
            System.out.println("名为mybucket的存储桶已经存在!");
        }

    }

}

执行前

bd3bfcad796cf49b6f20523b88400c9

执行后

023ad4088017dc9e29db4e023d83d8c


返回桶列表

listBuckets():用于列出用户有权访问的所有存储桶,返回存储桶的列表

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	// 列出所有的存储桶
    @Test
    public void testListBuckets() throws Exception {
        List<Bucket> buckets = Client.listBuckets();
        buckets.forEach(bucket -> System.out.println(bucket.name()));
    }
	
}

打印结果:

mybucket

删除一个桶

removeBucket():用于删除一个已存在的桶,删除失败会抛出异常

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	// 删除一个存储桶
    @Test
    public void testRemoveBucket() throws Exception {
        
        //指定删除名为mybucket的桶
        Client.removeBucket(RemoveBucketArgs.builder().bucket("mybucket").build());
        
        List<Bucket> buckets = Client.listBuckets();
        //因为目前只有一个桶mybucket,所以idea控制台无输出
        buckets.forEach(bucket -> System.out.println(bucket.name()));
    }
	
}

管理页面执行删除前:

qwerrrrr

执行后:

057d2b44e9173760f7d82e3aa3c35f4



针对文件的操作

文件需要上传到桶中,文件在minio中即为Object,也就是对象

上传文件到桶中(本地文件上传)

uploadObject():直接选择上传文件到桶

// 向桶中上传文件
@Test
public void testPutObject() throws Exception {


        ObjectWriteResponse mybucket = Client.uploadObject(UploadObjectArgs.builder()
                .bucket("mybucket")
                .object("test002.png")
                .filename("C:\\home\\minio\\test001.png")
                .build()
        );
        
        System.out.println(mybucket);
}

控制台输出结果:

io.minio.ObjectWriteResponse@1abebef3

查看管理界面:

Buckets中:

37b2c968cdc2c0faafe9ba647949624

Object Browser中:

1ec5a05abcbc48f69eca897163c8978

点击Object Browser中的mybucket:

24b9777777asdf


上传文件到桶中(基于io流上传)

putObject()

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	// 向桶中上传文件
    @Test
    public void testPutObject() throws Exception {
        File file = new File("C:\\home\\minio\\test001.png");
        Client.putObject(
                PutObjectArgs.builder()
                        .bucket("mybucket") //将文件上传到哪个桶
                        .object("test001.png") //上传到桶后该文件的名字
                        .stream(new FileInputStream(file),file.length(),-1) //构建一个流用于上传文件
                        .build()
        );
    }
	
}

关于上面的stream方法

stream(InputStream stream, long objectSize, long partSize) 方法的主要目的是设置要上传的数据流,以及处理上传时的块大小和对象的总大小。这个方法主要用于大文件的分块上传,如在 AWS S3 或 Minio 中上传文件时使用的多部分上传模式。

参数解释:

  1. InputStream stream:要上传的输入流,通常是文件、网络流或其他形式的数据流。

    • 输入流可以是任意类型,但代码会使用 BufferedInputStream 包装它以提高效率。
  2. long objectSize:上传对象的总大小。

    • 如果对象大小未知(如无法提前知道文件大小),可以传递 -1,表示未知大小。
    • 如果知道对象的大小,可以指定具体大小,这有助于优化上传。
  • 上传文件的最大大小不能超过5TB
  1. long partSize:分块上传时,每一部分的大小。
    • 如果不希望手动指定分块大小,可以传递 -1,自动根据对象大小选择合适的块大小。
    • 如果你知道需要特定大小的块上传(为了控制内存使用或上传效率),可以指定该大小。
    • 如果 partSize 大于 objectSize,那么直接将 objectSize 作为 partSize
    • 合规的 partSize 大小应该设置在5M5G之间

源码:


    /**
     * Sets stream to upload. Two ways to provide object/part sizes.
     *
     * <ul>
     *   <li>If object size is unknown, pass -1 to objectSize and pass valid partSize.
     *   <li>If object size is known, pass -1 to partSize for auto detect; else pass valid partSize
     *       to control memory usage and no. of parts in upload.
     *   <li>If partSize is greater than objectSize, objectSize is used as partSize.
     * </ul>
     *
     * <p>A valid part size is between 5MiB to 5GiB (both limits inclusive).
     */
     
    public Builder stream(InputStream stream, long objectSize, long partSize) {
      validateNotNull(stream, "stream");

      long[] partinfo = getPartInfo(objectSize, partSize);
      long pSize = partinfo[0];
      int pCount = (int) partinfo[1];

      final BufferedInputStream bis =
          (stream instanceof BufferedInputStream)
              ? (BufferedInputStream) stream
              : new BufferedInputStream(stream);
      return setStream(bis, objectSize, pSize, pCount);
    }

执行方法结果(执行成功后会由延迟,可稍后查看)

Buckets页签中:

4de8ee9d2972300d8b849ebde0e8921

Object Browser页签中,点击mybucket

effca42a114bd626859db8258044fb5



Controller上传文件到minio

Controller代码,使用基于流的方式上传,接收前端的文件并从后端传到minio中

在项目中添加如下Controller

import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;


@RequestMapping("upload")
@RestController
public class MinioController {

    @Autowired
    private MinioClient Client;

    @PostMapping("test")
    public String uploadFile(@RequestPart("file") MultipartFile file) {

        ObjectWriteResponse mybucket = null;
		
        //try-catch-resource方式,可以自动关闭流
        try (InputStream  inputStream = file.getInputStream()) {
            mybucket = Client.putObject(
                    PutObjectArgs.builder()
                            .bucket("mybucket") //将文件上传到哪个桶
                            .object(file.getOriginalFilename()) //上传到桶后该文件的名字
                            .stream(inputStream, file.getSize(), -1) //构建一个流用于上传文件
                            .build()
            );
        }catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(mybucket);
        return mybucket.toString();
    }

}

postman测试

f6a17f078eb3d2f68ea7cf372b85073

注意测试时的类型是表单,一般都是自动带出不需要改动

06fd8d971872752046cdddfecab1975

测试结果,查看minio管理页面

5451b2f5c452770200394549dddc050



检查某文件的状态

statObject():检查某个桶中的某个文件的状态,也可以用来检测其是否存在

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	@Test
    public void testStatObject() throws Exception {
        StatObjectResponse mybucket =
                Client.statObject(StatObjectArgs.builder()
                        .bucket("mybucket")
                        .object("test002.png")
                        .build()
                );
        System.out.println(mybucket);
    }
	
}

输出结果:

ObjectStat{bucket=mybucket, object=test002.png, last-modified=2024-09-19T08:16:55Z, size=716272}

如果文件不存在,会报错:

error occurred
ErrorResponse(code = NoSuchKey, message = Object does not exist
, bucketName = mybucket, objectName = test008.png, resource = /mybucket/test008.png, requestId = 17F69873D6323309, hostId = dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8)
request={method=HEAD, url=http://192.168.137.200:9000/mybucket/test008.png, headers=Host: 192.168.137.200:9000
Accept-Encoding: identity
User-Agent: MinIO (Windows 10; amd64) minio-java/8.5.12
Content-MD5: 1B2M2Y8AsgTpgAmY7PhCfg==
x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date: 20240919T083850Z
Authorization: ██
}
response={code=404, headers=Accept-Ranges: bytes
Content-Length: 0
Server: MinIO
Strict-Transport-Security: max-age=31536000; includeSubDomains
Vary: Origin
Vary: Accept-Encoding
X-Amz-Id-2: dd9025bab4ad464b049177c95eb6ebf374d3b3fd1af9251148b658df7ac2e3e8
X-Amz-Request-Id: 17F69873D6323309
X-Content-Type-Options: nosniff
X-Minio-Error-Code: NoSuchKey
X-Minio-Error-Desc: "The specified key does not exist."
X-Ratelimit-Limit: 1632
X-Ratelimit-Remaining: 1632
X-Xss-Protection: 1; mode=block
Date: Thu, 19 Sep 2024 08:38:50 GMT
}

	at io.minio.S3Base$1.onResponse(S3Base.java:775)
	at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)


Process finished with exit code -1


生成文件访问的URL

getPresignedObjectUrl():用于生成一个对象(文件)的签名URL,以便于使用http地址来直接访问该文件

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	// 返回某个桶中某个文件的http访问地址,地址中带有签名字符串
    @Test
    public void testPresignedObjectUrl() throws Exception {
        String url = Client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .bucket("mybucket")
                .object("test002.png")
                //.expiry(3, TimeUnit.MINUTES) //指定有效期为3分钟,地址生成3分钟后即失效无法在访问文件
                .method(Method.GET) //设置访问文件url的请求方式为get
                .build()
        );
        System.out.println(url);
    }
	
}

输出结果:

http://192.168.137.200:9000/mybucket/test002.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20240919%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240919T085803Z&X-Amz-Expires=180&X-Amz-SignedHeaders=host&X-Amz-Signature=b3d2d9fa782739e698b46b8a8193a60a49ac8741da472c118061b735c9b887d1

访问签名地址

浏览器访问,可以直接预览该图片:

767b041a405b5cf15d9a111e692b78f

如果不加签名串,直接访问地址

http://192.168.137.200:9000/mybucket/test002.png

则会变为如下页面:

cb85107a6883469a110fecbce1794cd

如果想要不带签名串访问,需要做其他配置

第一种,需要在管理界面修改桶的访问策略

首先点击桶

f752e3736a39449e21b8d779078e53d

点击后进入如下界面,修改红框处的访问策略:

77dd2cc2d4f84a956a83754a2a972dd

将访问策略由private改为public,然后点击set保存:

557a42665ab538542993671aa32b3c2

再次使用

http://192.168.137.200:9000/mybucket/test002.png

进行访问:

7cbd47d948f1e21c8e425f1ebf895de

改变访问策略为公有后可以不带签名字符串直接访问,但是此种做法相当于谁都可以访问桶中的文件,并不安全。


第二种,Api方式,使用MinioClientsetBucketPolicy()方法

创建桶mybucket01,并为其指定文件访问策略:

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	@Test
    public void testBucketPolicy() throws Exception {

        boolean exists = Client.bucketExists(BucketExistsArgs.builder().bucket("mybucket01").build());
        if(!exists){
            Client.makeBucket(
                    MakeBucketArgs
                            .builder()
                            .bucket("mybucket01")//参数为创建的桶的名字
                            .build()
            );
        }else{
            System.out.println("名为mybucket01的存储桶已经存在!");
        }
		
        //策略字符串
        String policyJson = "{\n" +
                "  \"Version\": \"2012-10-17\",\n" +
                "  \"Statement\": [\n" +
                "    {\n" +
                "      \"Effect\": \"Allow\",\n" +
                "      \"Principal\": {\n" +
                "        \"AWS\": [\"*\"]\n" +
                "      },\n" +
                "      \"Action\": [\"s3:GetObject\"],\n" +
                "      \"Resource\": [\"arn:aws:s3:::mybucket01/*\"]\n" +
                "    }\n" +
                "  ]\n" +
                "}\n";
        //为上面创建的桶设置文件访问策略,访问策略为public,即公开读取
        Client.setBucketPolicy(
                SetBucketPolicyArgs.builder()
                        .bucket("mybucket01")
                        .config(policyJson)
                        .build())
        ;

    }
	
}

上面的json串解释:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": ["*"]
      },
      "Action": ["s3:GetObject"],
      "Resource": ["arn:aws:s3:::mybucket01/*"]
    }
  ]
}
  • Version:指定策略的版本。
  • Effect:设为 Allow,表示允许操作。
  • Principal"*" 表示允许任何用户(即公开访问)。
  • Actions3:GetObject 允许对象的读取操作。
  • Resource:指定桶中所有对象的 ARN(arn:aws:s3:::mybucket01/*),最后的冒号后面是桶的名字。

运行成功后访问管理页面:

43f449518854091915dd731f1628b4c

进入新建的桶mybucket01中,发现策略为custom自定义策略,虽然为自定义策略,但是根据config的参数,桶中文件是公开读的

e52108b6638bc4d48cbd59a84b0ef6a

执行上传代码进行测试:

// 向桶中上传文件
@Test
public void testPutObject() throws Exception {

        ObjectWriteResponse mybucket = Client.uploadObject(UploadObjectArgs.builder()
                .bucket("mybucket01")
                .object("test001.png")
                .filename("C:\\home\\minio\\test001.png")
                .build()
        );

        System.out.println(mybucket);
}

直接通过ip:port/桶名/文件名来访问:

http://192.168.137.200:9000/mybucket01/test001.png

3622b6dd5eb856dbb513165a1aba001

设置成功。

最后,还可以通过手写json串的方式来实现自己想要的任何文件访问策略

2815270de4d0d2cfbd8b538f7b41bcd

在json串的Statement内编写策略,最后set保存即可:

ad0eda452d457b2e14ece7637ce8690



从指定的桶中下载文件

getObject():用于从指定的存储桶中下载文件

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
    @Test
    public void testGetObject() throws Exception {
        
        GetObjectResponse mybucket01 = Client.getObject(GetObjectArgs.builder()
                .bucket("mybucket01")
                .object("test001.png")
                .build());

        // 文件保存路径
        String filePath = "C:\\home\\minio\\test\\test001.png";

        // 将文件内容从流中读取并写入文件
        try (InputStream inputStream = mybucket01;  // GetObjectResponse 是一个流,可以直接使用
             OutputStream outputStream = new FileOutputStream(filePath)) {

            byte[] buffer = new byte[8192];  // 每次读取8KB
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
	
}

执行结果

会将mybucket01桶中的test001.png下载到C:\home\minio\test文件夹中:

03aef68788ad10b9f880bda5aa3c26a

05621613be8bbf5b46becf4b4b9f9c8


列出桶中所有文件

listObjects():用于列出指定存储桶中的所有对象(文件)

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
    @Test
    public void testListObjects() {

        //获取mybucket01桶中的所有对象(文件)
        Iterable<Result<Item>> results = Client.listObjects(ListObjectsArgs.builder()
                .bucket("mybucket01")
                .build());

        //循环输出文件名
        results.forEach(r -> {
            try {
                Item item = r.get();
                System.out.println(item.objectName());
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

    }
	
}

输出结果:

test001.png

删除指定桶中的文件

removeObject():用于删除指定存储桶中的对象,需要指定存储桶名称和对象键。如果抛出异常则代表删除失败

@SpringBootTest
public class MinioTestDemo {

    @Autowired
    private MinioClient Client;
    
	// 删除mybucket01桶中的test001.png文件
    @Test
    public void testRemoveObject() throws  Exception {
        //无返回值方法,如果异常则删除失败
        Client.removeObject(RemoveObjectArgs.builder().bucket("mybucket01").object("test001.png").build());
    }
	
}

执行前

22deaceaa7747b0c67062c888f400c2

执行后

12a98073644ac344017fbed1deedd29



纠删码模式单机部署

纠删码介绍

  • 纠删码(Erasure Code)简称EC,是一种数据保护方法,也是一种算法;
  • MinlO对纠删码模式的算法进行了实现,采用Reed-Solomon code(简称RScode)纠错码将对象拆分成N/2数据块和N/2奇偶校验块,Reed Solomon利用范德蒙矩阵(Vandermonde matrix)、柯西矩阵(Cauchy matrix)的特性来实现;
  • 即将数据拆分为多个数据块和多个校验块,分散存储在不同的磁盘上,即使在部分磁盘损坏或丢失的情况下,也可以通过剩余的数据块和校验块恢复出原始数据;
  • 举个例子,现在有12块磁盘,一个对象数据会被分成6个数据块、6个奇偶校验块,你可以损坏或丢失任意6块磁盘(不管其是存放的数据块还是奇偶校验块),你仍可以从剩下的磁盘中恢复数据;

单机多磁盘部署准备

纠删码模式 单机多磁盘部署前需要添加磁盘,这里以虚拟机为例演示,按如下步骤执行:

  1. 执行命令:lsblk

    lsblk是Linux中的一个命令,用于列出所有可用的块设备(数据存储设备,如硬盘、闪存驱动器)的信息,如设备名称、大小、挂载点等;

    [root@Centos7 minio]# lsblk
    NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
    sda               8:0    0   50G  0 disk 
    ├─sda1            8:1    0    1G  0 part /boot
    ├─sda2            8:2    0   19G  0 part 
    │ ├─centos-root 253:0    0   41G  0 lvm  /
    │ └─centos-swap 253:1    0    2G  0 lvm  [SWAP]
    └─sda3            8:3    0   30G  0 part 
      └─centos-root 253:0    0   41G  0 lvm  /
    sr0              11:0    1  4.4G  0 rom  /run/media/root/CentOS 7 x86_64
    

    sda即为现有磁盘,大小为50GB

  2. 添加一块磁盘:

    关闭虚拟机,右键设置,添加磁盘:

    0cc8b34132f325c6803f81f164c4263

    选中硬盘下一步后选择硬盘类型为推荐的SCSI即可,再下一步选创建新虚拟磁盘,继续下一步出现如下磁盘分配页面,分配自定义大小,然后下一步:

    736e8fb46bbba59a5baca22673b2313

    出现如下页面点击完成即可:

    a62d24c97a81f6be0f49bdfc45ec199

    最后虚拟机信息如下,然后重新开机:

    4a60dc4044588d5fe228412c24c45e1

    重新开机后再次执行lsblk,发现多了一个1GB的sdb磁盘:

    [root@Centos7 ~]# lsblk
    NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
    sda               8:0    0   50G  0 disk 
    ├─sda1            8:1    0    1G  0 part /boot
    ├─sda2            8:2    0   19G  0 part 
    │ ├─centos-root 253:0    0   41G  0 lvm  /
    │ └─centos-swap 253:1    0    2G  0 lvm  [SWAP]
    └─sda3            8:3    0   30G  0 part 
      └─centos-root 253:0    0   41G  0 lvm  /
    sdb               8:16   0    1G  0 disk 
    sr0              11:0    1  4.4G  0 rom  /run/media/root/CentOS 7 x86_64
    
  3. 将添加的磁盘格式化为xfs格式,以进行挂载: 执行命令mkfs.xfs /dev/sdb

    [root@Centos7 ~]# mkfs.xfs /dev/sdb
    meta-data=/dev/sdb               isize=512    agcount=4, agsize=65536 blks
             =                       sectsz=512   attr=2, projid32bit=1
             =                       crc=1        finobt=0, sparse=0
    data     =                       bsize=4096   blocks=262144, imaxpct=25
             =                       sunit=0      swidth=0 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
    log      =internal log           bsize=4096   blocks=2560, version=2
             =                       sectsz=512   sunit=0 blks, lazy-count=1
    realtime =none 
    
  4. 将磁盘挂载到minio的存储目录: 执行命令mount /dev/sdb /opt/minio/data,然后再lsblk查看:

    如果提示挂载点 /opt/minio/data 不存在,则需要在根目录opt文件夹中去建立minio/data

    [root@Centos7 ~]# mount /dev/sdb /opt/minio/data
    [root@Centos7 ~]# lsblk
    NAME            MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
    sda               8:0    0   50G  0 disk 
    ├─sda1            8:1    0    1G  0 part /boot
    ├─sda2            8:2    0   19G  0 part 
    │ ├─centos-root 253:0    0   41G  0 lvm  /
    │ └─centos-swap 253:1    0    2G  0 lvm  [SWAP]
    └─sda3            8:3    0   30G  0 part 
      └─centos-root 253:0    0   41G  0 lvm  /
    sdb               8:16   0    1G  0 disk /opt/minio/data
    sr0              11:0    1  4.4G  0 rom  /run/media/root/CentOS 7 x86_64
    

    sdb后出现 /opt/minio/data 挂载点


纠删码模式启动

使用纠删码模式进行后台启动,命令:

MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password nohup ./minio server  --console-address ":9001" --address ":9000" /opt/minio/data/data{1...12} > /opt/minio/data/minio.log 2>&1 &
  • nohup:这是一个Unix命令,用于运行另一个命令在后台,并且忽略挂起(HUP)信号,也就是即使你退出了终端或关闭了会话,该命令也会继续运行;
  • /opt/minio/data/minio.log:这部分是将标准输出(stdout)重定向到 /opt/minio/data/minio.log 文件,这意味着MinIO 服务器的所有正常输出(如启动信息、状态更新等)都会被写入到这个日志文件中;
  • 2>&1:这部分是将标准错误输出(stderr)重定向到标准输出(stdout),即输出到 /opt/minio/data/minio.log 文件,这样,无论是标准输出还是错误输出,都会被写入到同一个日志文件中;
  • &:这个符号是在命令的末尾,用于将命令放到后台执行,也就是即使你启动了 MinIO 服务器,你的终端或 shell 会话也不会被阻塞,你可以继续执行其他命令;

进入minio所在目录,执行命令

[root@Centos7 ~]# cd /home/minio
[root@Centos7 minio]# MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password nohup ./minio server  --console-address ":9001" --address ":9000" /opt/minio/data/data{1...12} > /opt/minio/data/minio.log 2>&1 &
[1] 6958
[root@Centos7 minio]# ps -ef|grep minio
root       6958   3011  8 14:41 pts/0    00:00:00 ./minio server --console-address :9001 --address :9000 /opt/minio/data/data{1...12}
root       6985   3011  0 14:41 pts/0    00:00:00 grep --color=auto minio

访问管理页面

虚拟机ip加9001端口访问:

00968f02655cc53ce9c01299adb2a72

进入/opt/minio/data目录查看,多出了12个minio存储的目录以及一个日志文件

[root@Centos7 minio]# cd /opt/minio/data
[root@Centos7 data]# ll
总用量 4
drwxr-xr-x. 3 root root  24 921 14:41 data1
drwxr-xr-x. 3 root root  24 921 14:41 data10
drwxr-xr-x. 3 root root  24 921 14:41 data11
drwxr-xr-x. 3 root root  24 921 14:41 data12
drwxr-xr-x. 3 root root  24 921 14:41 data2
drwxr-xr-x. 3 root root  24 921 14:41 data3
drwxr-xr-x. 3 root root  24 921 14:41 data4
drwxr-xr-x. 3 root root  24 921 14:41 data5
drwxr-xr-x. 3 root root  24 921 14:41 data6
drwxr-xr-x. 3 root root  24 921 14:41 data7
drwxr-xr-x. 3 root root  24 921 14:41 data8
drwxr-xr-x. 3 root root  24 921 14:41 data9
-rw-r--r--. 1 root root 789 921 14:41 minio.log

此时,12个存储目录中都是空的,从管理控制台上传文件:

Buckets页签下创建桶:

ddcc824739261a96992207b96c56e26

输入桶名字后点击创建,注意名字要符合规则:

b2538af06c66f26ec0a7f87e91d8912

创建完成后如下:

061598489cfdca474e345db7d2bda8b

Object Browser页签下点击上传文件:

84af4bb80b7e6747fd0231351c80652

上传一个图片,如下:

11f1bf03a6b60e956590af3b083d3cc

完成后可以发现每一个存储目录下都会出现此图片的元数据文件:

cfbdff463f4f7fb205fea40be80d208
至此完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2200842.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(Linux驱动学习 - 9).设备树下platform的LED驱动

一.platform相关结构体与函数 1.匹配列表 - struct of_device_id struct of_device_id {char name[32];char type[32];/* compatible 很重要&#xff0c;需要与设备树节点的 compatible 属性一致&#xff0c;才能匹配 */char compatible[128]; const void *data; }; …

dfs 判重Sequence one——hdu 2610

目录 前言 搜索算法判重 map判重 set判重 Sequence one 问题描述 输入 输出 数据范围 样例 问题分析 重构dfs参数 递减&#xff0c;不重复 去重的优化 最终代码 前言 搜索算法判重 搜索算法判重有很多种方法&#xff0c;常见的有两种&#xff0c;map判重和set判重…

模运算和快速幂

文章目录 模运算快速幂 模运算 模运算是大数运算中的常用操作。如果一个数太大&#xff0c;无法直接输出&#xff0c;或者不需要直接输出&#xff0c;则可以对它取模&#xff0c;缩小数值再输出。取模可以防止溢出&#xff0c;这是常见的操作。 取模运算一般要求a和m的符号一…

VCI_VBDSP使用教程-服务站

VCI_VBDSP使用教程-服务站 VBDSP软件压缩包请点击下载&#xff1a;(备注&#xff1a;将VBDSP软件压缩包做一个下载连接&#xff0c;放到此处) 教程视频&#xff1a;https://www.bilibili.com/video/BV19eHpeeEiz/?spm_id_from333.999.0.0&vd_source224b4434f72960113bc97…

数组的定义与使用(二)

2. 数组是引用类型 2.1初识JVM的内存分布 内存是一段连续的存储空间&#xff0c;主要用来存储程序运行时数据的。比如&#xff1a; 程序运行时代码需要加载到内存程序运行产生的中间数据要存放在内存程序中的常量也要保存有些数据可能需要长时间储存&#xff0c;有些数据当方…

PCL 平面点云边界特征提取(alpha shapes)

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 点云边界提取 2.1.2 可视化点云与边界 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&a…

07:(寄存器开发)串口通信

串口通信 1、串口简介2、串口通讯协议3、硬件外设4、发送数据5、使用轮询的方式接收数据&#xff08;USART1&#xff09;6、使用中断的方式接收数据7、串口进行printf重定向 1、串口简介 串口通讯&#xff08;Serial Communication&#xff09;是一种设备间非常常用的串行通讯方…

后端增删改查的基本应用——一个简单的货物管理系统

最终效果&#xff0c;如图所示&#xff1a; 如果想要进行修改操作&#xff0c;可点击某栏修改选项&#xff0c;会在本表格下方弹出修改的具体操作界面&#xff08;点击前隐藏&#xff09;&#xff0c;并且目前的信息可复现在修改框内。 本篇文章通过该项目将后端和前端结合起来…

java内存控制

Java 内存控制是一个相对复杂但至关重要的主题&#xff0c;它涉及到如何高效地管理Java应用程序中的内存资源。在Java中&#xff0c;内存管理主要由Java虚拟机&#xff08;JVM&#xff09;负责&#xff0c;包括内存的分配和回收。尽管如此&#xff0c;作为开发者&#xff0c;我…

2025年5月高项,从0备考信息系统项目管理师 | 备考经验全攻略分享

在逐步摸索备考信息系统项目管理师的过程中&#xff0c;我总结了很多关于班课资料和学习经验&#xff0c;现在与大家分享。&#xff08;全文约3k字&#xff0c;阅读用时约5min&#xff09; 这篇分享帖不仅告诉你关于备考信息系统项目管理师实用的班课资料&#xff0c;还有学习…

Win11 23H2 10月正式版:22631.4317 镜像免费下载!

今日&#xff0c;系统之家小编给您带来2024年10月最新更新的Windows11 23H2正式版系统下载&#xff0c;该版本系统基于微软官方最新Windows11 23H2 22631.4317专业版展开离线制作&#xff0c;没有病毒残留&#xff0c;且能完美支持新老机型&#xff0c;安装后&#xff0c;系统版…

【概率论】泊松分布

泊松分布 若 &#xff0c;则 归一性 例子 泊松分布多出现在当X表示一定时间或一定空间内出现的事件的个数这种场合&#xff0c;如在一定时间内某交通路口所发生的事故的个数。 将泊松分布假设为二项分布 假设条件: &#xff08;1&#xff09;泊松分布一般为一段时间或一…

★ 算法OJ题 ★ 二分查找算法

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;塞尔达将和大家一起做几道二分查找算法算法题 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 算法专栏&#xff1a;★ 优选算法100天 ★_椎名澄嵐的博客-CSDN博客…

STM32 SPI串行总线

目录 STM32的SPI通信原理 SPI串行总线概述 SPI串行总线互连方式 STM32F1 SPI串行总线的工作原理 SPI串行总线的特征 SPI串行总线的内部结构 SPI串行总线时钟信号的相位和极性 STM32的SPI接口配置 STM32的SPI接口数据发送与接收过程 SPI的HAL 驱动函数 STM32的SPI通信…

靶标弹孔检测系统源码分享

靶标弹孔检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

apt update报错:ModuleNotFoundError: No module named ‘apt_pkg‘(可能是默认python版本被改坏了)

文章目录 错误信息分析1. 确保 apt_pkg 模块已安装2. 检查 Python 版本3. 重新配置 Python4. 修复损坏的依赖5. 检查环境变量 尝试 错误信息 (base) rootkyai:/ky/tml/ky_ai_get_server_info# apt update 获取:1 file:/var/cuda-repo-cross-aarch64-ubuntu2004-11-4-local InR…

【Python】如何让SQL Server像MySQL一样拥有慢查询日志(Slow Query Log慢日志)

如何让SQL Server像MySQL一样拥有慢查询日志&#xff08;Slow Query Log慢日志&#xff09; SQL Server一直以来被人诟病的一个问题是缺少了像MySQL的慢日志功能&#xff0c;程序员和运维无法知道数据库过去历史的慢查询语句。 因为SQLServer默认是不捕获过去历史的长时间阻塞…

inBuilder低代码平台新特性推荐-第二十五期

今天来给大家带来的是inBuilder低代码平台社区版中的特性推荐系列第二十五期——选人组件扩展&#xff01; 一、概述 inBuilder低代码平台社区版的开发过程中&#xff0c;选人组件支持tab页中增加扩展页面&#xff0c;由二开人员根据业务场景实现自定义取数接口和页面展示形式…

【笔记】济南,天命人,春秋

孤独而高傲的济南人 浩克山东知天命热爱的sensei 浩克山东 哦哦&#xff0c;最高的大葱也是济南的了&#xff0c;这大葱&#xff0c;比一般人要高呢&#xff0c;尽管济南的朋友们也都个子不矮。。能想像的到两米高的米库。。。。 然而在这块地界&#xff0c;遇到个人&#xf…

基于STM32的简易交通灯proteus仿真设计(仿真+程序+设计报告+讲解视频)

基于STM32的简易交通灯proteus仿真设计(仿真程序设计报告讲解视频&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;C0091 **1.**主要功能 功能说明&#xff1a; 以STM32单片机和数码管、LED灯设计简易交通…