2024年9月

经过前面章节的学习,可以说大家已经算Redis开发入门了。已经可以去到项目上磨砺了。

但是今天我还想和大家分享一章:封装自己的Redis C#库,然后打包成Nuget包。

首先要说明的是:不是要自己开发一个Redis客户端库,而是基于上篇文章中介绍的6大库,做一个简单封装,真的很简单的那种,就是包个壳子。

再来说说为什么要做这个事情。

01
、原因

1.可测试

我希望代码是以服务的方式注入到程序中,而不是静态方法的方式去调用。使用依赖注入来提供服务使得程序可测试性增强,如果做单元测试,依赖注入的服务很容易通过mock来测试,而静态方法往往很难被模拟,测试起来很不灵活;

2.解耦

对于一个系统来说会使用到各种技术来达到某种能力,实现一个功能可能会有很多种方法,我们在意的是实现这个功能,而不是你用了什么方法。回到主题,我们需要的是使用Redis来实现业务功能,而具体用那个客户端库并不重要。

再举个例子比如今天我们选择了ServiceStack.Redis库接过遇到问题我们解决不了怎么办?难道业务不做了?不可能吧!而恰巧这个时候CSRedisCore库可以解决,你会怎么选?

这时候可能会想换的成本有多大?两种库方法名不统一,功能也不一样,如果系统中到处散落Redis方法调用,这可怎么换啊。

试想如果我们封装了一层,提供了一组接口,打包成Nuget包,这个时候大家用的就是这个Nuget包,而我们只需要把Nuget包里用ServiceStack.Redis实现的方法换成用CSRedisCore实现一下,大家直接更新一下Nuget包,可能一行代码都不用改就完成了替换。

因为我们依赖的是我们自己封装的接口,而不是具体Redis客户端库,因此可以解耦轻松替换。

3.扩展

Redis的原生功能可以理解为基础功能,表明Redis有这种能力。但是我们怎么使用,怎么更好的发挥它的价值,这就是我们自己能力的体现了。

大家相过想过没有,为什么有的库商业化做的特别好,特别简单容易上手。商业化好说明提供的服务好,也就是说明它能帮你做很多事情,它在原生功能上加了很多自己的创作。

项目做多了,我们自己也会遇到一些相似的功能,如果这个时候我们想把这些相似功能封装一下,要放哪里呢?怎么给别人用?如果我们遇到一个功能现有库都没有相应能力,需要我们基于原生自己开发实现又应该在哪做呢?

这些功能积累的多了总要有个地方放吧,而这时如果我们自己封装了一层,放哪的问题是不是一下子就解决了,说不定做着做着就成了一个产品了呢。

不知道到这里,大家有没有感觉思路一下子被打开了。可能我们没写几行代码,但是这个格局一下子就打开了,而这几行代码也可能产生意想不到的收获,可能是无限可能,也可能就是你实现自己Redis客户端库的开端。

当然这也是我自己对编码,对封装的个人拙见。说这么多也是希望可以给大家一些帮助。

02
、实现

下面闲话少说进入正题,如果来封装呢?

我们先梳理一下大致思路:

1.我们需要一个接口,里面包含:原库原生能力Client、其他我们自定义功能。

2.一个入口,别人要用,总要有个入口吧。

其实要求就这么简单。

下面我们就以封装CSRedisClient为例,首先定义IRedisService接口,里面包含Client字段以及两个演示的自定义方法

using CSRedis;
namespace Redis.RedisExtension
{
    public interface IRedisService
    {
        /// <summary>
        /// RedisClient
        /// </summary>
        /// <returns></returns>
        CSRedisClient Client { get; }
        #region 自定义方法
        /// <summary>
        /// 获取指定 key 的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        T Get<T>(string key);
        /// <summary>
        /// 获取指定 key 的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> GetAsync<T>(string key);
        #endregion
    }
}

然后需要实现IRedisService,同时以CSRedisClient为构造函数入参,具体代码如下:

