Minio 所需要的时间同步问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Minio 所需要的时间同步问题相关的知识,希望对你有一定的参考价值。

参考技术A 在执行客户端的服务器访问时,报错:

开启esxi主机的ntpd服务后,设置了ntp服务器为 0.pool.ntp.org和1.pool.ntp.org,2.pool.ntp.org 的IP地址,肉眼上看本地时间和服务器时间时相同的,但依然报错

设置时区

查看时区列表

centos 8 不再支持ntp,因此,yum install ntp 无法安装,但是默认使用 chrony
四个 minio server 重启了该服务后,时间同步成功,可以在主机访问 minio 服务了

时区在时间同步问题上,没有影响

局域网内找不到互联网的ntp服务器
思路:将windows主机作为ntp服务器,用EXSI同步w32time时间服务,虚拟机设置同步客户机时间与主机时间,同步ESXI的系统时间,

如果没有自动同步,需要root权限执行以下步骤

你可需要的对象存储中间件《Minio使用》

最近的项目中因为需要做一些上传和下载的工作,所以选择了minio。当然这也是公司的选择,废话不多说,今天主要是记录下经验。

1、minio相关信息

1.1 官方信息

中文网站:MinIO | 高性能,对Kubernetes友好的对象存储

你懂得,去掉cn 就是官方网站。在官方网站上有你要的信息。不打开看看吗?看起来了不起的样子

MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。

MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。

MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。

在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品

1.2 MinIO优势

1、数据安全

分布式存储,保证数据安全

2、高可用

分布式多副本机制,可以保证服务的高可用,即使挂掉几个也能保证服务

3、一致性

1.3 应用场景

互联网非结构化数据的存储需求

  • 电商网站:海量商品图片
  • 视频网站:海量视频文件
  • 网盘:海量文件

2、部署

懒省事,直接选择docker部署,看下脚本吧,没啥问题。

docker run  -p 9000:9000 --net=host \\
--name minio1 \\
       -d \\
-e MINIO_ACCESS_KEY=minio \\
-e MINIO_SECRET_KEY=minio@123 \\
-v /home/docker/minio/data:/data \\
-v /home/docker/minio/config:/root/.minio \\
 minio/minio server /data 

启动起来登录进控制台

管理地址:http://172.26.1.152:9000/,用户名和地址在上面的脚本里

3、Springboo继承Minio

1、添加依赖

这里在线上直接找了一个,你可以在repo里查找最新的 

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

2、配置文件

application.yml,这里直接创建了一个配置,你可以根据自己的需求定义格式

minio:
  endpoint: http://172.26.1.152:9000  # endpoint
  accessKey: minio  #用户名
  secretKey: minio@123 # 密码
  bucketName: apply # bucketName

3、读取配置文件

这里使用了lombok,如果你没使用的话,可以去除data注解,然后创建一些get/set方法。

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig 
    private String endpoint;
    private String accessKey;
    private String secretKey;
    @Bean
    public MinioClient minioClient()  
        MinioClient minioClient = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
        return minioClient;
    

4、创建一个工具类

这里借鉴了一些线上的文档,然后加了一些修改,可以直接拷贝到项目中使用。

package com.xin.miniodemo.config;

import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * minio 工具类
 */
