k8s 资源预留

KUBERNETES资源管理之–资源预留
Kubernetes 的节点可以按照 Capacity 调度。node节点本身除了运行不少驱动 OS 和 Kubernetes 的系统守护进程,默认情况下 pod 能够使用节点全部可用容量, 除非为这些系统守护进程留出资源,否则它们将与 pod 争夺资源并导致节点资源短缺问题。由于某些Pod没有对内存及CPU进行限制,导致Pod在运行过程中所需的内存超过了节点本身的内存(OOM),导致某些进程被Linux系统的OOM killer机制杀掉,假如被杀掉的进程是系统进程或K8S组件,会导致比较严重的问题,例如导致节点崩溃,使得运行在该节点上的所有Pod状态出现异常。

为了解决上述问题,可以采取如下方法

  • 每个节点为系统守护进程预留计算资源(CPU、内存、磁盘空间)
  • Pod驱逐:节点资源到达一定使用量,开始驱逐 pod,减轻本节点的压力
  • 每个Pod需指定所需资源,限制其可使用的资源上限。

一、资源问题概述

系统资源可分为两类:可压缩资源(CPU)和不可压缩资源(memory、storage)。可压缩资源比如CPU超配后,在系统满负荷时会划分时间片分时运行进程,系统整体会变慢(一般不会导致太大的问题)。但不可压缩资源如Memory,当系统内存不足时,就有可能触发系统 OOM;这时候根据 oom score 来确定优先杀死哪个进程,而 oom_score_adj 又是影响 oom score 的重要参数,其值越低,表示 oom 的优先级越低。在worker节点中,进程的 oom_score_adj 如下:
在这里插入图片描述
所以,OOM 的优先级如下:

BestEffort Pod > Burstable Pod > 其它进程 > Guaranteed Pod > kubelet/docker 等 > sshd 等

二、资源预留

kubelet的启动配置中有一个Node Allocatable特性,来为系统守护进程和k8s组件预留计算资源,使得即使节点满负载运行时,也不至于出现pod去和系统守护进程以及k8s组件争抢资源,导致节点挂掉的情况。目前支持对CPU, memory, ephemeral-storage三种资源进行预留。
在这里插入图片描述
可分配的节点暴露为 API 中 v1.Node 对象的一部分,也是 CLI 中 kubectl describe node 的一部分。

kubelet 中,可以为两类系统守护进程预留资源。
在这里插入图片描述
节点可供Pod使用资源总量的计算公式如下:

allocatable = NodeCapacity - [kube-reserved] - [system-reserved] - [eviction-threshold]

参考目前真实的物理环境,如下:

[root@node1 ~]# kubectl describe node node1
Capacity:cpu:                                        128ephemeral-storage:                          256378368Kihugepages-1Gi:                              36Giintel.com/intel_sriov_switchdev_xxv710_vf:  64memory:                                     527832708Kipods:                                       110
Allocatable:cpu:                                        112ephemeral-storage:                          236278303558hugepages-1Gi:                              36Giintel.com/intel_sriov_switchdev_xxv710_vf:  64memory:                                     448140932Kipods:                                       110这是我真实环境中的物理总量,cpu120C,内存504G,容器使用存储资源单独在/var目录下,未对存储资源进行限制,使用的默认值。系统中还开启了大页内存以及使用的sriov等资源(此处不做具体讲解,只说cpu,内存的限制使用)

三、kubelet常用配置参数

  • kube预留值