using CSRedis;
namespace Redis.RedisExtension
{
    public class RedisService : IRedisService
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="redisClient"></param>
        public RedisService(CSRedisClient redisClient)
        {
            Client = redisClient;
        }
        /// <summary>
        /// CSRedis
        /// </summary>
        /// <returns></returns>
        public CSRedisClient Client { get; }
        #region 自定义方法
        /// <summary>
        /// 获取指定 key 的值
        /// </summary>
        /// <returns></returns>
        public T Get<T>(string key)
        {
            return Client.Get<T>(key);
        }
        /// <summary>
        /// 获取指定 key 的值
        /// </summary>
        /// <returns></returns>
        public Task<T> GetAsync<T>(string key)
        {
            return Client.GetAsync<T>(key);
        }
        #endregion
    }
}

到这里第一个问题就解决了,对于第二个问题我们,我们可以对IServiceCollection进行扩展添加启动扩展方法AddRedisClientSetup,具体代码如下:

using CSRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Redis.RedisExtension
{
    public static class RedisSetupExtensions
    {
        /// <summary>
        /// Redis客户端启动项
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddRedisClientSetup(this IServiceCollection services)
        {
            services.AddSingleton<CSRedisClient>(serviceProvider =>
            {
                var configuration = serviceProvider.GetRequiredService<IConfiguration>();
                var setting = configuration["RedisConnectionString"];
                return new CSRedisClient(setting);
            });
            services.AddSingleton<IRedisService, RedisService>();
            return services;
        }
        /// <summary>
        /// Redis客户端启动项
        /// </summary>
        /// <param name="services"></param>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public static IServiceCollection AddRedisClientSetup(this IServiceCollection services, string connectionString)
        {
            services.AddSingleton<CSRedisClient>(serviceProvider =>
            {
                return new CSRedisClient(connectionString);
            });
            services.AddSingleton<IRedisService, RedisService>();
            return services;
        }
    }
}

为什么要提供两个重载方法,因为如果用户基于我们的约定,在配置文件中以"RedisConnectionString"命名Redis连接字符串,用户直接调用AddRedisClientSetup()方法即可完成Redis启动,但是可能因为各种原因用户没法遵守约定,因此我们也要提供一个用户可以指定Redis连接字符串方法的入口。

下面我们就用基于约定的方式,在配置文件中加入以下配置:

{
  "RedisConnectionString": "127.0.0.1:6379"
}

然后使用Client.Set方法设置key1,再用自定义方法Get
方法读取,代码如下:

public static void Run()
{
    var configuration = new ConfigurationBuilder()
        .SetBasePath(AppContext.BaseDirectory)
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .Build();
    var services = new ServiceCollection();
    services.AddSingleton<IConfiguration>(configuration);
    services.AddRedisClientSetup();
    var redisService = services.BuildServiceProvider().GetService<IRedisService>();
    var setResult = redisService.Client.Set("key1", "value1");
    Console.WriteLine($"redisService.Client.Set(\"key1\",\"value1\")执行结果:{setResult}");
    var value = redisService.Get<string>("key1");
    Console.WriteLine($"redisService.Get<string>(\"key1\")执行结果:{value}");
    redisService.Client.Del("key1");
}

执行结果如下:

是不是很简单,然后我们只需要把上面三个文件IRedisService、RedisService、RedisSetupExtensions放到单独的类库中,然后打包发布成Nuget包,就可以给大家一起用啦,今天我这边就不发布Nuget包了,后面会有相关的计划,到时候再细聊。


:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。
https://gitee.com/hugogoos/Planner

1. Performance API 的用处

Performance API
是浏览器中内置的一组工具,用于测量和记录页面加载和执行过程中的各类性能指标。它的主要用处包括:

  • 监控页面资源加载
    :跟踪页面中的资源(如 CSS、JavaScript、图片)的加载时间。
  • 分析页面加载时间
    :从导航到页面完全渲染的所有时间点。
  • 衡量用户交互性能
    :测量用户点击、输入等操作的响应时间。
  • 优化性能瓶颈
    :通过标记特定的代码片段和事件,精准定位性能瓶颈。

这些数据帮助开发者更好地理解页面表现,进而对性能进行优化和改进。

2. Performance API 常用的 API

在使用 Performance API 时,以下几个 API 是开发者最常用的工具:
getEntries()

mark()
、以及
PerformanceObserver
。这些 API 提供了从获取性能数据到观察性能事件的全面能力。

2.1 performance.getEntries()