@Component
@Slf4j
public class MinioUtil 
    @Autowired
    private MinioClient minioClient;

    /**
     * 查看存储bucket是否存在
     *
     * @return boolean
     */
    public boolean bucketExists(String bucketName) 
        boolean found = false;
        try 
            BucketExistsArgs args = BucketExistsArgs.builder().bucket(bucketName)
                    .build();
            found = minioClient.bucketExists(args);
         catch (Exception e) 
            log.error("bucketExists  ", e);
        
        return found;
    

    /**
     * 创建存储bucket
     *
     * @return Boolean
     */
    public boolean makeBucket(String bucketName) 
        try 
            MakeBucketArgs makeArgs = MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build();
            minioClient.makeBucket(makeArgs);
         catch (Exception e) 
            log.error("makeBucket  ", e);
            return false;
        
        return true;
    

    /**
     * 删除存储bucket
     *
     * @return Boolean
     */
    public boolean removeBucket(String bucketName) 
        try 
            RemoveBucketArgs removeArgs = RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build();
            minioClient.removeBucket(removeArgs);
         catch (Exception e) 
            log.error("removeBucket  ", e);
            return false;
        
        return true;
    

    /**
     * 获取全部bucket
     */
    public List<Bucket> getAllBuckets() 
        try 
            return minioClient.listBuckets();
         catch (Exception e) 
            log.error("getAllBuckets  ", e);
        
        return null;
    

    /**
     * 文件上传
     *
     * @param bucketName
     * @param fileName   上传文件的路径和名字
     * @param file
     * @return
     */
    public boolean upload(String bucketName, String fileName, MultipartFile file) 
        try 
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
         catch (Exception e) 
            log.error("upload  ", e);
            return false;
        
        return true;
    


    /**
     * 文件下载
     *
     * @param fileName 文件的路径和名字
     * @return Boolean
     */
    public void download(String fileName, String saveName, String bucketName) 
        DownloadObjectArgs build = DownloadObjectArgs.builder()
                .bucket(bucketName)
                .filename(saveName)
                .object(fileName)
                .build();
        try 
            minioClient.downloadObject(build);
         catch (Exception e) 
            throw new RuntimeException(e);
        
    

    /**
     * web下载文件
     *
     * @param fileName   文件的路径和名字
     * @param bucketName
     * @param resp
     */
    public void webDownload(String fileName, String bucketName, HttpServletResponse resp) 
        GetObjectArgs objectArgs = GetObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .build();
        try (GetObjectResponse response = minioClient.getObject(objectArgs)) 
            byte[] buf = new byte[1024];
            int len;
            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) 
                while ((len = response.read(buf)) != -1) 
                    os.write(buf, 0, len);
                
                os.flush();
                byte[] bytes = os.toByteArray();
                resp.setCharacterEncoding("utf-8");
                //设置强制下载不打开
                //res.setContentType("application/force-download");
                resp.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
                try (ServletOutputStream stream = resp.getOutputStream()) 
                    stream.write(bytes);
                    stream.flush();
                
            
         catch (Exception e) 
            log.error("webDownload  ", e);
        
    

    /**
     * 查看文件对象
     *
     * @return 存储bucket内文件对象信息
     */
    public List<Item> listObjects(String bucketName) 
        ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
                .bucket(bucketName)
                .build();
        Iterable<Result<Item>> results = minioClient.listObjects(listObjectsArgs);
        List<Item> itemList = new ArrayList<>();
        try 
            for (Result<Item> result : results) 
                itemList.add(result.get());
            
         catch (Exception e) 
            log.error("listObjects  ", e);
            return null;
        
        return itemList;
    

    /**
     * 删除
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    public boolean removeOne(String fileName, String bucketName) 
        try 
            RemoveObjectArgs removeArgs = RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build();
            minioClient.removeObject(removeArgs);
         catch (Exception e) 
            log.error("remove  ", e);
            return false;
        
        return true;
    

    /**
     * 批量删除文件对象
     *
     * @param objects 对象名称集合
     */
    public Iterable<Result<DeleteError>> removeObjects(List<String> objects, String bucketName) 
        List<DeleteObject> dos = objects.stream().map(DeleteObject::new).collect(Collectors.toList());
        RemoveObjectsArgs build = RemoveObjectsArgs.builder()
                .bucket(bucketName)
                .objects(dos)
                .build();
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(build);
        return results;
    



5、测试代码,

这里直接创建了一个controller测试

import com.xin.miniodemo.config.MinioUtil;
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.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;

@RestController
@RequestMapping
public class TestController 
    @Autowired
    private MinioUtil minioUtil;
    @PostMapping("/upload")
    public String test(MultipartFile file) 
         minioUtil.upload("chongxin",file.getOriginalFilename(),file);
        return "Hello";
    
    @PostMapping("/delete")
    public String delete(String fileName) 
        String[] fileArr = fileName.split(",");
        List<String> fl = Arrays.asList(fileArr);
        minioUtil.removeObjects(fl,"chongxin");
        return "Hello";
    
    @PostMapping("/download")
    public String download(String fileName) 

        minioUtil.download(fileName,"chongxin.jpg","chongxin.jpg");
        return "Hello";
    
    @PostMapping("/webdownload")
    public String download(String fileName, HttpServletResponse response) 

        minioUtil.webDownload(fileName,"chongxin",response);
        return "Hello";
    

4、总结

在开发的过程中还是出现一些问题的,但是已经都解决了,没有及时记录问题,这个有点可惜。

撸代码的时间还是快乐的,特别是解决问题之后,很开心

你的点赞是我分享的动力,欢迎点赞评论分享

以上是关于Minio 所需要的时间同步问题的主要内容,如果未能解决你的问题,请参考以下文章

使用Rclone实现minio数据的迁移

基于Docker的Minio集群部署

NTP时间同步

将同步 qtdbus 调用转换为异步所需的设计建议

简单几步让CentOS系统时间同步

将同步代码包装成异步调用