Kubelet 标志: --kube-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
Kubelet 标志: --kube-reserved-cgroup=#################
kube-reserved 用来给诸如 kubelet、容器运行时、节点问题监测器等 Kubernetes 系统守护进程记述其资源预留值。 该配置并非用来给以 Pod 形式运行的系统守护进程预留资源。假如组件要是以static pod形式启动的,那并不在这个kube-reserved管理并限制的cgroup中,而是在kubepod这个cgroup中。除了 cpu、内存 和 ephemeral-storage之外,pid 可用来指定为 kubernetes 系统守护进程预留指定数量的进程 ID。kube-reserved-cgroup这个参数用来指定k8s系统组件所使用的cgroup。注意,从 Kubernetes 1.18 版本开始,默认情况下,Kubernetes 已经为每个组件自动分配了一个保留的 cgroup。如果你的版本小于1.18,需要提前把指定的cgroup及其子系统需要预先创建好,kubelet并不会为你自动创建好。
  • system预留值
Kubelet 标志: --system-reserved=[cpu=100m][,][memory=100Mi][,][ephemeral-storage=1Gi][,][pid=1000]
Kubelet 标志: --system-reserved-cgroup=########################
system-reserved用于为系统守护进程记述其资源预留值例如sshd等服务。system-reserved也应该为kernel 预留内存,因为目前kernel使用的内存并不记在 Kubernetes 的 Pod 上。同时还推荐为用户登录会话预留资源(systemd 体系中的user.slice)。除了cpu、内存和ephemeral-storage之外,pid可用来指定为系统守护进程预留指定数量的进程 ID。如果你的版本小于1.18,需要提前创建system cgroup,否则kubelet启动失败。
  • 驱逐阈值
Kubelet 标志:--eviction-hard=[memory.available<500Mi]######################################
kubelet 的 --eviction-hard 标志用于设置 Kubernetes 节点上的资源耗尽情况下的强制驱逐策略。它支持以下资源阈值:1:memory.available:可用内存的百分比。例如,--eviction-hard=memory.available<100Mi 表示当可用内存小于 100 MiB 时触发驱逐。
2:nodefs.available:可用节点文件系统的百分比。例如,--eviction-hard=nodefs.available<10% 表示当可用节点文件系统空间小于 10% 时触发驱逐。
3:imagefs.available:可用容器镜像文件系统的百分比。例如,--eviction-hard=imagefs.available<15% 表示当可用容器镜像文件系统空间小于 15% 时触发驱逐。
可以使用 <、<=、>、>= 符号来设置不同的阈值条件。############################
请注意,--eviction-hard 的设置可能因 Kubernetes 版本而有所不同。确保参考您所使用的具体版本的文档来了解更多关于资源阈值以及其他相关设置和选项的详细信息。
  • 显示保留的cpu列表
Kubelet 标志:--reserved-cpus=0-3############################33
reserved-cpus旨在为操作系统守护程序和 kubernetes 系统守护程序保留一组明确指定编号的 CPU。

除了上述参数之外还有其他的一些参数可供参考

1:配置 cgroup 驱动 ,驱动通过--cgroup-driver标志配置。cgroupfs是默认的驱动,在主机上直接操作 cgroup 文件系统以对 cgroup 沙箱进行管理。systemd是可选的驱动,使用 init 系统支持的资源的瞬时切片管理 cgroup 沙箱。2:实施节点可分配约束 --enforce-node-allocatable=pods[,][system-reserved][,][kube-reserved]标志配置,调度器将 'Allocatable' 视为 Pod 可用的 capacity(资源容量)。kubelet 默认对 Pod 执行 'Allocatable' 约束。 无论何时,如果所有 Pod 的总用量超过了 'Allocatable',驱逐 Pod 的措施将被执行。可通过设置 kubelet --enforce-node-allocatable 标志值为 pods 控制这个措施。

四、cpu管理策略

默认情况下,kubelet 使用 CFS 配额 来执行 Pod 的 CPU 约束。 当节点上运行了很多 CPU 密集的 Pod 时,工作负载可能会迁移到不同的 CPU 核, 这取决于调度时 Pod 是否被扼制,以及哪些 CPU 核是可用的。 许多工作负载对这种迁移不敏感,因此无需任何干预即可正常工作。

然而,有些工作负载的性能明显地受到 CPU 缓存亲和性以及调度延迟的影响。 对此,kubelet 提供了可选的 CPU 管理策略,来确定节点上的一些分配偏好。

