虚拟化技术 — Libvirt 异构虚拟化管理组件

news2024/11/18 16:30:39

目录

文章目录

  • 目录
  • Libvirt
    • libvirt API 函数库
    • libvirtd Daemon
      • 软件架构
      • 权限模式
      • 运行模式
      • XML 格式
    • virsh CLI
  • Libvirt + QEMU-KVM 环境部署
    • HostOS 配置优化
    • (可选的)开启 KVM Nested 嵌套虚拟化
    • 安装 CentOS GNOME 图形界面
    • 安装 Libvirt + QEMU-KVM
  • Libvirt 的虚拟网络模式
    • (默认)Linux Bridge 虚拟网络方案
    • 1. vSwitch 使用 Bridge 模式
      • 在 HostOS 上配置虚拟机的桥接网络
        • 管理网桥
        • 局域网桥
    • 2. vSwitch 使用 NAT 模式
    • 3. vSwitch 使用 Routed 模式
    • 4. vSwitch 使用 Isolated 模式
    • (可选)使用 OvS 代替 Linux Bridge
  • Libvirt 的 Live Migration
    • 网络数据传输层
    • 控制层
    • KVM 的 Pre-Copy Live Migration 过程
    • 虚拟机迁移功能编程示例

Libvirt

Libvirt 是目前使用最为广泛的异构虚拟化管理工具,由 libvirt API 函数库、libvirtd Daemon 这 2 个关键部分组成,还具有一个默认命令行管理工具 virsh。

在这里插入图片描述

libvirt API 函数库

Libvirt 采用了面向驱动的架构设计,北向提供了统一的虚拟化资源管理 API,南向通过不同的驱动程序来对接异构的底层虚拟化技术。同时,libvirt API 为多种高级编程语言都提供了编程接口,包括 C、Python、Java、Perl、Ruby 等,具有非常强的可扩展性。

除了官方提供的多种管理工具之外(包括:virsh CLI、virt-manager、virt-viewer、vist-install ),OpenStack 也通过 libvirt API 提供的跨虚拟化平台能力,可以同时支持 QEMU-KVM、VMware、Xen 等多种虚拟化实现。

在这里插入图片描述

libvirtd Daemon

在这里插入图片描述

libvirtd Daemon 是一个 Multi-Drivers 软件架构,围绕虚拟机这一核心对象提供了计算、存储、网络、安全、监控等虚拟化资源的管理功能。

  • 虚拟机管理:用于创建、删除、修改、暂停、恢复、迁移和监视 VM。
  • 虚拟网络管理:用于创建、删除和修改虚拟网络,包括 Bridge/OvS、NAT、VLAN 网络。
  • 存储管理:用于管理 VM 的 QCOW2 镜像和虚拟磁盘,包括创建、删除、修改和查看存储卷。
  • 集群管理:用于管理多台运行了 libvirtd Daemon 的 Host Cluster 上的 VM,可以通过远程连接的方式进行管理。
  • 安全策略:用于控制对 Host 和 VM 的访问权限,防止未经授权的访问。
  • 监控和统计:用于获取 Host 和 VM 的状态信息和统计数据,包括 CPU 使用率、内存使用率、网络流量、磁盘 I/O 等。

软件架构

libvirtd 的软件架构包括了以下核心组件:

  1. 监听器(Listener):监听客户端连接请求。默认情况下,libvirtd 使用 TCP/IP 协议,并在本地主机上监听 16509 端口。
  2. 驱动程序(Driver):libvirtd 使用驱动程序来与不同的虚拟化技术交互。
  3. 数据库(DB):存储虚拟机相关的信息。默认情况下,libvirtd 使用 SQLite,也支持其他数据库,如:MySQL、PostgreSQL。

权限模式

为了保障 HostOS 的安全性,libvirtd 可以在 2 种权限模式下运行:

  1. 系统模式:libvirtd 以 Root 权限运行,可以使用 libvirtd 的完整功能,虚拟出物理主机的各种设备。
  2. 会话模式:libvirtd 以 Non-root 权限运行,以普通系统用户的身份运行。

运行模式

为了支持集群管理和虚拟机迁移功能,libvirtd 具有 2 种运行模式:

  1. 本地控制管理:Application 和 libvirtd 在同一个 Host 上。
  2. 远程控制管理:Application 和 libvirtd 不再同一个 Host 上。Local libvirtd 和 Remote libvirtd 之间可以使用 TCP over SSH 协议进行安全通信。

