openeuler 22.03 lts sp4 使用 cri-o 和 静态 pod 的方式部署 k8s-v1.32.0 高可用集群

devtools/2025/2/7 1:00:12/

前情提要

整篇文章会非常的长…可以选择性阅读,另外,这篇文章是自己学习使用的,用于生产,还请三思和斟酌

  • 静态 pod 的部署方式和二进制部署的方式是差不多的,区别在于 master 组件的管理方式是 kubectl 还是 systemctl
  • 有 kubeadm 工具,为什么还要用静态 pod 的方式部署?
    • kubeadm init 节点一旦灾难性异常了,整个 k8s 集群都难逃一死(我曾经干活干迷瞪了,要 reset 一个 worker 节点,不小心在 kubeadm init 节点执行 kubeadm reset 命令,整个集群都废了,好在是测试环境,pod 服务都有持久化和相关的 yaml 文件兜底,直接重建 k8s 集群了
  • 有二进制部署的方式,为什么还要用静态 pod 的方式部署?
    • 统一采集 pod 日志也能同时采集 master 组件的日志,不需要额外的处理
    • pod 的 request 和 limit 颗粒度更小,能更好的调整 master 组件的资源使用限制

相关概念

The differences between Docker, containerd, CRI-O and runc

  • 此图概述了 Docker、Kubernetes、CRI、OCI、containerd 和 runc 如何在这个生态系统中协同工作

在这里插入图片描述

OCI

**Open Container Initiative (OCI):**一组容器标准,用于描述镜像格式、运行时和分发的规范

  • OCI 是为容器世界创建一些标准的首批工作之一
  • 它由 Docker 和其他公司于 2015 年成立
  • OCI 得到了许多科技公司的支持,并维护着容器映像格式以及容器应如何运行的规范

CRI

**Container Runtime Interface (CRI) in Kubernetes:**是 Kubernetes 用来控制创建和管理容器的不同运行时的接口

  • CRI 使 Kubernetes 更容易使用不同的容器运行时
  • Kubernetes 项目不需要单独为每个运行时添加支持,而是描述了 Kubernetes 将如何与任何运行时交互
  • 只要给定的容器运行时实现 CRI API,运行时就可以按照自己的喜好创建和启动容器

在这里插入图片描述

containerd 和 CRI-O 都实现了 CRI 规范,都可以用来当作容器运行时

Docker

  • 容器化就是从 Docker 开始的,对很多人来说 “Docker” 这个名字本身就是 “容器” 的代名词
  • 它是管理容器的最流行的工具
  • 现在被命名为 Docker Engine
  • docker 命令实际上调用了一些较低级别的工具来完成繁重的工作

在这里插入图片描述

  • docker-cli:这是一个命令行工具,它是用来完成 docker 命令的 pull, build, run, exec 等进行交互。
  • containerd:这是高级别的容器运行时,一个管理和运行容器的守护进程。它推送和拉取镜像,管理存储和网络,并监督容器的运行。
  • runc:这是低级别的容器运行时(实际创建和运行容器的东西)。它包括 libcontainer,一个用于创建容器的基于 Go 的本地实现。
dockershim

由于 Docker 比 Kubernetes 更早,没有实现 CRI,这就是 dockershim 存在的原因,它支持将 Docker 被硬编码到 Kubernetes 中

  • 随着容器化成为行业标准,Kubernetes 项目增加了对额外运行时的支持,比如通过 Container Runtime Interface (CRI) 容器运行时接口来支持运行容器
  • dockershim 将会从 Kubernetes 1.24 中完全移除
    • 所有支持 OCI 规范的镜像,containerd 和 CRI-O 都可以运行

containerd

containerd 是来自 Docker 的高级容器运行时

  • containerd 诞生于原始 Docker 项目的一部分,之后被捐赠给云原生计算基金会(CNCF)
  • 在内部,Docker Engine 使用 containerd,所以安装 docker 的时候会同时安装 containerd

CRI-O

CRI-O 是一个轻量级的容器运行时

  • 它诞生于 Red Hat、IBM、Intel、SUSE 和其他公司
  • 专注于 Kubernetes 的需求,提供一个精简的容器运行时
  • 由 Kubernetes 使用的 kubelet 来管理和调用,直接通过 Kubernetes 的 CRI 接口与容器交互

runc

一个轻量级的容器运行时,负责创建和运行容器实例,是实现 OCI 接口的最低级别的容器运行时

  • 容器提供所有低级功能,并与现有的低级 Linux 功能(如命名空间和控制组)交互,使用这些功能来创建和运行容器进程

关系总结

  • runc: 容器运行时的低层实现,负责直接启动和运行容器
  • containerd: 容器运行时管理工具,负责容器的生命周期管理,通常通过 runc 来启动容器
  • CRI-O: 为 Kubernetes 提供的容器运行时实现
  • Docker: 一个容器平台,使用 containerd 作为容器运行时,包含了容器构建、管理和运行的完整工具链

开始部署

环境介绍

使用 podman 是因为比 docker 更轻量,没有 deamon 守护进程,只是一个命令文件,自身不占用系统资源,配置私有仓库什么的,也不存在重启服务,和 docker 一样的语法

组件版本
OSopenEuler 22.03 (LTS-SP4)
podman3.4.4
k8s1.32.0
cri-o1.23.2
etcd3.5.16-0
pause3.10
calicov3.26.0
corednsv1.11.3
haproxy2.9.8
keepalived2.3.1

机器 ip 和对应的服务

IPHOSTNAMESERVICE/ROLE
192.168.182.129k8s-master-01k8s-master+keepalived+haproxy
192.168.182.130k8s-master-02k8s-master+keepalived+haproxy
192.168.182.131k8s-master-03k8s-master+keepalived+haproxy
192.168.182.132k8s-worker-04k8s-worker
192.168.182.133k8s-worker-05k8s-worker
192.168.182.200/VIP

系统初始化相关

  • 如果是虚拟机还没就绪,可以先启动一台机器,执行完初始化后,直接克隆机器更方便快捷
  • 如果机器已经就绪了,下面的初始化操作,每个机器都需要执行
  • 下面的操作省略了静态 ip 时间同步的操作,大家自己操作一下
关闭防火墙
systemctl disable firewalld --now
关闭 selinux
setenforce 0
sed -i '/SELINUX/s/enforcing/disabled/g' /etc/selinux/config
关闭 swap
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
开启内核模块
# 针对于 kube-proxy 使用 ipvs 模式的
modprobe ip_vs
modprobe ip_vs_rr
modprobe ip_vs_wrr
modprobe ip_vs_sh
# 常规要开启的
modprobe nf_conntrack
modprobe br_netfilter
modprobe overlay
开启模块自动加载服务
cat > /etc/modules-load.d/k8s-modules.conf <<EOF
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
br_netfilter
overlay
EOF

设置为开机自启

systemctl enable systemd-modules-load && systemctl restart systemd-modules-load
sysctl 内核参数调整
cat <<EOF > /etc/sysctl.d/kubernetes.conf
# 开启数据包转发功能(实现vxlan)
net.ipv4.ip_forward=1
# iptables对bridge的数据进行处理
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.bridge.bridge-nf-call-arptables=1
# 不允许将TIME-WAIT sockets重新用于新的TCP连接
net.ipv4.tcp_tw_reuse=0
# socket监听(listen)的backlog上限
net.core.somaxconn=32768
# 最大跟踪连接数,默认 nf_conntrack_buckets * 4
net.netfilter.nf_conntrack_max=1000000
# 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.swappiness=0
# 计算当前的内存映射文件数。
vm.max_map_count=655360
# 内核可分配的最大文件数
fs.file-max=6553600
# 持久连接
net.ipv4.tcp_keepalive_time=600
net.ipv4.tcp_keepalive_intvl=30
net.ipv4.tcp_keepalive_probes=10
EOF

立即生效

sysctl -p /etc/sysctl.d/kubernetes.conf

特殊操作:/etc/sysctl.conf 文件里面的 net.ipv4.ip_forward=0 会覆盖掉上面子配置文件里面的值

  • 猜测是因为 /etc/openEuler_security/security.conf 文件里面配置了 301@m@/etc/sysctl.conf@net.ipv4.ip_forward=@0,但是不确定修改后会影响哪些,还是打算直接修改 /etc/sysctl.conf ,这样就不会导致机器重启,kubelet 起不来的情况
sed -i 's|^net.ipv4.ip_forward.*|net.ipv4.ip_forward=1|g' /etc/sysctl.conf
sysctl -p
清空 iptables 规则
iptables -F && \
iptables -X && \
iptables -F -t nat && \
iptables -X -t nat && \
iptables -P FORWARD ACCEPT
安装各种依赖和工具
yum install -y vim wget curl tar net-tools jq bash-completion tree bind-utils telnet unzip nc
修改 .bashrc 文件

具体参考我之前的博客:关于 openeuler 22.03-LTS-SP4 scp 失败问题的记录,主要影响的是 scp 命令,具体的,看大家自己选择

安装 kubectl 和 kubelet

k8s 官方也没有 openeuler 的源,但是可以直接使用 kubernetes-el7 的源来安装,下面是配置 kubernetes-el7

  • 由于 Kubernetes 官方变更了仓库的存储路径以及使用方式,如果需要使用 1.28 及以上版本,请使用新版配置方法进行配置:https://developer.aliyun.com/mirror/kubernetes
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.32/rpm/repodata/repomd.xml.key
EOF

后面会用 kubeadm 来生成 kubeconfig 证书

  • 新版本的 k8s 仓库,安装 kubeadm 不再自动安装 kubelet 和 kubectl 了,这里需要都装一下
  • 新版本的 k8s 仓库,安装 kubeadm 也不再自动安装 conntrack-tools 了,kube-proxy 依赖 conntrack
yum install -y kubeadm-1.32.0 kubelet-1.32.0 kubectl-1.32.0 conntrack-tools

利用 kubeadm 提前拉取镜像

kubeadm config images pull --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --kubernetes-version 1.32.0
安装 CRI-O
  • openeuler 的 EPOL 里面自带 cri-o,直接 yum 安装即可
  • crictl 可以在后期用来查看容器状态,日志等操作
yum install -y cri-o crictl
配置 cri-o

默认配置文件是 /etc/crio/crio.conf

[crio.image]
pause_image = "registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.10"
# 指定 cgroup 是 systemd,虽然参数默认是 systemd,这里再加一下也不影响
[crio.runtime]
cgroup_manager = "systemd"
# 默认配置文件里面是 true
[crio.metrics]
enable_metrics = false

启动 cri-o 并配置开机自启

systemctl enable crio.service --now
配置 crictl

检查 /etc/crictl.yaml 里面的内容

runtime-endpoint: "unix:///var/run/crio/crio.sock"
安装 podman
yum install -y podman

修改配置文件 /etc/containers/registries.conf

  • 让不带仓库的镜像自动指定 docker.io 这个仓库前缀,podman 不指定镜像仓库的时候,本地显示是 localhost/
unqualified-search-registries = ["docker.io"]

重启 crio,让 crio 重新加载 /etc/containers/registries.conf

systemctl restart crio.service

到这一步,就可以克隆机器了

配置变量

创建目录

mkdir -p /appdata/k8s_deploy

配置变量,避免一些目录名称或者 ip 和我不一样,后面还要一个个检查和修改,后面全部使用变量来替代,尽可能通过 cv 就可以完成部署

cat > /appdata/k8s_deploy/k8s.env <<EOF
# 部署文件的存放目录
deploy_home="/appdata/k8s_deploy"
# k8s master 节点
k8s_master_nodes='
192.168.182.129
192.168.182.130
192.168.182.131
'# k8s worker 节点
k8s_worker_nodes='
192.168.182.132
192.168.182.133
'# 所有节点
all_nodes="
\${k8s_master_nodes}
\${k8s_worker_nodes}
"
# 临时的证书目录
cert_dir=\${deploy_home}/certs
# 定义 k8s 目录
k8s_home=/etc/kubernetes
# k8s 证书目录
k8s_cert=\${k8s_home}/certs
# k8s kubeconfig 目录
kubeconfig_dir=\${k8s_home}/kubeconfig
# k8s 静态 pod 目录
manifest_dir=\${k8s_home}/manifests
# k8s 静态 pod 配置文件目录
pod_config=\${k8s_home}/static_pod_config
# k8s 高可用域名,自己定义
k8s_vip_url=apiserver.ha.icu
# k8s 高可用 vip 地址
k8s_vip_ip=192.168.182.200
# haproxy 端口
k8s_vip_port=8443
# 宿主机网卡名称
interface_name=ens33
# k8s svc 的 ip 段
svc_ip_range=10.96.0.1
# apiserver 中 svc 的网段配置,上下两个变量必须是同一个网段的
svc_cluster_ip_range=10.96.0.0/12
# coredns 的 ip 地址
cluster_dns=10.96.0.10
# k8s pod 的网段
cluster_cidr=172.22.0.0/16
EOF

将 source 命令加入到 ~/.bashrc 目录下面,防止终端断开后,变量为空

cat >> ~/.bashrc <<EOF
source /appdata/k8s_deploy/k8s.env
EOF
source ~/.bashrc

证书制作

创建证书目录

for i in ${k8s_master_nodes};do ssh ${i} "mkdir -p ${k8s_cert}";done
mkdir -p ${deploy_home}/{templates,certs}
ca 证书
  • 注:kubeadm 在创建证书的时候有三个 ca 证书,我这边就一个 ca 通用了,没啥影响

生成一个 2048 位的 ca.key 文件

openssl genrsa -out ${cert_dir}/ca.key 2048

在 ca.key 文件的基础上,生成 ca.crt 文件(用参数 -days 设置证书有效期,单位:天)

openssl req -x509 -new -nodes \
-key ${cert_dir}/ca.key \
-subj "/CN=kubernetes" \
-addext "keyUsage=critical,digitalSignature,keyEncipherment,keyCertSign" \
-addext "subjectAltName=DNS:kubernetes" \
-days 36525 \
-out ${cert_dir}/ca.crt

检查证书到期时间

openssl x509 -text -in ${cert_dir}/ca.crt | grep -A 2 Validity
分发 ca 证书到所有 master 节点
for i in ${k8s_master_nodes};do scp ${cert_dir}/{ca.crt,ca.key} ${i}:${k8s_cert}/;done
apiserver 相关证书
kube-apiserver.crt

生成一个 2048 位的 kube-apiserver.key 文件

cert_name='kube-apiserver'
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

证书配置文件模板

cat > ${deploy_home}/templates/server-csr.cnf.tmp <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn[ dn ]
CN = kubernetes[ req_ext ]
subjectAltName = @alt_names[ v3_ext ]
basicConstraints=critical, CA:FALSE
keyUsage=critical, digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName = @alt_names[ alt_names ]
EOF

生成证书配置文件

sed "s|CN =.*|CN = ${cert_name}|g" ${deploy_home}/templates/server-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnfidx_num=1;
for dnsurl in ${k8s_master_nodes} ${k8s_vip_ip} ${k8s_vip_url} kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local;
do echo "DNS.${idx_num} = ${dnsurl}" >> ${cert_dir}/${cert_name}-csr.cnf;let idx_num++;
doneidx_num=1;
for hostip in ${k8s_master_nodes} ${k8s_vip_ip} ${svc_ip_range};
do echo "IP.${idx_num} = ${hostip}" >> ${cert_dir}/${cert_name}-csr.cnf;let idx_num++;
done

生成 kube-apiserver.csr 证书

openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 apiserver.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
kube-apiserver-kubelet-client.crt

生成一个 2048 位的 kube-apiserver-kubelet-client.key 文件

cert_name='kube-apiserver-kubelet-client'
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

证书配置文件模板

cat > ${deploy_home}/templates/client-csr.cnf.tmp <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn[ dn ][ v3_ext ]
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=clientAuth
EOF

生成 kube-apiserver-kubelet-client.csr 证书

cat ${deploy_home}/templates/client-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnf
openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-subj "/O=system:masters/CN=${cert_name}" \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 kube-apiserver-kubelet-client.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
front-proxy-client.crt
  • 这个证书是 apiserver 的代理身份验证和身份识别相关的,比如 metrics-server 等代理的部署会依赖

生成一个 2048 位的 front-proxy-client.key 文件

cert_name=front-proxy-client
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

生成 front-proxy-client.csr 证书

cat ${deploy_home}/templates/client-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnf
openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-subj "/CN=${cert_name}" \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 front-proxy-client.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
kube-apiserver-etcd-client.crt

生成一个 2048 位的 kube-apiserver-etcd-client.key 文件

cert_name=kube-apiserver-etcd-client
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

生成 kube-apiserver-etcd-client.csr 证书

cat ${deploy_home}/templates/client-csr.cnf.tmp > ${cert_dir}/${cert_name}-csr.cnf
openssl req -new -key ${cert_dir}/${cert_name}.key \
-out ${cert_dir}/${cert_name}.csr \
-subj "/O=system:masters/CN=${cert_name}" \
-config ${cert_dir}/${cert_name}-csr.cnf

使用 csr 证书和 ca 证书生成 kube-apiserver-etcd-client.crt 证书

openssl x509 -req -sha256 -in ${cert_dir}/${cert_name}.csr \
-CA ${cert_dir}/ca.crt \
-CAkey ${cert_dir}/ca.key \
-CAcreateserial \
-out ${cert_dir}/${cert_name}.crt \
-days 36525 \
-extensions v3_ext \
-extfile ${cert_dir}/${cert_name}-csr.cnf
sa.pub

生成 sa.key 私钥

openssl genpkey -algorithm RSA -out ${cert_dir}/sa.key -pkeyopt rsa_keygen_bits:2048

生成 sa.pub 公钥文件

openssl rsa -pubout -in ${cert_dir}/sa.key -out ${cert_dir}/sa.pub
验证证书链

返回 ok 说明证书链没问题

for i in kube-apiserver kube-apiserver-etcd-client kube-apiserver-kubelet-client front-proxy-client;do openssl verify -CAfile ${cert_dir}/ca.crt ${cert_dir}/${i}.crt;done
分发 apiserver 相关证书到 master 节点
for i in ${k8s_master_nodes};do scp ${cert_dir}/{kube-apiserver*.crt,kube-apiserver*.key,front-proxy-client.crt,front-proxy-client.key,sa.key,sa.pub} ${i}:${k8s_cert}/;done
etcd 相关证书
  • 注:kubeadm 在创建证书的时候,etcd 会创建 server,peer 和 ca 三个证书,ca 已经通用了,剩下的两个证书也可以通用,就不重复创建了

生成一个 2048 位的 kube-etcd.key 文件

cert_name='kube-etcd'
openssl genrsa -out ${cert_dir}/${cert_name}.key 2048

证书配置文件模板

cat > ${deploy_home}/templates/serverAndClient-csr.cnf.tmp <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn[ dn ]
CN = kubernetes[ req_ext ]
subjectAltName = @alt_names[ v3_ext ]
basicConstraints=critical, CA:FALSE
keyUsage=critical, digitalSignature, keyEncipherment
extendedKeyUsage=serverAuth, clientAuth
subjectAltName = @alt_names[ alt_names ]
EOF

生成证书配置文件

for i in ${k8s_master_nodes};do sed "s|CN =.*|CN = ${i}|g" ${deploy_home}/templates/serverAndClient-csr.cnf.tmp > ${cert_dir}/${cert_name}-${i}-csr.cnf;done
idx_num=1;
for i in ${k8s_master_nodes};
dofor dnsurl in ${k8s_master_nodes} localhost;doecho "DNS.${idx_num} = ${dnsurl}" >> ${cert_dir}/${cert_name}-${i}-csr.cnf;let idx_num&#

http://www.ppmy.cn/devtools/156663.html

相关文章

linux——网络(服务器的永久不挂——守护进程)

文章目录 目录 文章目录 前言 一、前后台进程 1. 前台进程 (Foreground Process) 2. 后台进程 (Background Process) 3. 前后台进程的切换 4. 关键命令和操作 5. 注意事项 6. 信号处理 二、守护进程 1. 守护进程的核心特点 2. 常见守护进程示例 3.接口介绍 1、 fork() 2. sets…

深度学习|表示学习|卷积神经网络|NIN 相比普通 CNN|17

如是我闻&#xff1a; Network in Network (NIN) 是 2014 年由 Min Lin 等人 提出的一个改进 CNN 结构的模型。它的核心思想是&#xff1a;用小型的多层感知机&#xff08;MLP&#xff0c;Multi-Layer Perceptron&#xff09;替代传统 CNN 中的卷积层&#xff0c;从而提高网络的…

powershell编写一个简易的http服务器httpServer

文章目录 powershell一键启动检查相关进程 源码 powershell一键启动 一键启动脚本内容(powershell,兼容windows powershell和powershell7) irm https://gitee.com/xuchaoxin1375/scripts/raw/main/PS/Tools/Tools.psm1|iex sleep 0.5 help Start-HTTPServer #可以指定参数选择…

Rust场景示例:为什么要使用切片类型

通过对比 不用切片 和 使用切片 的场景&#xff0c;说明切片类型在 Rust 中的必要性&#xff1a; 场景&#xff1a;提取字符串中的单词 假设我们需要编写一个函数&#xff0c;从一个句子中提取第一个单词。我们将分别展示 不用切片 和 使用切片 的实现&#xff0c;并对比二者的…

单机性能调优中的程序优化

目录 一、系统框架的选择 二、程序优化 表单压缩 局部刷新 仅取所需 逻辑清晰 谨慎继承 程序算法优化 批处理 延迟加载 防止内存泄漏 减少大对象引用 防止争用死锁 存储过程 内存分配 并行 异步 缓存 单机优化顾名思义就是我们要在单机上对系统的性能进行调优…

8.PPT:小李-第二次世界大战【21】

目录 NO123 ​ NO4567 ​ NO8\9\10\11​ 图片→格式→大小对话框→锁定纵横比✔动画→飞入→效果选项&#xff1a;方向/序列→开始→持续时间→延迟时间持续时间&#xff1a;1s延迟&#xff1a;0.5s音频剪切时间&#xff1a;0.5s&#xff1a;00:00.500自动换片时间设置&…

javaEE初阶————多线程初阶(1)

多线程初阶———— 1&#xff0c;认识线程 1.1 概念 1&#xff09;线程是什么 线程就是一个“执行流”&#xff0c;可以理解为程序执行的最小单位&#xff1b; 可以看成轻量级的进程&#xff1b; 2&#xff09;为啥要有线程 “并发编程” 的需要&#xff0c;但是我们不…

pytorch图神经网络处理图结构数据

人工智能例子汇总&#xff1a;AI常见的算法和例子-CSDN博客 图神经网络&#xff08;Graph Neural Networks&#xff0c;GNNs&#xff09;是一类能够处理图结构数据的深度学习模型。图结构数据由节点&#xff08;vertices&#xff09;和边&#xff08;edges&#xff09;组成&a…