performance.getEntries()
是 Performance API 提供的一个方法,它返回所有的性能条目(entries)。这些条目记录了从页面加载到当前时刻,各类资源的加载和交互的性能数据。性能条目包括页面加载资源(如 CSS、JS、图片等)以及自定义的事件标记。

//获取页面中所有资源的性能条目
const entries =performance.getEntries();
console.log(entries);

通过
getEntries()
,你可以获取资源加载时间、开始时间、结束时间等详细信息。这对于了解页面中每个资源的加载耗时十分有帮助。

2.2 entries 的类型

getEntries()
返回的每个性能条目对象都属于以下几种类型,开发者可以根据需要筛选和分析不同类型的数据:

  • navigation
    :与页面导航相关的条目,通常用于分析页面加载的时间点。
  • resource
    :所有通过网络请求加载的资源条目,包括 JS、CSS、图片等。
  • mark
    :开发者自定义的标记,用于记录特定事件的开始或结束。
  • measure
    :通过
    performance.measure()
    生成的条目,用于测量两个标记之间的时间间隔。

例如,使用
performance.getEntriesByType('resource')
可以只获取资源加载的性能数据:

//获取所有资源加载的性能条目
const resourceEntries = performance.getEntriesByType('resource');
console.log(resourceEntries);

通过这种方式,开发者可以轻松获取页面资源的加载时间及其详情。

2.3 performance.mark()

performance.mark()
是 Performance API 提供的一个方法,允许开发者在代码中手动创建标记。这些标记可以用于记录特定事件的发生时间,从而在分析性能时,更加精确地掌握代码中某个关键操作的时机。

//创建自定义标记
performance.mark('start-task');//执行某个任务
doSomething();//创建结束标记
performance.mark('end-task');//测量开始和结束之间的时间
performance.measure('Task Duration', 'start-task', 'end-task');

mark()
非常适合用于衡量应用程序中某段代码的执行时间,与
measure()
一起使用可以提供更加详细的性能分析。

2.4 PerformanceObserver

PerformanceObserver
是 Performance API 的一个高级特性,它可以监听性能事件的发生,并在事件触发时执行回调。这种观察模式可以帮助开发者实时监控页面中的资源加载、导航和其他性能相关的事件。