在这里插入图片描述

XML 格式

libvirtd 使用 XML 格式来保存一个 VM 所有的配置信息,下面是一个简单的示例:

<domain type='kvm'>
  <name>myvm</name>
  <memory unit='KiB'>1048576</memory>
  <vcpu placement='static'>2</vcpu>
  <os>
    <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
    <boot dev='hd'/>
  </os>
  <devices>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2'/>
      <source file='/var/lib/libvirt/images/myvm.qcow2'/>
      <target dev='vda' bus='virtio'/>
    </disk>
    <interface type='network'>
      <mac address='52:54:00:9b:08:fa'/>
      <source network='default'/>
      <model type='virtio'/>
    </interface>
  </devices>
</domain>
  • domain 根元素:其中,type=‘kvm’ 表示使用 KVM Hypervisor。
  • name 元素:指定 VM 的名称。
  • memory 元素:指定 VM 的 vMemory 大小,单位为 KiB。
  • vcpu 元素:指定 VM 的 vCPU 个数,其中,placement=‘static’ 表示静态分配方式。
  • os 元素:指定 VM 的操作系统类型和 boot 引导顺序。
  • devices 元素:指定 VM 的设备信息。
    • disk 元素:指定 VM 的 vDisk 信息,包括:类型、文件路径、磁盘编号、驱动程序等信息。
    • interface 元素:指定 VM 的 vNIC 信息,包括:虚拟网络、MAC 地址、驱动程序等信息。

virsh CLI

virsh list               # 查看在运行的虚拟机。
virsh list --all         # 查看所有虚拟机。
virsh console centos72   # 连接虚拟机的 Console。
virsh start centos72     # 启动虚拟机。
virsh reboot centos72    # 重新启动虚拟机。
virsh shutdown centos72  # 优雅关闭虚拟机。
virsh destroy centos72   # 强制关闭虚拟机。
virsh suspend centos72   # 暂停(挂起)虚拟机。
virsh resume centos72    # 恢复被挂起的虚拟机。
virsh undefine centos72  # 删除虚拟机的 XML 配置文件,但不删除虚拟机的磁盘文件。
virsh autostart centos72 # 设置虚拟机随物理机一同启动。
virsh autostart --disable centos72 # 取消虚拟机的开机自启动。
virsh dumpxml centos72   # 查看虚拟机的配置文件。
virsh edit centos72      # 编辑虚拟机的配置文件。
virsh setvcpus           # 动态配置虚拟机的 CPU。
virsh setmaxmem          # 动态配置虚拟机的 Memory。

Libvirt + QEMU-KVM 环境部署

HostOS 配置优化

  1. 使用国内 yum 和 epel 镜像源加速。
yum -y install wget

mkdir /etc/yum.repos.d/repo.bk
mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/repo.bk

wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo

yum clean all
yum makecache

yum install -y epel-release
  1. 升级 HostOS。
yum update -y && yum upgrade -y

(可选的)开启 KVM Nested 嵌套虚拟化

如果 HostOS 本身就是一个 VM,那么就需要开启 KVM Nested 嵌套虚拟化,使得 HostOS 能够具有与 Host 相同的 CPU 硬件辅助虚拟化特性,才能够在 VM 里面嵌套运行 KVM 虚拟机。

KVM Nested 是一个可通过修改内核参数来启用的功能,它能够使一台 VM 与 Host 可以具相同的 CPU 特性,支持 vmx|svm(AMD) 硬件虚拟化,该特性需要 Linux 内核版本大于 Linux 3.x。

查看是否启动了 Nested:

$ cat /sys/module/kvm_intel/parameters/nested
Y

启用 Nested:

echo 'options kvm_intel nested=1' >/etc/modprobe.d/kvm-nested.conf

# 卸载内核模块
modprobe -r kvm_intel

# 重新加载内核模块
modprobe kvm_intel

NOTE:如果无法重载内核模块,可以考虑直接重启。

如果希望已经存在的 KVM 虚拟机支持嵌套虚拟化,则需要重新编辑虚拟机的 XML 文件,修改其 CPU mode。

# 关机
$ virsh shutdown domain-xxx

# 编辑
$ virsh edit domain-xxx

<cpu mode='host-passthrough'>

# 开机
$ virsh start domain-xxx

登录入虚拟机检查是否有 CPU 穿透:

$ egrep '(vmx|svm)' /proc/cpuinfo
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl eagerfpu pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust smep erms xsaveopt

安装 CentOS GNOME 图形界面

$ yum groupinstall -y "X Window System"
$ yum groupinstall -y "GNOME Desktop" "Graphical Administration Tools" 

$ init 5

安装 Libvirt + QEMU-KVM

$ cat /proc/cpuinfo | egrep 'vmx|svm'

$ setenforce 0
$ sed -i 's/=enforcing/=disabled/g' /etc/selinux/config

$ systemctl disable firewalld.service && systemctl stop firewalld.service && systemctl status firewalld.service

$ yum install -y qemu-kvm libvirt virt-manager virt-install bridge-utils 

$ lsmod | grep kvm

# 修改 QEMU 配置,使 Root 用户有文件访问权限
$ vi /etc/libvirt/qemu.conf
...
user = "root"
group = "root"

$ systemctl start libvirtd && systemctl enable libvirtd && systemctl status libvirtd

相关安装包及其作用

  • qemu-kvm:QEMU 的 KVM 分支发行版软件程序,包含了 KVM Kernel Module 和基于 KVM 重构后的 QEMU 模拟器。
  • qemu-img:QCOW2 镜像文件命令行工具。
  • libvirt:Libvirt 软件程序,提供了一套虚拟化管理工具及 API。
  • libvirt-client:Libvirt 的客户端软件程序,最重要的功能之一就是在宿主机关机时可以通知虚拟机也进行关机。
  • virt-manager:基于 Libvirt 的 GUI 虚拟机管理软件程序。
  • virt-install:基于 Libvirt 的用于创建虚拟机的命令行工具。
  • libvirt-python:Libvirt 的 Pyhton API。
  • python-virtinst:一套 Python 实现的用于创建虚拟机的命令行工具和程序库。
  • virt-viewer:连接虚拟机 Console 的命令行工具。
  • virt-top:虚拟机资源使用情况查看命令行工具。
  • virt-clone:虚拟机克隆命令行工具。
  • libguestfs-tools:GuestOS File System 命令行工具。
  • bridge-utils:Linux Bridge 命令行工具。

Libvirt 的虚拟网络模式

(默认)Linux Bridge 虚拟网络方案

libvirtd Daemon 首次启动时,默认会为 VMs 创建一个 vSwitch,表现为一个名为 virbr0 的 Linux Bridge 设备,因为 Linux Bridge 设备是连接到 Linux Kernel TCP/IP stack 中的,所以可以通过查看 Network Interface 的方式来查看到。

并且,这个 vSwitch 默认运行在 NAT 模式下,使 VMs 可以访问外部网络。

在这里插入图片描述

1. vSwitch 使用 Bridge 模式

Bridge 模式,将 vSwitch 当作一个 L2 Switch 设备。使 VM 与 Host 处于同一个 LAN 网络,VM 和外部网络之间可以互相访问,外部网络都可以看见这些 VM。

Bridge 模式多用于高级设置,特别是 Host 多个网络接口的情况,将一个 Bridge 与物理网卡进行绑定。

在这里插入图片描述

其中,网桥模式是目前比较简单,也是用的比较多的模式,下图是网桥模式下的 VM 的收发包的流程。红色箭头表示数据报文的入方向,过程为:

  1. 网络数据从 Host pNIC 接收,到达网桥;
  2. 由于 eth0 与 tap1 均加入网桥中,根据二层转发原则,br0 将数据从 tap1 口转发出去,即数据由 Tap设备接收;
  3. Tap 设备通知对应的 fd 数据可读;
  4. fd 的读动作通过 tap 设备的字符设备驱动将数据拷贝到用户空间,完成数据报文的前端接收。

在这里插入图片描述

在 HostOS 上配置虚拟机的桥接网络

管理网桥

# 虚拟机管理网网桥 br-mgmt
$ vi /etc/sysconfig/network-scripts/ifcfg-br-mgmt
TYPE=Bridge
BOOTPROTO=static
ONBOOT=yes
DEFROUTE=yes
NAME=br-mgmt
DEVICE=br-mgmt
IPADDR=192.168.1.2
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
DNS1=114.114.114.114
DNS1=8.8.8.8