CPU 管理策略通过 kubelet 参数 --cpu-manager-policy来指定,有以下两种策略可供使用

  • none: 默认策略,表示现有的调度行为。
none策略为默认的CPU亲和方案,不提供操作系统调度器默认行为之外的亲和性策略。 通过 CFS 配额来实现 Guaranteed Pods 和 Burstable Pods 的 CPU 使用限制。
  • static: 允许为节点上具有某些资源特征的 Pod 赋予增强的 CPU 亲和性和独占性。
static策略针对具有整数型 CPU requests的 Guaranteed Pod ,它允许该Pod中的容器独占物理机的CPU资源。这种独占性是使用cpuset cgroup控制器来实现的。####################
注意: CPU管理器不支持运行时下线和上线 CPUs。如果节点上的在线CPUs集合发生变化,则必须驱逐节点上的Pod,并通过删除kubelet根目录中的状态文件cpu_manager_state来手动重置CPU管理器。#########################
此策略管理一个CPU共享池,该共享池最初包含节点上所有的CPU资源。可独占性CPU资源数量等于节点的CPU总量减去通过kubelet --kube-reserved和--system-reserved参数中预留的CPU资源。从1.17版本开始,可以通过 kubelet --reserved-cpus参数显式地指定CPU预留列表。由--reserved-cpus指定的显式CPU列表优先于由 --kube-reserved和--system-reserved指定的CPU预留。通过这些参数预留的CPU是以'整数'方式,按物理核心 ID升序从初始共享池获取的。 共享池是BestEffort和Burstable Pod运行的CPU集合。 Guaranteed Pod 中的容器,如果声明了'非整数值'的CPU requests,也将运行在共享池的CPU上。只有Guaranteed Pod中,指定了整数型CPU requests 的容器,才会被分配独占CPU资源。########################################
spec:containers:- name: nginximage: nginx该Pod属于BestEffort QoS类型,因为其未指定requests或limits值。所以该容器运行在共享CPU池中。###################################
spec:containers:- name: nginximage: nginxresources:limits:memory: "200Mi"requests:memory: "100Mi"
该Pod属于Burstable QoS类型,因为其资源requests不等于limits,且未指定cpu数量。所以该容器运行在共享CPU池中。###################################
spec:containers:- name: nginximage: nginxresources:limits:memory: "200Mi"cpu: "2"requests:memory: "100Mi"cpu: "1"
该Pod属于Burstable QoS类型,因为其资源requests 不等于limits。所以该容器运行在共享 CPU池中。#######################################
spec:containers:- name: nginximage: nginxresources:limits:memory: "200Mi"cpu: "2"requests:memory: "200Mi"cpu: "2"
该Pod属于Guaranteed QoS类型,因为其requests值与limits相等。同时容器对CPU资源的限制值是一个大于或等于1的整数值。所以该nginx容器被赋予2个独占CPU。#################################
spec:containers:- name: nginximage: nginxresources:limits:memory: "200Mi"cpu: "1.5"requests:memory: "200Mi"cpu: "1.5"
该Pod属于Guaranteed QoS类型,因为其requests值与limits相等。但是容器对CPU资源的限制值是一个小数。所以该容器运行在共享CPU池中。#####################################
spec:containers:- name: nginximage: nginxresources:limits:memory: "200Mi"cpu: "2"该Pod属于Guaranteed QoS类型,因其指定了limits值,同时当未显式指定时,requests值被设置为与limits值相等。同时容器对CPU资源的限制值是一个大于或等于1的整数值。所以该 nginx容器被赋予2个独占CPU。

CPU 管理器定期通过 CRI 写入资源更新,以保证内存中 CPU 分配与 cgroupfs 一致。 同步频率通过新增的 Kubelet 配置参数 --cpu-manager-reconcile-period 来设置。 如果不指定,默认与 --node-status-update-frequency 的周期相同。