//创建 PerformanceObserver 实例,监听资源加载的事件
const observer = new PerformanceObserver((list) =>{const entries =list.getEntries();
entries.forEach(entry
=>{
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
//监听资源类型的性能条目 observer.observe({ entryTypes: ['resource'] });

通过
PerformanceObserver
,你可以监听特定类型的性能条目,如
resource

mark
,并实时分析其数据。对于监控资源加载、关键操作或用户交互时的性能表现非常有用。

总结

Performance API 是前端开发者进行性能监控的强大工具,它提供了对页面加载、资源加载以及用户交互的详细分析能力。常用的 API,如
getEntries()

mark()
、以及
PerformanceObserver
,可以帮助开发者实时获取和分析性能数据。

通过合理地使用 Performance API,你可以更好地了解页面中各类操作的性能表现,从而有效地优化 Web 应用的加载速度和用户体验。

manim
提供了
通用多边形
模块,可以绘制任意的多边形。

通用多边形模块有两种,
Polygon

Polygram

Polygon
是一个几何学术语,主要指的是由三条或三条以上的线段首尾顺次连接所组成的平面图形,


Polygram
的含义更加广泛一些,它除了可以绘制传统的多边形,还能绘制非闭合的多边形,各部分不相连的多边形等等。

对于一般的几何问题,使用
Polygon
就足够了,只有在需要表达一些图形的组合或序列时,才会用到
Polygram

manim
中关于
Polygon

Polygram
的模块主要有4个:

  1. Polygon
    :任意多边形
  2. RegularPolygon
    :任意

    多边形
  3. Polygram
    :广义的多边形
  4. RegularPolygram
    :广义的

    多边形

Polygon

Polygram
其实也可以绘制

多边形,只不过用
RegularPolygon

RegularPolygram
会更加方便。

这4个模块的继承关系如上图所示。

1. 主要参数

Polygon
的参数很简单,就是提供一系列的顶点坐标。

绘制时会依照提供的顶点顺序依次连线,最后一个点会连接第一个点,形成一个闭合的多边形。

参数名称 类型 说明
vertices Point3D 多边形的顶点列表

RegularPolygon
的参数也很简单:

参数名称 类型 说明
n int 正多边形的边数

Polygram
的参数是多组的顶点,每组有多个顶点,与之相比,
Polygon
的参数只有一组顶点。

参数名称 类型 说明
vertex_groups Point3D 多组顶点列表,如果只有一组顶点,那么图形和
Polygon
一样

RegularPolygram
的参数有:

参数名称 类型 说明
num_vertices int 顶点的个数
radius float 图形外接圆的半径
density int 跳跃多少个顶点来连接
start_angle float 第一个顶点的角度

RegularPolygon
比较简单,就是顺序连接各个顶点形成多边形,


RegularPolygram
有个
density
参数,可以控制跳跃几个顶点来连接。

设置
density=1
的话,
RegularPolygram

RegularPolygon
的图形是一样的,后面示例中详细演示。

2. 主要方法

Polygram
作为最通用的多边形,提供了3个方法。

名称 说明
get_vertex_groups 以分组的形式获取多变形的所有顶点坐标
get_vertices 获取多变形的所有顶点坐标
round_corners 调整多边形角的曲率

get_vertex_groups

get_vertices
主要区别在于:

get_vertex_groups
以分组的形式返回顶点坐标,这对于
Polygram
模块比较有用,因为
Polygram
模块的参数可以传入多组顶点;

get_vertices
则是将所有的坐标作为一个列表返回出来。

round_corners
用来调整多边形尖角的曲率。

# 创建3个广义正六边形
p1 = RegularPolygram(6)
p2 = RegularPolygram(6)
p3 = RegularPolygram(6)

# p2的尖角曲率设为0.1
p2.round_corners(radius=0.1)

# p3的尖角曲率设为0.3
p3.round_corners(radius=0.3)

其他3个模块没有什么重要的方法。

3. 使用示例

3.1. 多边形示例

多变形就是按照传入的顶点的顺序逐个连接成一个闭合图形。

# 凸多边形
points = [
    LEFT * 2.5,
    LEFT * 1.5 + UP,
    LEFT * 0.5,
    LEFT * 0.5 + DOWN * 1.5,
    LEFT * 2.5 + DOWN * 1.5,
]
Polygon(*points)

# 凹多边形
points = [
    RIGHT * 0.5 + UP,
    RIGHT * 1.5 + DOWN,
    RIGHT * 2.5 + UP,
    RIGHT * 2.5 + DOWN * 1.5,
    RIGHT * 0.5 + DOWN * 1.5,
]
Polygon(*points)

3.2. 正多边形

正多边形最简单,只要传入边的数量即可。

RegularPolygon(n=6)
RegularPolygon(n=8)
RegularPolygon(n=12)

3.3. 广义多边形

广义多边形更像是多个多边形的组合,它可以传入多个组的的顶点,然后根据每个组的顶点来构造图形。

下面的示例中,第一个图形有3个组顶点,第二个图形有2个组顶点。

group_points = [
    [[-2.5,0,0], [-1.5,1,0], [-0.5,0,0]],
    [[-2,0,0], [-2,-1.5,0]],
    [[-1,0,0], [-1,-1.5,0]],
]
Polygram(*group_points)

group_points = [
    [[0.5,0,0], [1.5,1,0], [2.5,0,0]],
    [[0.5,-1,0], [1.5,0,0], [2.5,-1,0]],
]
Polygram(*group_points)

3.4. 广义正多边形

广义正多边形可以调整顶点的连接顺序(通过属性
density
),逐个连接时,和普通正多边形是一样的。

# 正九边形,逐个连接顶点
RegularPolygram(9, density=1)

# 正九边形,隔一个顶点连接
RegularPolygram(9, density=2)

# 正九边形,隔两个顶点连接
RegularPolygram(9, density=3)

4. 附件

文中完整的代码放在网盘中了(
polygon02.py
),

下载地址:
完整代码
(访问密码: 6872)

前言

在C# 9版本中引入了一项新特性:
顶级语句
,这一特性允许在不显式定义 Main 方法的情况下直接编写代码。

传统的写法

namespace TestStatements
{
    internal class Program
    {
        static void Main(string[] args)
        {
            foreach (var arg in args)
            {
                Console.WriteLine(arg);
            }
            Console.WriteLine("Hello, 追逐时光者!");
        }
    }
}

顶级语句写法

foreach (var arg in args)
{
    Console.WriteLine(arg);
}
Console.WriteLine("Hello, 追逐时光者!");

顶级语句的优势

  • 省去了 Main 方法和命名空间声明,使得代码更加简洁。
  • 特别适合编写简单的控制台应用、脚本和演示代码。
  • 对于初学者来说,不需要了解太多复杂的语法结构就可以开始编写 C# 程序。

顶级语句的不足

  • 顶级语句更适合于简单的程序,对于大型复杂的项目,传统的 Main 方法和命名空间这些还是非常有必要的。
  • 对于习惯了传统结构的开发者来说,顶级语句可能会让代码的组织结构显得不够明确。
  • 如果与其他 C# 版本或一些特定的项目结构混用,可能会导致兼容性问题。

最后总结

顶级语句通过简化代码结构,降低了学习曲线并提高了开发效率,特别适合初学者和编写简单程序的场景。然而,在大型项目中,传统的代码结构依然是必要的。因此,顶级语句和传统方法各有其适用的场景和优势,开发者可以根据具体需求选择使用哪种方式。对于我个人而言还是比较喜欢传统的写法,看起来更直观且代码的组织结构分明。

参考文章

图形界面使用

bucket

bucket创建

图形界面创建bucket。

022

023

特性:

  • Versioning
    开启版本控制,开启版本控制则允许在同一键下保持同一对象的多个版本。

  • Object Locking
    对象锁定防止对象被删除,需要支持保留和合法持有,只能在创建桶时启用。

  • Quita
    配额限制bucket中的数据量。

  • Retention
    保留会施加规则,在一段时间内防止对象删除。为了设置桶保留策略,必须启用版本控制。

确认创建成功,查看bucket详情。

024

035

Anonymous:配置Access Poilcy为custom,可以自己定义那些前缀是只读,那些前缀是读写的等。

036

Events:事件,设置Bucket绑定那些事件通知。

037

Lifecycle:生命周期,配置bucket的生命周期。
类型选择Expiry代表是过期直接删除,选择Transition就是过期后转移到目标存储服务器,需要搭配Tiering使用。

Prefix:文件名前缀。
After:代表多少天后过期。

038

039

测试上传

测试上传文件。

033

034

Access keys

创建Access Keys

图形界面创建AK和SK。

025

强烈建议对锁创建的key进行记录:

xuq70VZxkfwPvDG5Mfga
t3FgyXTOhfyKowWFbMvFpTPJ9rJQh0RiTLEnJ2F5

026

027

也可将所创建的Key下载到本地。

028

配置权限

授予权限

Minio 的存储桶默认是不和任何 Acess Key 关联,同时 Minio 支持标准 S3 协议,可以在创建 bucket 和 ak 后给 Access Key 授予某个 Bucket 存储桶的访问权限,实现 Key 和 Bucket 的绑定。

Policy

MinIO使用基于策略的访问控制(PBAC)来定义经过身份验证的用户有权访问的授权操作和资源。
每个策略描述一个或多个操作和条件,这些操作和条件概括了一个用户或一组用户的权限。
MinIO PBAC是为了兼容AWS IAM策略语法、结构和行为而构建的。
每个用户只能访问内置角色显式授予的资源和操作。
默认情况下,MinIO拒绝访问任何其他资源或操作。

即通过策略来管理用户是否有权进行操作和可访问的资源等等。

  • Policy语句
    语句中的信息均含在一系列的元素内。
    Version:指定要使用的策略语言版本。建议您使用最新的 2012-10-17 版本。
    Statement:将该主要策略元素作为以下元素的容器。可以在一个策略中包含多个语句。
    Sid(可选):包括可选的语句 ID 以区分不同的语句。
    Effect:使用 Allow 或 Deny 指示策略是允许还是拒绝访问。
    Principal(仅在某些情况下需要):如果创建基于资源的策略,必须指示要允许或拒绝访问的账户、用户、角色或联合身份用户。如果要创建 IAM 权限策略以附加到用户或角色,则不能包含该元素。主体暗示为该用户或角色。
    Action:包括策略允许或拒绝的操作列表。
    Resource(仅在某些情况下需要):如果创建 IAM 权限策略,必须指定操作适用的资源列表。如果创建基于资源的策略,则该元素是可选的。如果不包含该元素,则该操作适用的资源是策略附加到的资源。
    Condition(可选):指定策略在哪些情况下授予权限。

更多IMA参考:
IAM 中的策略和权限

User

User:MinIO用户由唯一的access key (username) 和 对应的 secret key (password)组成。

客户端必须通过指定现有MinlO用户的有效access key (username)和相应的secret key (password)来验证其身份。
Groups提供了一种简化的方法,用于管理具有通用访问模式和工作负载的用户之间的共享权限。
User通过所属组继承对数据和资源的访问权限。

MinlO使用基于策略的访问控制(PBAC)来定义经过身份验证的用户有权访问的授权操作和资源。
每个策略描述一个或多个操作和条件,这些操作和条件概括了一个用户或一组用户的权限。
每个用户只能访问内置角色显式授予的资源和操作。

默认情况下,MinlO拒绝访问任何其他资源或操作。

创建User。

040

Groups

Groups可以有一个附加的IAM策略,该组中具有成员资格的所有用户都继承该策略。
Groups支持更简化的MinIO租户用户权限管理,即可以通过用户组来管理用户组下的用户权限,多对多的关系,一个组下面有可以选择多个组员,一个组员可以属于多个用户组。

创建一个组。
041

042
确认创建成功。
043

设置Groups的Policy。

044

勾选已创建的Policy。

045

确认创建完成。
046

关联策略,关联用户成员,从而实现更方便的批量权限管理。

Monitoring

Metrics

Metrics指标,MinIO 支持 Prometheus 用于指标和警报。
Prometheus 是一个开源系统和服务监控系统 支持基于收集的指标进行分析和警报。
Prometheus 生态系统包括多个 integrations ,允许广泛的处理和存储范围收集的指标。

MinIO 发布了 Prometheus 兼容的集群获取endpoint和节点级指标。
看 指标 为了 更多信息。
对于警报,请使用 Prometheus Alerting Rules 和 Alert Manager 根据收集的指标触发警报。

MinIO 使用 Prometheus 兼容数据发布收集的指标数据结构。
任何与 Prometheus 兼容的抓取软件都可以获取和处理 MinIO 指标以进行分析、可视化和警报。

如下图所示,可以看到基本信息相关的监控指标。

047

Trace

追踪,选择那些Trace的调用,然后开启Trace,下面就会记录所有的Trace,如时间,名称。状态,等等。
048

Events

时间通知,MinIO桶通知允许管理员就某些对象或桶事件向受支持的外部服务发送通知。MinIO支持桶级和对象级S3事件,类似于Amazon S3事件通知。

本质是Minio操作完成后通过事件的形式对外进行通知。

049

Minio支持多种事件的通知,如下图所示:

050

Tiering

对象生命周期管理:Tiering由MinIO对象生命周期管理使用,它允许创建基于时间或日期的对象自动转换或到期规则。对于对象迁移,MinIO会自动将对象迁移到已配置的远端存储层。

对于对象到期,MinIO 会自动删除该对象。
即对象生命周期可以用户自定义管理,但是对象过期了处理方式,Minio提供了两种选择,要么直接删除该对象,要么把该对象转换到远端的存储服务上去。

051

MinIO支持创建对象转移的生命周期管理规则,MinIO可以自动将对象移动到远程存储“Tiering”:
MinIO支持以下Tier类型:

052

Site Replication

复制站点:网站复制,此特性允许将使用相同外部IDentity Provider (IDP)的多个独立MinIO站点(或集群)配置为副本。。

即复制一个副本出来,到目标网站,快速搭建集群,以及迁移,无需再繁琐的配置等。

053

如下图所示,填写对应的站点信息,包括名字、端地址、Access Key,Secret Key。
需要填写本站的,目标站的,目标站可以多个。

054

客户端使用

mc客户端安装

MinIO Client mc命令行工具提供了ls、cat、cp、mirror和diff等命令,支持文件系统和Amazon s3兼容的云存储服务。

mc命令行工具是为与AWS S3 API兼容而构建的,并在MinIO和AWS S3上测试了预期的功能和行为。

安装mc:

[root@master01 minio]# curl https://dl.min.io/client/mc/release/linux-amd64/mc \
  --create-dirs \
  -o /usr/local/bin/mc

[root@master01 minio]# chmod +x /usr/local/bin/mc
[root@master01 minio]# mc --autocompletion              #mc自动补全

[root@master01 minio]# mc --help

连接minio:
使用mc alias set命令将Amazon s3兼容的服务添加到mc配置中,将alias替换为要关联到S3服务的名称。
mc命令通常需要alias作为参数来标识要对哪个S3服务执行,如果省略ACCESS_KEY和SECRET_KEY,执行命令时会提示在CLI中输入这些值。

[root@master01 minio]# mc alias set myminio https://api.linuxsb.com minio minio123
Added `myminio` successfully.
[root@master01 minio]# mc admin info myminio

055

bucket管理

  • 创建bucket
[root@master01 ~]# mc mb myminio/mybucket02                 #创建bucket

[root@master01 ~]# mc ls myminio                            #列出bucket
[2024-09-06 04:14:49 CST]     0B mybucket/
[2024-09-09 07:29:20 CST]     0B mybucket02/
  • 删除bucket
[root@k8s-master ~]# mc rb myminio/mybucket02               #删除没有object的bucket

[root@k8s-master ~]# mc rb myminio/mybucket02 --force       #强制删除bucket,即使含有文件

object管理

  • 上传下载
[root@master01 ~]# echo "This is my test file!" > test01.txt
[root@master01 ~]# mc cp test01.txt myminio/mybucket/test01.txt                 #上传测试文件

[root@master01 ~]# mkdir testdir                                                #创建测试目录

[root@master01 ~]# echo "This is my test02 file!" > testdir/test02.txt
[root@master01 ~]# mc cp testdir myminio/mybucket --recursive                   #上传测试目录,且递归上传

[root@master01 ~]# mc ls myminio/mybucket                                       #查看minio存储
[2024-09-10 09:32:04 CST]    22B STANDARD test01.txt
[2024-09-10 09:32:45 CST]     0B testdir/

[root@master01 ~]# mkdir download
[root@master01 ~]# mc cp myminio/mybucket/test01.txt download/                  #下载文件
[root@master01 ~]# mc cp myminio/mybucket/testdir download/ --recursive         #下载目录,且递归下载

[root@master01 ~]# ll download/                                                 #查看文件
total 4.0K
-rw-r--r-- 1 root root 22 Sep 10 09:33 test01.txt
drwxr-xr-x 2 root root 24 Sep 10 09:34 testdir

[root@master01 ~]# ll download/testdir/
total 4.0K
-rw-r--r-- 1 root root 24 Sep 10 09:34 test02.txt
  • 删除
[root@master01 ~]# mc rm myminio/mybucket/test01.txt                            #删除文件

[root@master01 ~]# mc rm myminio/mybucket/testdir --recursive --force           #删除目录,即使包含文件

[root@master01 ~]# mc ls myminio/mybucket                                       #查看minio存储

Policy管理

查看policy

列出 MinIO 上的所有预设策略。

[root@master01 ~]# mc admin policy list myminio
diagnostics
mypolicy
readonly
readwrite
writeonly
consoleAdmin

删除policy

[root@master01 ~]# mc admin policy remove myminio listbucketsonly

创建policy

创建一个新的policy。

[root@master01 ~]# vim listbucketsonly.json              #编写新的策略规则
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListAllMyBuckets"
      ],
      "Resource": [
        "arn:aws:s3:::*"
      ]
    }
  ]
}

