PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解
文章目录
- 1. nn.Module
- 1.1 基本使用
- 1.2 常用函数
- 1.2.1 核心函数
- 1.2.2 查看函数
- 1.2.3 设置函数
- 1.2.4 注册函数
- 1.2.5 转换函数
- 1.2.6 加载函数
- 2. nn.Sequential()
- 2.1 基本定义
- 2.2 Sequential类不同的实现
- 2.3 nn.Sequential()的本质作用
- 3. nn.ModuleList
- 参考资料
本篇文章主要介绍 torch.nn.Module
、torch.nn.Sequential()
、torch.nn.ModuleList
的使用方法与区别。
1. nn.Module
1.1 基本使用
在PyTorch中,nn.Module
类扮演着核心角色,它是构建任何自定义神经网络层、复杂模块或完整神经网络架构的基础构建块。通过继承 nn.Module
并在其子类中定义模型结构和前向传播逻辑(forward() 方法),开发者能够方便地搭建并训练深度学习模型。
在自定义一个新的模型类时,通常需要:
- 继承
nn.Module
类 - 重新实现
__init__
构造函数 - 重新实现
forward
方法
实现代码如下:
import torch.nn as nn
import torch.nn.functional as Fclass Model(nn.Module):# nn.Module的子类函数必须在构造函数中执行父类的构造函数def __init__(self):super(Model, self).__init__() # 等价与nn.Module.__init__()self.conv1 = nn.Conv2d(1, 20, 5)self.conv2 = nn.Conv2d(20, 20, 5)def forward(self, x):x = F.relu(self.conv1(x))return F.relu(self.conv2(x))model=Model()
print(model)
输出如下:
注意:
- 一般把网络中具有可学习参数的层(如全连接层、卷积层)放在构造函数
__init__()
中 - forward() 方法必须重写,它是实现模型的功能,实现各个层之间连接关系的核心
nn.Module
类中的关键属性和方法包括:
-
初始化 (init):在类的初始化方法中定义并实例化所有需要的层、参数和其他组件。
在实现自己的MyModel类时继承了nn.Module,在构造函数中要调用Module的构造函数super(MyModel,self).init()
-
前向传播 (forward):实现前向传播函数来描述输入数据如何通过网络产生输出结果。
因为parameters是自动求导,所以调用forward()后,不用自己写和调用backward()函数。而且一般不是显式的调用forward(layer.farword),而是layer(input),会自执行forward()。 -
管理参数和模块:
- 使用 .parameters() 访问模型的所有可学习参数。
- 使用 add_module() 添加子模块,并给它们命名以便于访问。
- 使用 register_buffer() 为模型注册非可学习的缓冲区变量。
- 训练与评估模式切换:
- 使用 model.train() 将模型设置为训练模式,这会影响某些层的行为,如批量归一化层和丢弃层。
- 使用 model.eval() 将模型设置为评估模式,此时会禁用这些依赖于训练阶段的行为。
- 保存和加载模型状态:
- 调用 model.state_dict() 获取模型权重和优化器状态的字典形式。
- 使用 torch.save() 和 torch.load() 来保存和恢复整个模型或者仅其状态字典。
- 通过 model.load_state_dict(state_dict) 加载先前保存的状态字典到模型中。
此外,nn.Module 还提供了诸如移动模型至不同设备(CPU或GPU)、零化梯度等实用功能,这些功能在整个模型训练过程中起到重要作用。
1.2 常用函数
torch.nn.Module 这个类的内部有多达 48 个函数,下面就一些比较常用的函数进行讲解。
1.2.1 核心函数
-
__init__
函数 和forward()
函数
__init__中主要是初始化一些内部需要用到的state;forward在这里没有具体实现,是需要在各个子类中实现的,如果子类中没有实现就会报错raise NotImplementedError。 -
apply(fn)
函数
将Module及其所有的SubModule传进给定的fn函数操作一遍。我们可以用这个函数来对Module的网络模型参数用指定的方法初始化。下边这个例子就是将网络模型net中的子模型Linear的参数全部赋值为 1 。
def init_weight(m):if type(m) == nn.Linear:m.weight.data.fill_(1.0)m.bias.data.fill_(0)net = nn.Sequential(nn.Linear(2, 2))
net.apply(init_weight)
输出如下:
state_dict()
函数
返回一个包含module的所有state的dictionary,而这个字典的Keys对应的就是parameter和buffer的名字names。该函数的源码部分有一个循环可以递归遍历Module中所有的SubModule。
net = torch.nn.Linear(2, 2)
print(net.state_dict())
输出如下:
print(net.state_dict().keys())
add_module()
函数
将子模块加入当前模块中,被添加的模块可以用name来获取
1.2.2 查看函数
使用 nn.Module
中的查看类函数可以对网络中的参数进行有效管理,常用的查看类参数如下:
parameters() #返回一个包含模型所有参数的迭代器
buffers()
children() # 返回当前模型子模块的迭代器
modules() # 返回一个包含当前模型所有模块的迭代器与之对应的四个函数:named_parameters()
named_buffers()
namde_children()
named_modules()
parameters()
函数
可以使用for param in model.parameters()来遍历网络模型中的参数,因为该函数返回的是一个迭代器iterator。我们在使用优化算法的时候就是将model.parameters()传给优化器Optimizer。
net = nn.Sequential(nn.Linear(2, 2))
params = list(net.parameters())
print(params)
输出如下:
-
buffers
函数、children
函数 和modules
函数
与parameters()函数类似。 -
named_parameters()
函数
net = nn.Sequential(nn.Linear(2, 2))
print(type(net.named_parameters()))
for name, params in net.named_parameters():print(name, params)
输出如下:
named_buffers
函数、named_children
函数 和named_modules
函数
与named_parameters()函数类似。
1.2.3 设置函数
设置类包含包括设置模型的训练/测试状态、梯度设置、设备设置等。
train()
函数 和eval()
函数- train(): 将Module及其SubModule设置为training mode
- eval(): 将Module及其SubModule设置为evaluation mode
这两个函数只对特定的Module有影响,例如Class Dropout、Class BatchNorm。
-
requires_grad()
函数 和zero_grad()
函数- 设置self.parameters()是否需要record梯度,默认情况下是True。
- 函数zero_grad 用于设置self.parameters()的gradients为零。
-
cuda()
函数 和cpu()
函数- cuda(): Moves all model parameters and buffers to the GPU.
- cpu(): Moves all model parameters and buffers to the CPU.
两者返回的都是Module本身且都调用了_apply函数。
to()
函数
函数to的作用是原地 ( in-place ) 修改Module,它可以当成三种函数来使用:- to(device=None, dtype=None, non_blocking=False):设备
- to(dtype, non_blocking=False):类型
- to(tensor, non_blocking=False): 张量
基于nn.Modeule构建Linear层:
linear = nn.Linear(2, 2)
print(linear.weight)
# Parameter containing:
# tensor([[ 0.4331, 0.6347],
# [ 0.5735, -0.0210]], requires_grad=True)
修改参数类型:
linear.to(torch.double)
print(linear.weight)
# Parameter containing:
# tensor([[ 0.4331, 0.6347],
# [ 0.5735, -0.0210]], dtype=torch.float64, requires_grad=True)
修改设备类型:
gpu1 = torch.device("cuda:1")
linear.to(gpu1, dtype=torch.half, non_blocking=True)
# Linear(in_features=2, out_features=2, bias=True)print(linear.weight)
# Parameter containing:
# tensor([[ 0.4331, 0.6347],
# [ 0.5735, -0.0210]], dtype=torch.float16, device='cuda:1')
cpu = torch.device("cpu")
linear.to(cpu)
# Linear(in_features=2, out_features=2, bias=True)print(linear.weight)
# Parameter containing:
# tensor([[ 0.4331, 0.6347],
# [0.5735, -0.0210]], dtype=torch.float16)
1.2.4 注册函数
register_parameter # 向self._parameters注册新元素
register_buffer # 向self._buffers注册新元素register_backward_hook # 向self._backward_hook注册新元素
register_forward_pre_hook # 向self._forward_pre_hook注册新元素
register_forward_hook # 向self._forward_hook注册新元素
1.2.5 转换函数
to() # 转换为张量,设置类型、设备等
type() # 将parameters和buffers的数据类型转换为目标类型dst_type
double() # 将parameters和buffers的数据类型转换为double
float() # 将parameters和buffers的数据类型转换为float
half() # 将parameters和buffers的数据类型转换为half
1.2.6 加载函数
可以很方便的进行 save 和 load,以防止突然发生的断点和系统崩溃现象
load_state_dict(state_dict, strict=True)
# 将state_dict中的参数和缓冲区复制到此模块及其后代中。如果strict为真,则state_dict的键必须与该模块的state_dict()函数返回的键完全匹配。"""
state_dict (dict) – 保存parameters和persistent buffers的字典。
将state_dict中的parameters和buffers复制到此module和它的后代中。state_dict中的key必须和 model.state_dict()返回的key一致。
"""
2. nn.Sequential()
nn.Sequential()是一个序列容器,用于搭建神经网络的模块按照被传入构造器的顺序添加到nn.Sequential()容器中。除此之外,一个包含神经网络模块的OrderedDict也可以被传入nn.Sequential()容器中。利用nn.Sequential()搭建好模型架构,模型前向传播时调用forward()方法,模型接收的输入首先被传入nn.Sequential()包含的第一个网络模块中。然后,第一个网络模块的输出传入第二个网络模块作为输入,按照顺序依次计算并传播,直到nn.Sequential()里的最后一个模块输出结果。
2.1 基本定义
先简单看一下它的定义:
class Sequential(Module): # 继承Moduledef __init__(self, *args): # 重写了构造函数def _get_item_by_idx(self, iterator, idx):def __getitem__(self, idx):def __setitem__(self, idx, module):def __delitem__(self, idx):def __len__(self):def __dir__(self):def forward(self, input): # 重写关键方法forward
2.2 Sequential类不同的实现
方法一:最简单的序列模型
import torch.nn as nnmodel = nn.Sequential(nn.Conv2d(1, 20, 5),nn.ReLU(),nn.Conv2d(20, 64, 5),nn.ReLU())
# 采用第一种方式,默认命名方式为 [0,1,2,3,4,...]
print(model, '\n')
print(model[2]) # 通过索引获取第几个层
输出如下:
在每一个包装块里面,各个层是没有名称的,层的索引默认按照0、1、2、3、4来排名。
方法二:有序字典(给每一个层添加名称)
import torch.nn as nn
from collections import OrderedDictmodel = nn.Sequential(OrderedDict([('conv1', nn.Conv2d(1,20,5)),('relu1', nn.ReLU()),('conv2', nn.Conv2d(20,64,5)),('relu2', nn.ReLU())]))
print(model, '\n')
print(model[2]) # 通过索引获取第几个层
输出如下:
很多人认为python中的字典是无序的,因为它是按照hash来存储的,但是python中有个模块collections(英文,收集、集合),里面自带了一个子类OrderedDict,实现了对字典对象中元素的排序。
从上面的结果中可以看出,这个时候每一个层都有了自己的名称,但是此时需要注意,并不能够通过名称直接获取层,依然只能通过索引index,即model[2] 是正确的,model[“conv2”] 是错误的,这其实是由它的定义实现的,看上面的Sequenrial定义可知,只支持index访问。
方法三:add_module()
import torch.nn as nn
from collections import OrderedDictmodel = nn.Sequential()model.add_module("conv1", nn.Conv2d(1, 20, 5))
model.add_module('relu1', nn.ReLU())
model.add_module('conv2', nn.Conv2d(20, 64, 5))
model.add_module('relu2', nn.ReLU())print(model, '\n')
print(model[2]) # 通过索引获取第几个层
输出如下:
这里,add_module()这个方法是定义在它的父类Module里面的,Sequential继承了该方法。
2.3 nn.Sequential()的本质作用
与一层一层的单独调用模块组成序列相比,nn.Sequential() 可以允许将整个容器视为单个模块(即相当于把多个模块封装成一个模块),forward()方法接收输入之后,nn.Sequential()按照内部模块的顺序自动依次计算并输出结果。
这就意味着我们可以利用nn.Sequential() 自定义自己的网络层,示例如下:
import torch.nn as nnclass Model(nn.Module):def __init__(self, in_channel, out_channel):super(Model, self).__init__()self.layer1 = nn.Sequential(nn.Conv2d(in_channel, in_channel / 4, kernel_size=1),nn.BatchNorm2d(in_channel / 4),nn.ReLU())self.layer2 = nn.Sequential(nn.Conv2d(in_channel / 4, in_channel / 4),nn.BatchNorm2d(in_channel / 4),nn.ReLU())self.layer3 = nn.Sequential(nn.Conv2d(in_channel / 4, out_channel, kernel_size=1),nn.BatchNorm2d(out_channel),nn.ReLU())def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)return x
上边的代码,我们通过nn.Sequential()将卷积层,BN层和激活函数层封装在一个层中,输入x经过卷积、BN和ReLU后直接输出激活函数作用之后的结果。
3. nn.ModuleList
nn.ModuleList就像一个普通的Python的List,我们可以使用下标来访问它。好处是传入的ModuleList的所有Module都会注册到PyTorch里,这样Optimizer就能找到其中的参数,从而用梯度下降进行更新。但是nn.ModuleList并不是Module(的子类),因此它没有forward等方法,通常会被放到某个Module里。
- nn.ModuleList()
ModuleList 具有和List 相似的用法,实际上可以把它视作是 Module 和 list 的结合。
# 输入参数 modules (list, optional) – 将要被添加到MuduleList中的 modules 列表class Model(nn.Module):def __init__(self):super().__init__()self.layers=nn.ModuleList([nn.Linear(1,10), nn.ReLU(),nn.Linear(10,1)])def forward(self,x):out = xfor layer in self.layers:out = layer(out)return outmodel = Model()
print(model)
输出如下:
- append(module)
class Model(nn.Module):def __init__(self):super().__init__()self.layers=nn.ModuleList([nn.Linear(1,10), nn.ReLU(),nn.Linear(10,1)])self.layers.append(nn.Linear(1, 5))def forward(self,x):out = xfor layer in self.layers:out = layer(out)return out
- extend(modules)
extend(),必须也为一个list
self.layers.extend([nn.Linear(size1, size2) for i in range(1, num_layers)])
nn.Sequential()和nn.ModuleList的区别:
- nn.Sequential()定义的网络中各层会按照定义的顺序进行级联,因此需要保证各层的输入和输出之间要衔接。
- nn.Sequential()实现了farward()方法,因此可以直接通过类似于x=self.combine(x)实现 forward()。
- nn.ModuleList则没有顺序性要求,并且也没有实现forward()方法。
参考资料
- 【PyTorch】torch.nn.Module 源码分析
- pytorch nn.Module()模块
- https://github.com/ShusenTang/Dive-into-DL-PyTorch/blob/master/docs/chapter04_DL_computation/4.1_model-construction.md
相关文章:

PyTorch之nn.Module、nn.Sequential、nn.ModuleList使用详解
文章目录 1. nn.Module1.1 基本使用1.2 常用函数1.2.1 核心函数1.2.2 查看函数1.2.3 设置函数1.2.4 注册函数1.2.5 转换函数1.2.6 加载函数 2. nn.Sequential()2.1 基本定义2.2 Sequential类不同的实现2.3 nn.Sequential()的本质作用 3. nn.ModuleList参考资料 本篇文章主要介绍…...

C++Primer Plus 第十四章代码重用:编程练习,第4题
CPrimer Plus 第十四章代码重用:编程练习,第4题 CPrimer Plus 第十四章代码重用:编程练习,第4题 文章目录 CPrimer Plus 第十四章代码重用:编程练习,第4题前言4.一、定义二、方法 前言 4. Person 类保存人的名和姓。除构造函数外ÿ…...

01 Docker 概述
目录 1.Docker简介 2.传统虚拟机 vs 容器 3.Docker运行速度快的原因 4.Docker基本组成三要素 5.Docker 平台架构 入门版 架构版 1.Docker简介 Docker是基于Go语言实现的云开源项目。 Docker的主要目标是:Build, Ship and Run Any App, Anywhere,…...

c++的const
const在C中是一个非常重要的关键字,用于定义不可变的变量、函数参数、成员函数等。它可以提高代码的可读性、安全性,并帮助编译器进行优化。 定义常量 使用const定义不可变的变量: const int MAX_SIZE 100;常量指针 指向常量的指针和常量…...

Git不想跟踪某个文件
如果你不想跟踪某个文件,可以将该文件路径添加到 .gitignore 文件中。.gitignore 文件用于告诉 Git 哪些文件或目录应该被忽略,不进行版本控制。以下是具体步骤: 编辑 .gitignore 文件:在项目的根目录下找到或创建一个 .gitignore…...

DB-GPT 文档切分报错
感谢阅读 配置完知识库,进行切分报错切分完成后,进行问答时后台日志报错 配置完知识库,进行切分报错 报的错如下 document sync error cryptography>3.1 is required for AES algorithm pip install -U cryptography 之后重新运行程序 …...

#如何使用 Qt 5.6 在 Android 上启用 NFC
如何使用 Qt 5.6 在 Android 上启用 NFC NFC 技术在 Android 应用开发中变得越来越重要。在本文中,我将介绍如何使用 Qt 5.6 来实现 Android 上的 NFC 功能。这个教程基于一个创建于 8 年 8 个月前的问题,并在 7 年 3 个月前进行了修改,讨论…...

合并排序的数组
题目链接 合并排序的数组 题目描述 注意点 A的末端有足够的缓冲空间容纳BA和B都是排序的 解答思路 最初想到的是双指针,从小到大找到合并B时应该A相应位置应该插入的元素,因为在插入的过程中B的元素会替换A原有位置的元素,所以需要先将A…...

js 复制文本带样式
一键复制带样式的html文本到邮件 <div><div idcopy-content><div style{{ fontSize: 16px,fontWeight: 500, lineHeight: 24px, color: #222, marginBottom: 16px }}>邀请您参加腾讯会议网络研讨会(Webinar)</div></div><Button …...

服务器之BIOS基础知识总结
1.BIOS是什么? BIOS全称Basic Input Output System,即基本输入输出系统,是固化在服务器主板的专用ROM上,加载在服务器硬件系统上最基本的运行程序,它位于服务器硬件和OS之间,在服务器启动过程中首先运行&am…...

FFmpeg 实现从摄像头获取流并通过RTMP推流
使用FFmpeg库实现从USB摄像头获取流并通过RTMP推流,FFmpeg版本为4.4.2-0。RTMP服务器使用的是SRS,拉流端使用VLC。 在Linux上查看摄像头信息可使用 v4l2-ctl 工具,查看命令如下: v4l2-ctl --device/dev/video0 --list-formats-e…...

学生管理系统
一、登录 用户类:属性:用户名、密码、身份证号码、手机号码 1、欢迎页面 System.out.println("欢迎来到学生管理系统"); System.out.println("请选择操作1登录 2注册 3忘记密码"); 代码实现: //欢迎页面public static…...

【linux】网络基础(3)——tcp协议
文章目录 TCP协议概括TCP头部格式TCP连接管理建立连接(三次握手)数据传输确认应答机制捎带应答 滑动窗口丢包问题 拥塞控制延时应达 终止连接(四次挥手) TCP协议概括 TCP是一个面向连接的协议,在传输数据之前需要建立连…...

[Day 21] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
區塊鏈的智能合約運行機制 區塊鏈技術自比特幣誕生以來,便以其去中心化、安全性和透明性等特點引起了廣泛的關注和應用。而智能合約作為區塊鏈技術的一大創新,進一步擴展了區塊鏈的應用場景,使其不僅僅局限於數字貨幣,還可以應用…...

使用ps给gif动图抠图
目录 导入gif图片 打开时间轴 选择图片 魔棒抠图-初步抠图 套索抠图-精准抠图 导入gif图片 打开时间轴 因为gif动图实际上多张图片实现的效果,所以如果要给gif抠图,就得挨个给每个时间线的图片抠图 点击窗口->时间轴 选择图片 在时间轴上选择要…...

pmp顺利通关总结
目录 一、背景二、总结三、过程 一、背景 人活着总是想去做一些事情,通过这些事情来证明自己还活着。 而我证明自己还会活着并且活得很好的方式和途径,是通过这些东西去让自己有一个明确的边界节点;借此知识来验证自己的学习能力。 我坚定认…...

未来的钥匙在于过去:学历史的真正意义,震惊!历史竟然是偶然的?从历史中寻找未来的方向!
我们自幼接受的教育是,学历史是为了相信历史是必然的。中国人民必然战胜日寇的侵略,解放思想和改革开放必定会发生,和平和发展必定是世界的主题,中国经济必定是高速增长…… 然而,在真正的历史学家眼中,历史…...

ES6自定义模块
在ES6中,我们可以使用 export 和 import 关键字来定义和使用自定义模块。 定义模块 导出(export) 命名导出(Named Exports): 使用 export 关键字来导出模块中的变量、函数、类等。例如: // ma…...

Windows页面错误(Page Fault)写几种c++会导致,此问题的例子
在C中,直接导致Windows页面错误(Page Fault)的情景较少直接由编程错误引发,页面错误更多是由操作系统在内存管理和虚拟内存机制中处理的。不过,某些编程错误可能导致访问违规,进而间接引起操作系统报告页面…...

AC7801时钟配置流程
一 默认配置 在启动文件中,已经对时钟进行了初始化,默认按外部8M晶振,配置系统时钟为48MHZ,APB为系统时钟的2分频,为24MHZ。在system_ac780x.c文件中,可以找到下面这个系统初始化函数,里面有Se…...

加密与安全_Java 加密体系 (JCA) 和 常用的开源密码库
文章目录 Java Cryptography Architecture (JCA)开源国密库国密算法对称加密(DES/AES⇒SM4)非对称加密(RSA/ECC⇒SM2)散列(摘要/哈希)算法(MD5/SHA⇒SM3) 在线生成公钥私钥对,RSA公私钥生成参考…...

读书笔记-《Spring技术内幕》(三)MVC与Web环境
前面我们学习了 Spring 最核心的 IoC 与 AOP 模块(读书笔记-《Spring技术内幕》(一)IoC容器的实现、读书笔记-《Spring技术内幕》(二)AOP的实现),接下来继续学习 MVC,其同样也是经典…...

k8s及常用对象简介
文章目录 一、k8s是什么应用程序早期部署形式容器的引入k8s的作用 二、k8s中的常用对象1、Node获取node信息 2、Namespacenamespace的使用 3、Pod生命周期pod的使用 4、DaemonSetDaemonSet的使用 5、Deployment创建deploy 6、ReplicaSet7、StatefulSet创建StatefulSet 8、更新操…...

HTTPS数字证书验证论述
1 概述 网络请求方式通常分为两种,分别是HTTP请求和HTTPS请求,其中HTTP的传输属于明文传输,在传输的过程中容易被人截取并且偷窥其中的内容,而HTTPS是一种在HTTP的基础上加了SSL/TLS层(安全套接层)的安全的…...

【高考志愿】地质资源与地质工程
目录 一、专业概述 1.1 专业定义 1.2 主要课程 1.3 专业培养目标 二、就业前景和考研方向 三、工作特点和挑战 四、如何培养核心竞争力 五、 地质资源与地质工程专业排名 六、结语 关于高考志愿选择地质资源与地质工程专业,以下是一些详细的介绍和参考信息…...

全网最佳硕士研究生复试简历模板
硕士研究生复试简历模板 ✨ 简介 提供了一个适用于国内硕士研究生复试的个人简历模板。该模板通过统一的“样式”形成规范的Word格式,是目前研究生复试的最佳简历模板之一。模板使用“华文中宋”字体,如您的电脑中未安装此字体,请提前安装。…...

Rocky Linux 9 系统OpenSSH CVE-2024-6387 漏洞修复
Rocky Linux 9系统 OpenSSH CVE-2024-6387 漏洞修复 1、漏洞修复2、修复思路3、修复方案3.1、方案一3.2、方案二 4、总结5、参考 1、漏洞修复 CVE-2024-6387:regreSSHion:OpenSSH 服务器中的远程代码执行(RCE),至少在…...

Sping源码(九)—— Bean的初始化(非懒加载)—mergeBeanDefinitionPostProcessor
序言 前几篇文章详细介绍了Spring中实例化Bean的各种方式,其中包括采用FactoryBean的方式创建对象、使用反射创建对象、自定义BeanFactoryPostProcessor以及构造器方式创建对象。 创建对象 这里再来简单回顾一下对象的创建,不知道大家有没有这样一个疑…...

labview技巧——AMC框架安装
AMC工具包的核心概念是队列,队列是一种先进先出(FIFO,First In First Out)的数据结构,适用于处理并发和异步任务。在LabVIEW中,队列可以用于在不同VI之间传递数据,确保消息的有序处理࿰…...

解锁分布式云多集群统一监控的云上最佳实践
作者:在峰 引言 在当今数字化转型加速的时代,随着混合云、多云多集群环境等技术被众多企业广泛应用,分布式云架构已成为众多企业和组织推动业务创新、实现弹性扩展的首选,分布式云容器平台 ACK One(Distributed Clou…...