更改 CPU 管理器策略

CPU 管理器策略只能在 kubelet 生成新 Pod 时应用,所以简单地从 “none” 更改为 “static” 将不会对现有的 Pod 起作用。更改节点上的 CPU 管理器策略步骤如下:

1:删除旧的CPU管理器状态文件。文件的路径默认为/var/lib/kubelet/cpu_manager_state。这将清除CPUManager维护的状态,以便新策略设置的 cpu-sets 不会与之冲突。
2:修改kubelet的启动参数
3:重启kubelet

五、NUMA 感知的内存管理器

Kubernetes 内存管理器(Memory Manager)为 Guaranteed QoS 类 的 Pods 提供可保证的内存(或者内存大页)分配能力。内存管理器使用提示生成协议来为 Pod 生成最合适的 NUMA 亲和性配置。 内存管理器将这类亲和性提示输入给中央管理器(即 Topology Manager)。 基于所给的提示和 Topology Manager(拓扑管理器)的策略设置,Pod 或者会被某节点接受,或者被该节点拒绝。此外,内存管理器还确保 Pod 所请求的内存是从尽量少的 NUMA 节点分配而来。

使用内存管理器的前提条件

  • CPU 管理器应该被启用,并且在节点(Node)上要配置合适的 CPU 管理器策略。
  • 拓扑管理器要被启用,并且要在节点上配置合适的拓扑管理器策略。

我的环境是1.23.6。默认开启MemoryManager

内存管理策略

内存管理器支持两种策略。通过 kubelet 参数 --memory-manager-policy 来选择哪种策略,如下:

  • none(默认)
默认的策略,并且不会以任何方式影响内存分配。None策略返回默认的拓扑提示信息
  • static
对Guaranteed Pod而言,Static内存管理器策略会返回拓扑提示信息,该信息与内存分配有保障的NUMA节点集合有关,并且内存管理器还通过更新内部的'节点映射'对象来完成内存预留。对BestEffort或Burstable Pod而言,因为不存在对有保障的内存资源的请求,Static内存管理器策略会返回默认的拓扑提示,并且不会通过内部的'节点映射对象'来预留内存。

内存管理策略配置

前面提到的参数包括 --kube-reserved--system-reserved--eviction-threshold。 这些参数值的综合计作预留内存的总量。为内存管理器而新增加的 --reserved-memory 参数可以将总的预留内存进行划分, 并完成跨 NUMA 节点的预留操作。

标志设置的值是一个按 NUMA 节点的不同内存类型所给的内存预留的值的列表,用逗号分开。内存管理器不会使用这些预留的内存来为容器负载分配内存。
配置方式如下:
--reserved-memory N:memory-type1=value1,memory-type2=value2,...
1:N(整数)- NUMA 节点索引,例如,0,1,2,3,4
2:memory-type(字符串)- 代表内存类型:memory 表示常规内存hugepages-2Mi或hugepages-1Gi 表示内存大页
3:value(字符串) 表示预留内存的量,例如 1Gi######################
举例如下:
--reserved-memory 0:memory=1Gi,hugepages-1Gi=2Gi 在numa0上预留了1G的普通内存和2G的内存大页如果有多个numa,可以写成如下配置
--reserved-memory 0:memory=1Gi --reserved-memory 1:memory=2Gi#########################
在设置--reserved-memory时,必须遵守如下公式
sum(reserved-memory(i)) = kube-reserved + system-reserved + eviction-threshold
也就是reserved-memory的值等于kube预留、系统预留以及阈值条件(默认的硬性驱逐阈值是 100MiB)的总和#########################
当系统中有以下设置时
--kube-reserved=cpu=4,memory=16Gi 
--system-reserved=cpu=12,memory=16Gi 
--eviction-hard=memory.available<8Gi  ##如果此值没有设置,则reserved-memory需要加上默认的100Mi
--memory-manager-policy=Static那么reserved-memory的值就是kube-reserved + system-reserved + eviction-hard
正确设置为--reserved-memory 0:memory=20Gi --reserved-memory 1:memory=20Gi