# 虚拟机管理网物理网卡,绑定到 br-mgmt
$ vi /etc/sysconfig/network-scripts/ifcfg-enp2s0
TYPE=Ethernet
BOOTPROTO=none
ONBOOT=yes
NAME=enp2s0
DEVICE=enp2s0
BRIDGE=br-mgmt 

$ systemctl restart network

$ ip a
...
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br-mgmt state UP group default qlen 1000
    link/ether 40:8d:5c:b8:25:4b brd ff:ff:ff:ff:ff:ff
...
7: br-mgmt: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 40:8d:5c:b8:25:4b brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.2/24 brd 192.168.1.255 scope global noprefixroute br-mgmt
       valid_lft forever preferred_lft forever
    inet6 fe80::428d:5cff:feb8:254b/64 scope link
       valid_lft forever preferred_lft forever

局域网桥

创建网桥设备:

$ brctl addbr br-lan01
$ brctl addbr br-lan02

配置网桥设备:

$ vi /etc/sysconfig/network-scripts/ifcfg-br-lan01
TYPE=Bridge
DEVICE=br-lan01
ONBOOT=yes
BOOTPROTO=static

$ vi /etc/sysconfig/network-scripts/ifcfg-br-lan02
TYPE=Bridge
DEVICE=br-lan02
ONBOOT=yes
BOOTPROTO=static

$ systemctl restart network

$ brctl show
bridge name	bridge id		STP enabled	interfaces
br-lan01		8000.000000000000	no
br-lan02		8000.000000000000	no
br-mgmt		8000.408d5cb8254b	no		enp2s0
virbr0		8000.525400088710	yes		virbr0-nic

使能网桥设备:

$ ifup br-lan01
$ ifup br-lan02

2. vSwitch 使用 NAT 模式

NAT 模式(默认)将 vSwitch 当作一个 Firewall NAT 设备。底层支撑使用了 iptables nat 的 MASQUERADE(地址伪装)规则类型,而非 SNAT 或 DNAT。IP 地址伪装规则,使得 VMs 可以使用 Host 的 IP 地址访问外部网络,但外部网络无法主动访问到 VMs,因为 VMs 对于外部网络而言是不可见的。

在这里插入图片描述

从下图可以看出,vSwitch virbr0 和物理接口之间是没有绑定关系的,而是使用了 Linux Kernel TCP/IP Stack 中的 netfilter 框架完成 NAT 转发。

┌───────────────────────┐                      
│         HOST          │                      
│ ┌──────┐              │   ┌─────────────────┐
│ │ br0  │─┬──────┐     │   │Virtual Machine 1│
│ └──────┘ │      │     │   │   ┌──────┐      │
│     │    │  ┌───────┐ │ ─ │   │ br0  │      │
│     │    │  │ vnet0 │─│┘  │   └──────┘      │
│ ┌──────┐ │  └───────┘ │   └─────────────────┘
│ │virbr0│ │  ┌───────┐ │   ┌─────────────────┐
│ │ -nic │ └──│ vnet1 │─│┐  │Virtual Machine 2│
│ └──────┘    └───────┘ │   │                 │
│ ┌──────┐              │└ ─│   ┌──────┐      │
│ │ eno0 │              │   │   │ br0  │      │
│ └──────┘              │   │   └──────┘      │
│ ┌──────┐              │   └─────────────────┘
│ │ eno1 │              │
│ └──────┘              │
└───────────────────────┘

另外,在 NAT 模式下,Host 内部的虚拟网络环境自成一套体系,所以可以考虑将 DNS 和 DHCP server 部署在 vSwitch 上,Libvirt 可以通过 dnsmasq 程序来实现。

在这里插入图片描述

3. vSwitch 使用 Routed 模式

路由模式,将 vSwitch 当作一个 L3 Router 设备,作为 VMs 的 default GW。路由模式中,所有 VMs 都处于一个 LAN 中,通过 vSwitch 来完成 L3 Routing,继而与外部网络进行通信。

值得注意的是,路由模式并不总是理想的,因为外部网络上的其他 Hosts 并不默认使用该 vSwitch,也就无法访问 VMs 了。

在这里插入图片描述

4. vSwitch 使用 Isolated 模式

隔离模式,vSwitch 不与外部网络进行互通。所以同一个 vSwitch 中的 VMs 可以互相访问,VMs 也可以访问 Host,但不能访问外部网络。

在这里插入图片描述

(可选)使用 OvS 代替 Linux Bridge

  1. 编辑 ovs-net XML 文件。