[root@master01 ~]# mc admin policy create myminio listbucketsonly ./listbucketsonly.json

User管理

  • 创建用户
[root@master01 ~]# mc admin user add myminio newuser newuser123
Added user `newuser` successfully.

[root@master01 ~]# mc admin user add myminio newuser02 newuser123
Added user `newuser02` successfully.

[root@master01 ~]# mc admin user add myminio newuser03 newuser123
Added user `newuser03` successfully.
  • 禁用用户
[root@master01 ~]# mc admin user disable myminio newuser
Disabled user `newuser` successfully.
  • 启用用户
[root@master01 ~]# mc admin user enable myminio newuser
Enabled user `newuser` successfully.
  • 给用户关联策略
[root@master01 ~]# mc admin policy attach myminio listbucketsonly --user newuser
Attached Policies: [listbucketsonly]
To User: newuser

  • 创建用户组及关联用户
    创建用户组,并关联用户。
[root@master01 ~]# mc admin group add myminio somegroup newuser
Added members `newuser` to group `somegroup` successfully.

[root@master01 ~]# mc admin group add myminio somegroup newuser02
Added members `newuser02` to group `somegroup` successfully.
  • 给用户组关联策略
[root@master01 ~]# mc admin policy attach myminio listbucketsonly --group somegroup
Attached Policies: [listbucketsonly]
To Group: somegroup
  • 列出用户
    列出用户,或以json格式列出。