k8s中,内存管理器文件位于/var/lib/kubelet/memory_manager_state中

六、实践

上面讲述了需要的知识点,接下来我们按照实际的物理环境来进行配置

  • 检查节点的cpu拓扑
lscpu查看系统中cpu数量
[root@node1 ~]# lscpu 
架构:           x86_64
CPU 运行模式:   32-bit, 64-bit
字节序:         Little Endian
CPU:             128
在线 CPU 列表:  0-127      ###总共有128C,并开启了超线程
每个核的线程数: 2
每个座的核数:   32
座:             2
NUMA 节点:      8
厂商 ID:        HygonGenuine
BIOS Vendor ID:  Chengdu Hygon
CPU 系列:       24
型号:           0
型号名称:       Hygon C86 7285 32-core Processor
BIOS Model name: Hygon C86 7285 32-core Processor
步进:           2
CPU MHz:        2461.008
CPU 最大 MHz:   2000.0000
CPU 最小 MHz:   1200.0000
BogoMIPS:       4000.07
虚拟化:         AMD-V
L1d 缓存:       32K
L1i 缓存:       64K
L2 缓存:        512K
L3 缓存:        8192K
NUMA 节点0 CPU: 0-7,64-71
NUMA 节点1 CPU: 8-15,72-79
NUMA 节点2 CPU: 16-23,80-87
NUMA 节点3 CPU: 24-31,88-95
NUMA 节点4 CPU: 32-39,96-103
NUMA 节点5 CPU: 40-47,104-111
NUMA 节点6 CPU: 48-55,112-119
NUMA 节点7 CPU: 56-63,120-127###################
查看numa架构
[root@node1 ~]# numactl -H
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3 4 5 6 7 64 65 66 67 68 69 70 71
node 0 size: 63973 MB
node 0 free: 1335 MB
node 1 cpus: 8 9 10 11 12 13 14 15 72 73 74 75 76 77 78 79
node 1 size: 64441 MB
node 1 free: 54748 MB
node 2 cpus: 16 17 18 19 20 21 22 23 80 81 82 83 84 85 86 87
node 2 size: 64507 MB
node 2 free: 50674 MB
node 3 cpus: 24 25 26 27 28 29 30 31 88 89 90 91 92 93 94 95
node 3 size: 64507 MB
node 3 free: 9211 MB
node 4 cpus: 32 33 34 35 36 37 38 39 96 97 98 99 100 101 102 103
node 4 size: 64507 MB
node 4 free: 28655 MB
node 5 cpus: 40 41 42 43 44 45 46 47 104 105 106 107 108 109 110 111
node 5 size: 64507 MB
node 5 free: 26002 MB
node 6 cpus: 48 49 50 51 52 53 54 55 112 113 114 115 116 117 118 119
node 6 size: 64507 MB
node 6 free: 4099 MB
node 7 cpus: 56 57 58 59 60 61 62 63 120 121 122 123 124 125 126 127
node 7 size: 64507 MB
node 7 free: 53190 MB
node distances:
node   0   1   2   3   4   5   6   7 0:  10  16  16  16  28  28  22  28 1:  16  10  16  16  28  28  28  22 2:  16  16  10  16  22  28  28  28 3:  16  16  16  10  28  22  28  28 4:  28  28  22  28  10  16  16  16 5:  28  28  28  22  16  10  16  16 6:  22  28  28  28  16  16  10  16 7:  28  22  28  28  16  16  16  10 
[root@node1 ~]# 
  • 设置预留资源