$ vi ovs-net.xml 
<network>
  <name>ovs-net</name>
  <forward mode="bridge"/>
  <bridge name="ovs-br0"/>
  <virtualport type="openvswitch"/>
</network>
  1. 创建 ovs-net 网桥,并添加一个 Physical NIC 作为 internal Interface。

  2. 创建 OvS Network,并删除 Default Linux Bridge Network。

virsh net-destory default
virsh net-define ovs-net.xml 
virsh net-start default
virsh net-autostart default
virsh net-list --all
  1. 使用 OvS Network 创建虚拟机。
$ virt-install \
	--virt-type kvm \
	--name vm01 \
	--ram 128 \
	--boot hd \
	--disk path=cirros.qcow2 \
	--network network=ovs-net,mac=52:54:00:aa:69:cc \
	--graphics vnc,listen=0.0.0.0 \
	--noautoconsole
  1. Libvirt 会自动的在 OvS Bridge 中添加 vnetX Ports。

Libvirt 的 Live Migration

Libvirt 的 Live Migration 主要分为两个层面

  1. 网络数据传输层面。
  2. 控制层面。

网络数据传输层

  1. 基于 Hypervisor 的传输,两个 Hypervisor 之间直接建立数据传输连接。优点:数据传输量少。缺点:需要额外配置 Hypervisor Network。需要在防火墙上面打开更多的端口来支持并发迁移,数据不一定支持加密(取决于 Hypervisor 实现)。
    在这里插入图片描述

  2. 基于 libvirtd Tunnel 的传输,源主机和目标主机上运行的 libvirtd 之间建立 RPC 隧道来传输数据。数据要先拷贝到 libvirtd,再由 libvirtd 中继到目标主机的 libvirtd。优点:不需要重新配置网络,防火墙上面只需要一个端口就可以支持并发迁移,数据强加密。缺点:相关的数据拷贝多,所有流量都通过一个端口,容易造成网络拥堵。
    在这里插入图片描述

在 Tunnel 传输模式下,同一份数据需要被拷贝多次,并且所有的流量都通过一个端口,在大内存、高业务(快速增加 RAM 脏数据)的场景下,同样的网络带宽,Tunnel 传输模式迁移速率较慢。因此,对于大内存、业务繁忙的场景下,首选基于 Hypervisor 的传输。

控制层

  1. Client 控制:由 Libvirt Client 直接控制迁移。Client 跟源主机 libvirtd 连接,也跟目的主机 libvirtd 连接,当目的主机迁移过程出现异常会反馈给 Client,再由 Client 通知源 libvirtd。整个过程,由 Client 主导控制。
    在这里插入图片描述

  2. 源主机 libvirtd 控制:由源主机 libvirtd 主导整个迁移过程。Client 仅作为迁移指令的发起者,将迁移指令异步发送给源主机 libvirtd。如果目的主机迁移过程出现异常会反馈给源主机 libvirtd。这种方式的好处是,Client 故障也不会影响到整个迁移过程。
    在这里插入图片描述

  3. Hypervisor 控制:有源主机 Hypervisor 控制整个迁移过程,Client 向源主机 Hypervisor 发送迁移指令,源主机和目的主机的 libvirtd 不参与控制。这种方式的前提是 Hypervisor 自身支持热迁移,好处在于 Client 和 libvirtd 的故障不会影响到整个迁移过程。
    在这里插入图片描述

KVM 的 Pre-Copy Live Migration 过程

Step 1. 系统验证目标服务器的存储器和网络设置是否正确,并预保留目标服务器虚拟机的资源。
在这里插入图片描述

Step 2. 当虚拟机还在源服务器上运转时,第一个循环内将全部内存镜像复制到目标服务器上。在这个过程中,KVM 依然会监视内存的任何变化。

在这里插入图片描述

Step 3. 以后的循环中,检查上一个循环中内存是否发生了变化。 假如发生了变化,那么 VMM 会将发生变化的内存页即 dirty pages 重新复制到目标服务器中,并覆盖掉先前的内存页。在这个阶段,VMM 依然会继续监视内存的变化情况。

在这里插入图片描述

Step 4. VMM 会持续这样的内存复制循环。随着循环次数的增加,所需要复制的 dirty pages 就会明显减少,而复制所耗费的时间就会逐渐变短,那么内存就有可能没有足够的时间发生变化。最后,当源服务器与目标服务器之间的差异达到一定标准时,内存复制操作才会结束,同时暂停源系统。