[root@master01 ~]# mc admin user list myminio
enabled    newuser               listbucketsonly     
enabled    newuser02                                 
enabled    newuser03                                 

[root@master01 ~]# mc admin user list myminio --json
{
 "status": "success",
 "accessKey": "newuser02",
 "userStatus": "enabled"
}
{
 "status": "success",
 "accessKey": "newuser03",
 "userStatus": "enabled"
}
{
 "status": "success",
 "accessKey": "newuser",
 "policyName": "listbucketsonly",
 "userStatus": "enabled",
 "memberOf": [
  {
   "name": "somegroup",
   "policies": [
    "listbucketsonly"
   ]
  }
 ]
}
  • 显示用户信息
    显示用户详细信息。
[root@master01 ~]# mc admin user info myminio newuser
AccessKey: newuser
Status: enabled
PolicyName: listbucketsonly
MemberOf: [somegroup]
  • 删除用户
[root@master01 ~]# mc admin user remove myminio newuser03
Removed user `newuser03` successfully.

Groups管理

  • 创建用户组并添加用户

创建用户组并添加用户

  • 从组中移除用户
[root@master01 ~]# mc admin group remove myminio somegroup newuser02
Removed members {newuser02} from group somegroup successfully.
  • 列出用户组
[root@master01 ~]# mc admin group list myminio
mygroups
somegroup
  • 禁用用户组