配置方式有两种,可以修改/var/lib/kubelet/config.yaml文件进行修改,不过不建议采用
此处我们采用另外一种方式,修改kubelet启动服务文件,如下:
1:进入kebelet服务配置目录,有默认的10-kubeadm.conf配置文件
[root@node1 ~]# cd /etc/systemd/system/kubelet.service.d/
[root@node1 kubelet.service.d]# ll
总用量 8
-rw-r--r-- 1 root root 1003 9月  10 14:33 10-kubeadm.conf2:编辑新文件11-kubelet.conf,添加如下内容
[Service]
Environment="KUBELET_ECS_ARGS=--kube-reserved=cpu=4,memory=16Gi --system-reserved=cpu=12,memory=16Gi --eviction-hard=memory.available<8Gi,nodefs.available<10% --cpu-manager-policy=static --reserved-cpus=0-3,64-67,32-35,96-99 --memory-manager-policy=Static --reserved-memory 0:memory=20Gi --reserved-memory 4:memory=20Gi"#####################
我们环境中为kube组件预留了4个cpu和16G内存,为系统进程预留12个cpu和16G内存的资源,阈值条件是当时系统内存少于8G时,执行pod疏散任务。预留的cpu列表是0-3,64-67,32-35,96-99   ##共16个cpu,根据上面的numa架构,位于numa0和numa4上,也别需要注意一点,预留cpu时,物理核一定要和其超线程对应,例如cpu0的超线程是64reserved-memory的值是16G + 16G + 8G = 40G ###因为预留的cpu位于两个numa上,所以reserved-memory的numa也要与之对应,否则共享池中的pod在访问内存时,会出现跨numa的问题,影响性能
  • 重启kubelet
1:首先要删除系统的/var/lib/kubelet/cpu_manager_state和/var/lib/kubelet/memory_manager_state,避免与旧的策略产生冲突
2:加载服务 systemctl daemon-reload
3:重启kubelet服务 systemctl restart kubelet 
新的策略文件会重新生成
  • 启动pod查看资源使用
1:编辑pod 启动yaml,如下;
apiVersion: v1
kind: Pod
metadata:name: nginx
spec:containers:- name: nginximage: docker.io/library/nginx:latestimagePullPolicy: IfNotPresentresources:limits:memory: "200Mi"cpu: "2"requests:memory: "200Mi"cpu: "2"2:启动pod,如下:
[root@node1 ~]# kubectl apply -f  pod.yaml 
pod/nginx created
[root@node1 ~]# vim pod.yaml 
[root@node1 ~]# 
[root@node1 ~]# 
[root@node1 ~]# kubectl get po -o wide 
NAME    READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          55s   172.10.30.91   node3   <none>           <none>3:以上得知pod位于node3节点,查看该节点的cpu管理策略文件
[root@node3 ~]# cat /var/lib/kubelet/cpu_manager_state 
{"policyName":"static","defaultCpuSet":"0-3,21-23,32-67,85-87,96-127","entries":{"28e92e4f-958d-4f9d-8aae-e2f8557dee9d":{"nginx":"20,84"},"66ce7446-8e92-49d7-8c49-06c9ccf46e6a":{"loam-b":"13-14,77-78"},"9f223236-e84e-4169-8139-e103062d54ee":{"llb":"15-16,79-80"},"c25c6025-cfda-4c87-9413-0627187848c0":{"ipds":"7,19,24-31,71,83,88-95"},"c396c532-70d1-41b0-9993-30b2bd36d7b3":{"necc":"4,8-10,68,72-74"},"c4020329-6fc9-41a3-94c8-1d47a08e48e5":{"eems":"5,69"},"d82d23c7-b3a5-43cf-ba77-df4a2de5b225":{"alms":"6,70"},"e14ad8c9-a58c-4cad-a309-b0be2047c7cb":{"loam-a":"17-18,81-82"},"e4a6664a-d38e-4bcb-a5bd-65027645da14":{"llb":"11-12,75-76"}},"checksum":1874914806}以上可以看到nginx使用的cpu是20,84,结合上面的cpu的拓扑,位于numa2上。4:查看node3节点的内存管理文件
[root@node3 ~]# cat /var/lib/kubelet/memory_manager_state  | jq ."nginx": [{"numaAffinity": [0            ####nginx使用的内存位于numa0上,和cpu不在一个numa上,如果这个是性能型pod,会影响业务的使用],"type": "memory","size": 2147483648}]############################################
如果要解决pod使用cpu和内存numa不一致问题,有以下方法
1:关闭服务器numa功能,使节点只有一个numa0
2:在kubelet中添加配置参数 --topology-manager-policy=single-numa-node 
3:重新加载服务配置,重启kubelet。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