在这里插入图片描述

Step 5. 在源系统和目标系统都停机的情况下,将最后一个循环的 dirty-pages 和源系统设备的工作状态复制到目标服务器。

在这里插入图片描述

Step 6. 然后,将存储从源系统上解锁,并锁定在目标系统上。启动目标服务器,并与存储资源和网络资源相连接。

在这里插入图片描述

虚拟机迁移功能编程示例

import libvirt 
import pprint

conn_src = libvirt.open('qemu+tcp://username@src_server/system') 
conn_dest = libvirt.open('qemu+tcp://username@dest_server/system') 

vm_domain = conn_src.lookupByName('instance_name') 
vm_domain.migrate(conn_dest, True, 'instance_name', None, 0)

pprint.pprint(help(vm_domain.migrate))

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言ctype.h头文件中2类好用的库函数

本篇博客会讲解C语言ctype.h这个头文件中的2类好用的库函数&#xff0c;分别是字符分类函数和字符转换函数。 字符分类函数 字符分类函数&#xff0c;指的是判断一个字符是不是属于某个类别&#xff0c;如果属于这个类别&#xff0c;返回非0数&#xff1b;如果不属于这个类别…

性能测试工具 IxChariot:Tcl脚本调用方法介绍

ixChariot是一款功能强大的性能测试软件&#xff0c;可用来测试有线和无线性能&#xff0c;可以模拟真实应用程序流量&#xff0c;并提供关键性能指标&#xff0c;包括吞吐量、丢包、抖动、延迟、MOS等。本文简单介绍如何使用IxChariot Tcl API来实现自动化跑流。 目录 IxChari…

RK3399平台开发系列讲解(调试篇)断言的使用

🚀返回专栏总目录 文章目录 一、什么是断言二、静态断言三、运行时断言沉淀、分享、成长,让自己和他人都能有所收获!😄 📢断言为我们提供了一种可以静态或动态地检查程序在目标平台上整体状态的能力,与它相关的接口由头文件 assert.h 提供。 一、什么是断言 在编程中…

浏览器状态同步和路由-SSR和单页面应用的分析 【单页面应用和服务端渲染】

目录 单页面应用&#xff08;优缺点&#xff09;&#xff08;Single Page Application&#xff09; 优点&#xff1a; SPA的缺点&#xff1a; 服务端渲染&#xff08;Server Side Rendering&#xff09; SSR示例&#xff08;一个ssr小引擎&#xff09; SSR优缺点分析 总结…

Opencv+Python笔记(八)轮廓检测