[root@master01 ~]# mc admin group disable myminio somegroup
Disabled group `somegroup` successfully.
  • 启用用户组
[root@master01 ~]# mc admin group enable myminio somegroup
Enabled group `somegroup` successfully.
  • 显示用户组信息
[root@master01 ~]# mc admin group info myminio somegroup
Group: somegroup
Status: enabled
Policy: listbucketsonly
Members: newuser
  • 删除用户组
    只有当用户组为空,即用户组里不存在用户时,才可删除。
[root@master01 ~]# mc admin group remove myminio somegroup
mc: <ERROR> Could not perform remove operation. The specified group is not empty - cannot remove it. (Specified group is not empty - cannot remove it).

[root@master01 ~]# mc admin group info myminio somegroup                #查看用户组信息
Group: somegroup
Status: enabled
Policy: listbucketsonly
Members: newuser

[root@master01 ~]# mc admin group remove myminio somegroup newuser      #删除仅存的用户
Removed members {newuser} from group somegroup successfully.

[root@master01 ~]# mc admin group remove myminio somegroup              #再次删除用户组
Removed group somegroup successfully.

config管理

[root@master01 ~]# mc admin config export myminio                       #获取集群配置

[root@master01 ~]# mc admin config export myminio > my-serverconfig     #获取集群配置并重定向至文件

集群管理

查看集群信息

mc工具

显示debug调试

[root@master01 ~]# mc admin info --debug myminio

json格式显示

指定显示格式。

[root@master01 ~]# mc admin info myminio --json

重启minio服务

service命令提供了一种重新启动和停止所有 MinIO 服务器的方法。

[root@master01 ~]# mc admin policy --help
[root@master01 ~]# mc admin service restart myminio
Service status: ▰▰▱ [DONE]
Summary:
    ┌───────────────┬─────────────────────────────┐
    │ Servers:      │ 4 online, 0 offline, 0 hung │
    │ Restart Time: │ 1.133381597s                │
    └───────────────┴─────────────────────────────┘

curl工具使用

curl工具参考:
curl客户端使用