BUUCTF 另外一个世界 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 下载附件&#xff0c;解压得到一个.jpg图片。 密文&#xff1a; 解题思路&#xff1a; 1、这道题我尝试了很多方法&#xff0c;知道看了别人的wp才知道flag在我忽略的地方。将图片在010 Editor中打开&#xff0c;从…

服务号升级订阅号的流程

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;首先我们要知道服务号和订阅号有什么区别。服务号侧重于对用户进行服务&#xff0c;每月可推送4次&#xff0c;每次最多8篇文章&#xff0c;发送的消息直接显示在好友列表中。订阅号更侧重于信息传…

【QT】绘图设备

绘图设备是指继承QPainterDevice的子类。Qt提供了很多这样的类&#xff0c;例如QPixmap、QBitmap、QImage和 QPicture。其中&#xff0c; QPixmap专门为图像在屏幕上的显示做了优化QBitmap是QPixmap的一个子类&#xff0c;它的色深限定为1&#xff0c;可以使用 QPixmap的isQBi…

使用工具+迅雷解决ESP32配置下载问题

因为一些原因下载git上内容相当缓慢或都根本无法下载所以写了一个工具获取链接并使用迅雷下载。 工具下载&#xff1a;【免费】使用迅雷下载开发板工具资源-CSDN文库

分享77个工作总结PPT,总有一款适合您

分享77个工作总结PPT&#xff0c;总有一款适合您 PPT下载链接&#xff1a;https://pan.baidu.com/s/1qdoA_Ylbxkmp2Qkh9VDw8A?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 水彩插画风幼儿说课PPT模板 舞龙舞狮文化传承通…

【前端设计】HTML+CSS+JavaScript基本特性

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

小程序使用echarts(超详细教程)

小程序使用echarts第一步就是先引用到小程序里面&#xff0c;可以直接从这里下载 文件很多&#xff0c;我们值下载 ec-canvas 就好&#xff0c;下载完成后&#xff0c;直接放在pages同级目录下 index.js 在我们需要的页面的 js 文件顶部引入 // pages/index/index.js impor…

BUUCTF RSA4

BUUCTF RSA4 下载题目&#xff0c;可见文件给出了3组n和c N 331310324212000030020214312244232222400142410423413104441140203003243002104333214202031202212403400220031202142322434104143104244241214204444443323000244130122022422310201104411044030113302323014101…

从零开始的目标检测和关键点检测(三):训练一个Glue的RTMPose模型

从零开始的目标检测和关键点检测&#xff08;三&#xff09;&#xff1a;训练一个Glue的RTMPose模型 一、重写config文件二、开始训练三、ncnn部署 从零开始的目标检测和关键点检测&#xff08;一&#xff09;&#xff1a;用labelme标注数据集 从零开始的目标检测和关键点检测…

Java自学第1课:安装JDK+Eclipse

1 引言 在学习前&#xff0c;我想说一句&#xff0c;那就是为什么要学习Java。 每个人的出发点都不同&#xff0c;对于做信息化的工程技术人员来说&#xff0c;java不懂&#xff0c;就没法干项目。 尽管有c和matlab等基础&#xff0c;但java看起来与这些语言都不太一样。 做…

PXI-6608 185745H-02 PXI-6527 185633D-01