目录 一、轮廓的检测和绘制1.读入图像2.将读入图像转化为灰度图3.对灰度图进行二值化 [图像的阈值化处理](https://blog.csdn.net/Ggs5s_/article/details/130301816?spm1001.2014.3001.5501)4.进行轮廓检测5.在原图中显示轮廓 二、轮廓层级关系1.RET_LIST2.RETR_EXTERNAL3. R…

座椅内饰如何「跟上」智能电动?这款智能概念座舱看到未来

进入智能电动汽车时代&#xff0c;理想的车内空间应该是怎样的&#xff1f;作为“内饰空间创造者”、全球三大汽车座椅及内饰厂商之一&#xff0c;丰田纺织在2023上海车展上给出了一系列解决方案。 4月19日&#xff0c;丰田纺织携诸多产品亮相本次上海车展&#xff0c;包括面向…

【速卖通】 AliExpress(速卖通)关键词搜索结果采集

采集场景 在AliExpress(速卖通) 首页中 http://www.aliexpress.com 中输入关键词&#xff0c;采集关键词搜索后得到的商品列表信息。 采集字段 关键词、标题、商品id、商品图片地址、商品详情链接、价格、免费退送货、星级、已出售数量、店铺名 采集结果 采集结果可导出为E…

C语言入门篇——函数篇

1、什么是函数 首先&#xff0c;什么是函数&#xff1f;函数(function)是完成特定任务的独立程序代码。单元语法规则定义了函数的结构和使用方式。虽然C中的函数和其他语言中的函数、子程序、过程作用相同&#xff0c;但是细节上略有不同。 为什么使用函数&#xff1f; 首先…

刷题训练2之AcWing第 96 场周赛

竞赛 - AcWing 一、完美数 4876. 完美数 - AcWing题库 1、题目 如果一个正整数能够被 2520 整除&#xff0c;则称该数为完美数。 给定一个正整数 n&#xff0c;请你计算 [1,n]范围内有多少个完美数。 输入格式 一个整数 n。 输出格式 一个整数&#xff0c;表示 [1,n] 范…

【社区图书馆】操作系统的经典书籍

操作系统的经典书籍 一、引言二、书籍的选择三、优缺点3.1、《操作系统》3.2、《计算机操作系统》 小结 一、引言 《操作系统》罗宇和《计算机操作系统》汤小丹这两本书都是关于操作系统的经典书籍&#xff0c;各有优势。 二、书籍的选择 首先&#xff0c;从内容深度上&…

倾斜摄影超大场景的三维模型的顶层合并常见的问题分析

倾斜摄影超大场景的三维模型的顶层合并常见的问题分析 倾斜摄影超大场景的三维模型顶层合并是将多个局部区域的点云或网格数据进行融合&#xff0c;生成一个整体的三维模型的过程。在这个过程中&#xff0c;常见的问题包括&#xff1a; 1、数据不一致。由于数据采集时间、空间…

SAP SM30表格维护生成器隐藏记录日志字段

1.背景 在表格维护生成器中往往会隐藏记录日志字段&#xff0c;不让用户直接查看&#xff0c;而供运维或者开发部门使用&#xff0c;如下所示&#xff1a; 2.实现 2.1 SM30逻辑流和屏幕元素中删除日志记录字段 2.2 创建事件&#xff0c;写入记录日志代码 2.2.1 记录日志方式…

Node.js使用CORS解决跨域问题的三种方法

目录 1、通过CORS中间键解决2、设置响应头3、app.all解决4、解决跨域问题案例 现如今&#xff0c;实现跨域数据请求&#xff0c;最主要的两种解决方案&#xff0c;分别是JSONP和CORS. JSONP:出现的早&#xff0c;兼容性好&#xff08;兼容低版本IE&#xff09;。是前端程序员为…

m1下利用dockerdesktop安装ELK

一、背景&#xff1a;公司有一个需求&#xff0c;就是将txt中的数据加载到es中&#xff0c;之前没用过es&#xff0c;想着先在本地安装一个&#xff0c;然后再做测试。 二、安装docker desktop 打开docker的官网&#xff0c;下载苹果芯片的docker 网址&#xff1a;https://ww…

当DevOps遇见AI,智能运维的黄金时代开启

文章目录 1. 当DevOps遇见AI&#xff0c;智能运维的黄金时代2. 什么是DevOpts&#xff1f;改变开发格局&#xff1a;测开、运开必然趋势3. 什么是Docker容器化&#xff0c;它会替代掉VM虚拟机吗&#xff1f;4. 运维的终点是开发5. 实际项目的部署案例6. 誉天程序员课程 1. 当De…

顶象推出应用隐私合规检测服务

为帮助开发者更高效地进行App隐私合规检测&#xff0c;顶象推出应用隐私合规检测服务&#xff0c;快速发现App可能存在的各类隐私安全漏洞&#xff0c;并提供详细的检测报告&#xff0c;给出专业的合规整改建议。该服务可应用于上架前和合规检测&#xff0c;通过个人信息保护分…

map<int,int>和map<int,int>::iterator

map< int,int >和map< int,int >::iterator 一、map<int,int>、map<string, string>的含义二、map<int,int>::iterator的作用三、map<int,XXX>的自动升序特点 一、map<int,int>、map<string, string>的含义 map容器是CSTL的一…

学成在线笔记+踩坑(7)——绑定媒资

导航&#xff1a; 【黑马Java笔记踩坑汇总】JavaSEJavaWebSSMSpringBoot瑞吉外卖SpringCloud黑马旅游谷粒商城学成在线牛客面试题 目录 8 绑定媒资 8.1 需求分析 8.1.1 业务流程 8.1.2 数据模型 8.2 接口定义 8.2.1 抽取模型类 8.2.2 定义接口层 8.3 接口开发 8.3.1…

23.4.21总结

正则表达式 正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串&#xff0c;通常被用来检索、替换那些符合某个模式&#xff08;规则&#xff09;的文本。 正则表达式是一种对字符串操作的一种逻辑公式&#xff0c;就是用事先定义好的一些特定字符、及这些…

【Java 数据结构】十大排序 (动图解析)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…