PXI-6608 185745H-02 PXI-6527 185633D-01 人工智能技术并不新鲜&#xff0c;但运行它的数据和计算却很新鲜 对于那些对人工智能技术历史感兴趣的人来说&#xff0c;一些今天正在使用的技术从20世纪50年代和60年代就已经存在了。 但是&#xff0c;如果人工智能已经存在了这么…

智能电表瞬时电量是什么意思?

智能电表已经成为我们进行能源管理的重要工具。其中&#xff0c;瞬时电量这一概念逐渐走进大众视野。那么&#xff0c;智能电表瞬时电量究竟是什么意思&#xff1f;它对我们的生活和能源管理又有哪些影响呢&#xff1f;下面&#xff0c;小编就来为大家介绍一下瞬时电量&#xf…

安卓毕业设计:基于安卓Android的仓库货物管理app

项目介绍 本文介绍了仓库货物管理APP软件开发建设的意义和国内外发展现状&#xff0c;然后详细描述了所开发手机APP的可行性分析&#xff0c;并分析了手机APP所要实现的功能。因为仓库货物管理设施较多&#xff0c;而且人口密集&#xff0c;不能更好的管理仓库货物&#xff0c…

django毕业设计基于python企业资产管理系统

项目介绍 本文首先介绍了企业资产管理系统的发展背景与发展现状&#xff0c;然后遵循软件常规开发流程&#xff0c;首先针对系统选取适用的语言和开发平台&#xff0c;根据需求分析制定模块并设计数据库结构&#xff0c;再根据系统总体功能模块的设计绘制系统的功能模块图&…

【LeetCode刷题-链表】--146.LRU缓存

146.LRU缓存 方法一&#xff1a;哈希表双向链表 使用一个哈希表和一个双向链表维护所有在缓存中的键值对 双向链表按照被使用的顺序存储了这些键值对&#xff0c;靠近头部的键值对是最近使用的&#xff0c;而靠近尾部的键值对是最久使用的哈希表即为普通的哈希映射&#xff0…

文心一言 VS 讯飞星火 VS chatgpt (127)-- 算法导论11.2 2题

二、用go语言&#xff0c;位向量(bit vector)是一个仅包含0和1的数组。长度为m的位向量所占空间要比包含m个指针的数组少得多。请说明如何用一个位向量来表示一个包含不同元素(无卫星数据)的动态集合。字典操作的运行时间应为 O(1)。 文心一言&#xff0c;代码正常运行&#x…

HTML5+CSS3+JS小实例:简约的黑色分页

实例:简约的黑色分页 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" content="…

【计算机网络】数据链路层——以太网协议

目录 1.完整的数据传输流程2.以太网以太网通信原理以太网帧格式MAC地址对比MAC地址和IP地址MTU 3.ARP协议ARP协议的作用ARP协议的格式ARP协议的原理 1.完整的数据传输流程 IP拥有将数据跨网络从一台主机送到另一台主机的能力&#xff0c;但IP并不能保证每次都能够将数据可靠的送…

docker中安装rabbitMq并配置启动

目录 1. 拉取镜像并安装&#xff08;此处实例安装的是最新版&#xff09;2.查看docker中已安装的镜像和版本3.启动RabbitMq4.配置管理端5.安装完成 1. 拉取镜像并安装&#xff08;此处实例安装的是最新版&#xff09; docker pull rabbitmq2.查看docker中已安装的镜像和版本 …

06、如何将对象数组里 obj 的 key 值变成动态的(即:每一个对象对应的 key 值都不同)

1、数据情况&#xff1a; 其一、从后端拿到的数据为&#xff1a; let arr [1,3,6,10,11,23,24] 其二、目标数据为&#xff1a; [{vlan_1: 1, value: 1}, {vlan_3: 3, value: 1}, {vlan_6: 6, value: 1}, {vlan_10: 10, value: 1}, {vlan_11: 11, value: 1}, {vlan_23: 23, v…