当前位置: 首页 > news >正文

K8S之网络深度剖析(一)(持续更新ing)

K8S之网络深度剖析

一 、关于K8S的网络模型

在K8s的世界上,IP是以Pod为单位进行分配的。一个Pod内部的所有容器共享一个网络堆栈(相当于一个网络命名空间,它们的IP地址、网络设备、配置等都是共享的)。按照这个网络原则抽象出来的为每个Pod都设置一个IP地址的模型也被称作为IP-per-Pod模型。

Kubernetes对集群网络有如下要求:

  • 所有容器都可以在不用NAT的方式下同别的容器通讯。
  • 所有节点都可以在不用NAT的方式下同别的容器通讯。
  • 容器的地址和别人看到的地址是同一个地址。

二、Docker 网络

Docker 使用到的与Linux网络有关的主要技术:

  • 网络命名空间(Network Namespace)
  • Veth 设备对
  • 网桥
  • Iptables
  • 路由

2.1 网络命名空间

为了支持网络协议栈中的多个实例,Linux 2.6.24内核版本的网络协议栈中引入了网络命名空间,这些独立的协议栈被隔离到不用的命名空间中。处于不用命名空间中的网络栈是完全隔离的,彼此之间无法通讯,就好像两个"平行宇宙"。通过对于网络资源的隔离,就能在一个宿主机上虚拟多个不同的网络环境。Docker 正是利用了网络的命名空间特性,实现了不同容器之间的网络隔离。

在Linux的网络命名空间中可以有自己独立的路由表,及独立的Iptables设置来提供包转发、NAT、及IP包过滤等功能。

为了隔离出独立的协议栈,需要纳入命名空间的元素有进程、套接字、网络设备等。进程创建的套接字必须属于某个网络命名空间,套接字的操作也必须在命名空间中进行。同样,网络设备也必须属于某个命名空间。因为网络设备属于公共资源,所以可以通过修改属性实现在命名空间之间移动。当然,是否允许移动,和设备的特征有关系。

2.1.1 网络命名空间的实现

Linux的网络协议栈是十分复杂的,为了支持独立的协议栈,相关的这些全局变量都必须被修改为协议栈私有,最好的办法就是让这些全局变量成为一个 Net NameSpace变量的成员,然后修改协议栈的函数调用,在加入一个NameSpace的参数,这就是Linux 实现网络命名空间的核心。

同时,为了保证对已经开发的应用程序,以及内核代码的兼容性,内核代码隐式地使用了网络命名空间中的变量,程序如果没有对网络命名空间有特殊需求,就不需要编写额外的代码,网络命名空间对应用程序而言是透明的。

在建立了新的网络命名空间,并将某个进程关联到这个网络命名空间后,就出现了如下图的数据结构,所有的网络栈变量都没放到了私有的命名空间,和其他进程组并不冲突。

在这里插入图片描述
上图来自网络命名空间深度好文

在新生成的理由命名空间中,只有回环设备,(名为"lo" 且是停止状态),其他设备默认都不存在,如果我们需要,则要一一手工建立,Docker容器中的各类网络栈设备都是Docker Daemon 在启动时自动创建和配置的。

所有的网络设备(物理的或虚拟接口、桥等在内核里都叫做Net Device)都只能属于一个命名空间、当然,物理设备(连接实际硬件的设备)通常只能关联到root 这个命名空间。虚拟的网络设备(虚拟的以太网接口或者虚拟网口对)则可以被关联到一个给定的命名空间,而且可以在这些命名空间中移动。

前面提到,由于网络命名空间代表的是一个独立的协议栈,所以它们之间是相互隔离的,彼此无法通讯,在协议栈内部都看不到对方, 那么有没有办法打破这种限制,让处于不同网络命名空间的网络互相通讯,甚至和外部的网络通讯呢? 答案就是“有”,应用 “Veth设备对即可”, Veth 设备对一个重要的作用就是打通互相看不到的协议栈的协议栈之间的壁垒,他就像一条管子,一端连着这个网络命名空间的协议栈,一端连着另一个网络命名空间协议栈,所以想要在两个命名空间之间通讯,就必须有一个 Veth 设备对。

2.1.2 网络命名空间的操作

我们可以使用 Linux iproute2 系列配置工具中的IP 命令来操作网络命名空间,注意: 这个命令需要使用root 用户来执行。

安装:

# alphine
apk add iproute2# ubuntu
sudo apt install iproute2# centos
sudo yum -y install iproute2

创建一个网络命名空间:

ip netns add <name>

创建一个名为test1 的网络命名空间

ip netns add test1

在命名空间中执行命令:

ip netns exec <name> <command>

在命名空间test1 执行 ip a s 命令

root@test:~# ip netns exec test1 ip a s
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

也可以先通过切换到对应的网络命名空间,执行各种命令:

ip netns exec <name> bash

执行 exit 或Ctrl +d 退出当前网络命名空间。
上面的操作相当于网络命名空间进行了切换,文件系统还是当前,在Docker 中,其实也做了类似操作,并且将文件系统通过chroot 进行了切换,通过cgroup 对资源进行了隔离。

2.1.3 网络命名空间的实用技巧

操作系统网络命名空间的一些技巧如下:

我们可以在不同的网络命名空间之间转移设备,列如下面会提到的Veth 设备对的转移,因为一个设备只能属于一个命名空间,所以转移后在这个网络命名空间内就看不到这个设备了,具体哪些设备能被转移到不同的网络命名空间, 在设备里面有一个属性: NETIF_F_NETNS_LOCAL,如果这个属性为 on,就不能被转移到其他命名空间中。Veth 设备属于可转移设备,而其他设备如,lo 设备,vxlan,ppp 设备,bridge设备等都是不可转移的。将无法转移的设备移动到别的命名空间时,会得到无效的参数错误提示。

root@test1:~# ip link set lo netns test1
RTNETLINK answers: Invalid argument

如何知道这些设备是否可以转移呢? 可以使用ethtool 工具查看:

root@test1:~#  apt install ethtool
root@test1:~# ethtool -k docker0  | grep netns
netns-local: on [fixed]
root@test1:~# ethtool -k veth276e185  | grep netns
netns-local: off [fixed]
2.1.4 使用nsenter 工具来切换网络命名空间

执行lsns 查看当前主机的namespace

root@test1:~# lsns NS TYPE   NPROCS     PID USER             COMMAND
4026531834 time      314       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531835 cgroup    312       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531836 pid       312       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531837 user      313       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531838 uts       308       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531839 ipc       312       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531840 net       308       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531841 mnt       297       1 root             /lib/systemd/systemd --system --deserialize 35 splash
4026531862 mnt         1      62 root             kdevtmpfs
4026532391 mnt         1     296 root             /lib/systemd/systemd-udevd
4026532392 uts         1     296 root             /lib/systemd/systemd-udevd
4026532421 mnt         1     471 systemd-resolve  /lib/systemd/systemd-resolved
4026532422 mnt         1     472 systemd-timesync /lib/systemd/systemd-timesyncd
4026532423 mnt         1 2540333 systemd-oom      /lib/systemd/systemd-oomd
4026532424 uts         1 2540333 systemd-oom      /lib/systemd/systemd-oomd
4026532425 uts         1     472 systemd-timesync /lib/systemd/systemd-timesyncd
4026532426 mnt         1   10214 root             /lib/systemd/systemd-logind
4026532427 uts         1   10214 root             /lib/systemd/systemd-logind
4026532430 mnt         1  995086 fwupd-refresh    /usr/bin/fwupdmgr refresh
4026532448 mnt         1 2435299 root             sh
4026532449 uts         1 2435299 root             sh
4026532450 ipc         1 2435299 root             sh
4026532451 pid         1 2435299 root             sh
4026532452 net         1 2435299 root             sh
4026532483 mnt         1   30455 root             /usr/libexec/accounts-daemon
4026532484 net         1   30455 root             /usr/libexec/accounts-daemon
4026532485 net         1   10330 rtkit            /usr/libexec/rtkit-daemon
4026532539 mnt         1     525 root             /usr/sbin/irqbalance --foreground
4026532542 mnt         2 1469053 root             /snap/snapd-desktop-integration/157/usr/bin/snapd-desktop-integration
4026532545 mnt         1   10629 root             /usr/libexec/upowerd
4026532546 mnt         1   10631 root             /usr/libexec/power-profiles-daemon
4026532547 user        1   10629 root             /usr/libexec/upowerd
4026532549 mnt         1   10715 root             /usr/sbin/ModemManager
4026532628 cgroup      1 2435299 root             sh
4026532631 mnt         1  380128 root             sh
4026532632 uts         1  380128 root             sh
4026532633 ipc         1  380128 root             sh
4026532634 pid         1  380128 root             sh
4026532635 net         3  380128 root             sh
4026532665 mnt         1   11076 colord           /usr/libexec/colord
4026532692 cgroup      1  380128 root             sh

这里可以看到pid 380128 容器的namespace,主要为以下几个类型:

  • mount
  • uts
  • ipc
  • pid
  • network
  • user

我们可以通过如下的方法对容器进行抓包:
获取容器的Pid

root@test1:~# docker inspect  -f "{{.State.Pid}}" a19dee489a47 
380128

可以看到有多个namespace

ls -l /proc/380128/ns/
total 0
lrwxrwxrwx 1 root root 0  7月  2 22:19 cgroup -> 'cgroup:[4026532692]'
lrwxrwxrwx 1 root root 0  7月  2 22:19 ipc -> 'ipc:[4026532633]'
lrwxrwxrwx 1 root root 0  7月  2 22:19 mnt -> 'mnt:[4026532631]'
lrwxrwxrwx 1 root root 0  6月 28 15:56 net -> 'net:[4026532635]'
lrwxrwxrwx 1 root root 0  7月  2 22:19 pid -> 'pid:[4026532634]'
lrwxrwxrwx 1 root root 0  7月  2 22:21 pid_for_children -> 'pid:[4026532634]'
lrwxrwxrwx 1 root root 0  7月  2 22:19 time -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0  7月  2 22:21 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx 1 root root 0  7月  2 22:19 user -> 'user:[4026531837]'
lrwxrwxrwx 1 root root 0  7月  2 22:19 uts -> 'uts:[4026532632]'

进入对应Pid 的Network Namespace

root@test1:~# nsenter -t 380128 -n 
root@test1:~# ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
76: eth0@if77: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0valid_lft forever preferred_lft forever

nsenter 工具详解及 namespace 背景

2.2 Veth 设备对

Veth设备对的出现是为了解决不同的网络命名空间之间通讯,利用它可以将两个网络命名空间进行连接,由于要连接多个网络命名空间,所以Veth 设备基本都是成对出现的,很像一对以太网卡,并且中间有一根直连的网线。既然是一对网卡,我们将其中一端称之为另一端的peer。在veth 另一端发送数据时,它会将数据直接发送到另一端,并触发另一端的接收操作。

veth设备示意图

2.2.1 Veth 设备对的操作命令

创建veth设备对:

root@test1:~# ip link add veth0 type veth peer name veth1

创建后,使用ip link show 查看所有网络接口

root@test1:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000link/ether 2e:8d:36:b4:77:40 brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default link/ether 02:42:ae:2b:65:9a brd ff:ff:ff:ff:ff:ff
69: veth9b5ea1d@if68: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether 7e:29:46:4f:52:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0
77: veth276e185@if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether 0e:73:3e:73:b5:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 1
82: veth1@veth0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/ether 6e:3b:cf:dc:10:a6 brd ff:ff:ff:ff:ff:ff
83: veth0@veth1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/ether da:61:bf:d0:bf:25 brd ff:ff:ff:ff:ff:ff

可以看到,上面的命令生成了两个网络接口 一个是veth1 他的peer 是veth0,现在两个设备都在默认的命名空间,我们将其中一个设备加入到另一个命名空间

root@test1:~# ip link set veth1 netns test1

这时在外面看两个设备的情况

root@test1:~# ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp6s18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000link/ether 2e:8d:36:b4:77:40 brd ff:ff:ff:ff:ff:ff
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default link/ether 02:42:ae:2b:65:9a brd ff:ff:ff:ff:ff:ff
69: veth9b5ea1d@if68: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether 7e:29:46:4f:52:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0
77: veth276e185@if76: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT group default link/ether 0e:73:3e:73:b5:b3 brd ff:ff:ff:ff:ff:ff link-netnsid 1
83: veth0@if82: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/ether da:61:bf:d0:bf:25 brd ff:ff:ff:ff:ff:ff link-netns test1

只剩下一个veth 设备了,已经看不到另一个设备了,另一个设备已经被转移到了test1的网络命名空间中了。

在test1的网络命名空间中可以看到veth1 设备,符合预期

root@test1:~# ip netns exec test1 ip link show
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
82: veth1@if83: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/ether 6e:3b:cf:dc:10:a6 brd ff:ff:ff:ff:ff:ff link-netnsid 0

现在我们看到,两个不用的命名空间中有一个veth 设备,在Docker的实现里面,它除了将veth 放入到容器内,还将它的名字改成了eth0

现在我们给他分配一个IP地址,让他们可以通讯

root@test1:~# ip netns exec test1 ip addr add 10.1.1.1/24 dev veth1
root@test1:~# ip addr add 10.1.1.2/24 dev veth0

在启动他们:

root@test1:~# ip netns exec test1 ip link set dev veth1 up
root@test1:~# ip link set dev veth0 up

现在两个网络命名空间可以互相通讯了

root@test1:~# ping 10.1.1.1 
PING 10.1.1.1 (10.1.1.1) 56(84) bytes of data.
64 bytes from 10.1.1.1: icmp_seq=1 ttl=64 time=0.074 ms
64 bytes from 10.1.1.1: icmp_seq=2 ttl=64 time=0.064 ms
root@test1:~# ip netns exec test1  ping 10.1.1.2
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.130 ms

在Docker内部,Veth 设备是连通容器与宿主机网络的主要设备。

2.2.2 veth 设备如何查看对端

一旦将veth 设备对的另一端放入另一个命名空间,在本命名空间就看不到它了,那我们如何知道设备的对端在哪里呢?可以使用ethtool 工具来查看(当网络命名空间较多时,这个也不太容器)。

首先,在命名空间test1中查询Veth设备对端接口在设备列表中的序列号:

root@test1:~# ip netns exec test1 ethtool -S veth1
NIC statistics:peer_ifindex: 83

获取另一端的接口序列号是83,我们在查看序列号83是什么设备

root@test1:~# ip link | grep 83
83: veth0@if82: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000

veth 参考资料

2.3 网桥

Linux可以支持多个不同的网络,他们之间可以相互通讯,如何将这些网络连接起来,并实现各网络中主机的相互通讯? 可以用网桥,网桥是一个二层的虚拟网络设备,把若干个网络接口”连接“起来,使得网络接口之间得报文能够互相转发,网桥能够解析收发得报文,读取目标MAC地址得信息,和自己记录得Mac表结合,来决策报文的转发目标网络接口,为了实现这些功能,网桥会学习源MAC地址(二层网桥转发得依据就是MAC地址),在转发报文时,网桥只需要向特定得网口进行转发,来避免不必要得网络交互,如果他遇到一个自己从未学习过得地址,就无法知道这个报文需要转发给哪个网络接口,就将报文广播给所有得网络接口(报文来源得接口除外)。

在实际得网络中,网络拓扑不可能永远不变,设备如果被移动到另一个端口上,却没有发送任何数据,网桥设备就无法感知这个变化,网桥还是向原来得端口转发数据时,这种情况数据就会丢失。所以网桥还要对学习到的MAC地址表加上超时时间(默认为5min)。如果网桥收到了对应带你看MAC地址回发的数据包,则重置超时时间,否则过了超时时间后,就认为设备已经不再那个端口上,它就会重新发送广播。

Linux内核支持网口的桥接(目前只支持以太网接口),但是与单纯的交换机不同,交换机只是一个二层设备,对于接收到的报文,要么转发,要么丢弃.运行着Linux 内核的机器本身就是一台主机,有可能时网络报文的目的地,其收到的报文除了转发和丢弃,还有可能会被送到网络协议栈的上层(网络层),从而被自己(这台主机本身的协议栈)消化,所以我们既可以把他当作一个二层设备,也可以当作一个三层设备。

2.3.1 Linux 网桥的实现

Linux 内核是通过一个虚拟的网桥设备(Net Device)来实现桥接的。这个虚拟设备可以绑定若干个以太网接口设备,从而将它们桥接起来, Net Device 和普通的设备,最明显的特征是它还可以有一个IP地址。
在这里插入图片描述
网桥的参考资料
如图所示,网桥设备绑定了 veth0 ,veth1。对于网络协议栈的上层来说,只看得到网桥就可以。因为桥接实在数据链路层实现的,上层不需要关心桥接的细节,所以协议栈上层需要发送的报文被送到 网桥,网桥设备判断报文是被转发到 veth0还是 veth1,或者两者皆转发,反过来从eth0 或从eth1 接收到的报文被提交给网桥的,在这里会判断应该被转发、丢弃、还是协议栈上层。

而有时,veth0,veth1 也可能作为报文的源地址或者目的地址,直接参与报文的发送与接收,从而绕过网桥

2.3.2 网桥的常用操作命令

Docker自动完成了对网桥的创建和维护。为了进一步理解网桥,下面举几个常用的网桥的例子,对网桥进行手工操作:

bridge-utils包中的 brctl 用来管理以太网桥,在内核中建立、维护、检查网桥配置。一个网桥一般用来连接多个不同的网络,这样这些不同的网络就可以像一个网络那样进行通讯。

网桥是一种在链路层实现中继,对帧进行转发的技术,根据MAC分区块,可隔离碰撞,将网络的多个网段在数据链路层连接起来的网络设备。网桥工作在数据链路层,将两个LAN连起来,根据MAC地址来转发帧,可以看作一个“底层的路由器”。

在网桥上每个以太网连接可以对应到一个物理接口,这些以太网接口组合成一个大的逻辑的接口,这个逻辑接口对应于桥接网络。

root@test1:~# apt-get install bridge-utils -y 

相关文章:

K8S之网络深度剖析(一)(持续更新ing)

K8S之网络深度剖析 一 、关于K8S的网络模型 在K8s的世界上,IP是以Pod为单位进行分配的。一个Pod内部的所有容器共享一个网络堆栈(相当于一个网络命名空间,它们的IP地址、网络设备、配置等都是共享的)。按照这个网络原则抽象出来的为每个Pod都设置一个IP地址的模型也被称作为I…...

Land survey boundary report (template)

Land survey boundary report (template) 土地勘测定界报告&#xff08;模板&#xff09;.doc...

[数据集][目标检测]婴儿状态睡觉哭泣检测数据集VOC+YOLO格式7109张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;7109 标注数量(xml文件个数)&#xff1a;7109 标注数量(txt文件个数)&#xff1a;7109 标注…...

深入解析 MySQL 的 SHOW FULL PROCESSLIST

在数据库管理中&#xff0c;监控和理解数据库进程是至关重要的。MySQL 提供了 SHOW PROCESSLIST 命令&#xff0c;它允许管理员查看当前所有活动线程的列表&#xff0c;包括它们的状态、执行的命令、消耗的资源等。这不仅帮助我们了解数据库的运行情况&#xff0c;还可以用于性…...

IPsec连接 和 SSL连接

Psec和SSL连接是两种用于保障网络通信安全的技术 IPsec 通常用于连通两个局域网&#xff0c;主要是网对网的连接&#xff0c;如分支机构与总部之间&#xff0c;或者本地IDC与云端VPC的子网连接。适合站点间的稳定通讯需求以及对网络层安全有严格要求的场合。要求两端有固定的网…...

Redis【超详细】

Redis 是一个基于内存的key-value结构的数据库 一、redis的安装 1.1、安装步骤 1&#xff09;安装Redis依赖 Redis是基于c语言编写的&#xff0c;因此需要安装对应的gcc环境 yum install -y gcc tcl 2&#xff09;进入/usr/local/src/目录上传并解压安装包 解压&#xf…...

通过ip获取用户位置信息以及地区时间

项目需要获取用户得位置信息以及地区时间&#xff0c;因为第一次搞&#xff0c;以防还有下次&#xff0c;特此记录 1.首先就是显得拿到用户得ip地址 先上代码&#xff1a; public boolean checkIp(String ip) {return null ip || ip.isEmpty() || "unknown".equa…...

pytest-yaml-sanmu(七):使用fixture返回值

fixture 是 pytest 中非常重要的功能&#xff0c;大部分项目都可能会用到 fixture。 pytest 的内置标记 usefixtures 可以帮助用例自动的使用 fixture 1. 创建 fixture pytest 中的 fixtures 大致有两个用途 在用例执行之前、执行之后&#xff0c;自动的执行 通过 fixture …...

2024最全软件测试面试八股文(答案+文档+视频讲解)

Part1 1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自…...

EasyBoss ERP移动端上线数据分析模块,随时查Shopee/TikTok本土店数据

前段时间&#xff0c;EasyBoss ERP出了个超酷炫的数字大屏功能&#xff0c;广受好评。 但是也有老板说&#xff0c;电脑端看数据不够方便啊&#xff0c;你们EasyBoss有本事上个手机就能看数据的功能啊&#xff01; 说干就干&#xff0c;直接满足你们的需求&#xff01; 于是在…...

机器学习与AI大数据的融合:开启智能新时代

在当今这个信息爆炸的时代&#xff0c;大数据和人工智能&#xff08;AI&#xff09;已经成为推动社会进步的强大引擎。作为AI核心技术之一的机器学习&#xff08;Machine Learning, ML&#xff09;&#xff0c;与大数据的深度融合正引领着一场前所未有的科技革命&#xff0c;不…...

视频监控业务平台LntonCVS国标视频综合管理平台功能及技术优势

随着安防行业的快速进步&#xff0c;传统的视频监控平台正在与先进的技术和互联网技术融合&#xff0c;包括5G通信、GIS、大数据、云计算、边缘计算、AI识别、智能分析和视频直播等。这些技术的整合形成了综合性视频监控管理平台&#xff0c;具备集中管理、多级联网共享、互联互…...

Python面试宝典第6题:有效的括号

题目 给定一个只包括 (、)、{、}、[、] 这些字符的字符串&#xff0c;判断该字符串是否有效。有效字符串需要满足以下的条件。 1、左括号必须用相同类型的右括号闭合。 2、左括号必须以正确的顺序闭合。 3、每个右括号都有一个对应的相同类型的左括号。 注意&#xff1a;空字符…...

Windows上使用Navicat连接ubuntu上的mysql8报错:10061和1130

问题一&#xff1a;can’t connect to mysql server on ‘192.168.xxx.xxx’(10061) 解决&#xff1a; sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf&#xff0c;bind-address绑定了登陆的IP&#xff0c;把这两行代码注释掉&#xff0c;然后重启mysql。 问题二&#xff1a;1…...

Feign远程调用,请求头丢失情况

现象 解决方案 import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.context.request.RequestContextHolde…...

Windows 11 安装 安卓子系统 (WSA)

How to Install Windows Subsystem for Android (WSA) on Windows 11 新手教程&#xff1a;如何安装Windows 11 安卓子系统 说明 Windows Subsystem for Android 或 WSA 是由 Hyper-V 提供支持的虚拟机&#xff0c;可在 Windows 11 操作系统上运行 Android 应用程序。虽然它需…...

CD4017 – 带解码输出的十进制计数器

CD4017 IC 是一个十进制计数器&#xff0c;它有 10 个输出&#xff0c;分别代表 0 到 9 的数字。计数器在&#xff08;14号引脚&#xff09;每个时钟脉冲上升时增加 1。计数器达到 9 后&#xff0c;它会在下一个时钟脉冲时从 0 重新开始。 引脚名称管脚 &#xff03;类型描述VD…...

Spring Boot 文件上传和下载指南:从基础到进阶

文章目录 引言1. 环境配置2. 文件上传2.1 配置文件上传路径2.2 创建上传服务2.3 创建上传控制器 3. 文件下载3.1 创建下载服务3.2 创建下载控制器 4. 前端页面4.1 文件上传页面4.2 文件下载页面 5. 技术分析结论 &#x1f389;欢迎来到SpringBoot框架学习专栏~ ☆* o(≧▽≦)o …...

Windows Server 2019部署网络负载均衡NLB服务的详细操作步骤

部署前准备 首先需要准备两台Windows Server 2019服务器&#xff0c;虚拟机创建请参考 VMware Workstation安装Windows Server2019系统详细操作步骤_安装windows server 2019操作系统(写出操作过程)-CSDN博客 克隆虚拟机请参考 VMware Workstation克隆虚拟机详细步骤-CSDN博…...

Java增加线程后kafka仍然消费很慢

文章目录 一、问题分析二、控制kafka消费速度属性三、案例描述 一、问题分析 Java增加线程通常是为了提高程序的并发处理能力&#xff0c;但如果Kafka仍然消费很慢&#xff0c;可能的原因有&#xff1a; 网络延迟较大&#xff1a;如果网络延迟较大&#xff0c;即使开启了多线…...

分布式事务实现技术及考虑点

什么是分布式事务&#xff1f; 首先理解什么是本地事务 平时我们在程序中通过Spring去控制事务是利用数据库本身的事务特性来实现的&#xff0c;因此叫数据库事务&#xff0c;由于应用主要靠关系数据库来控制事务&#xff0c;而数据库通常和应用在同一个服务器&#xff0c;所…...

JavaScript中闭包的理解

闭包&#xff08;Closure&#xff09;概念&#xff1a;一个函数对周围状态的引用捆绑在一起&#xff0c;内层函数中访问到其外层函数的作用域。简单来说;闭包内层函数引用外层函数的变量&#xff0c;如下图&#xff1a; 外层在使用一个函数包裹住闭包是对变量的保护&#xff0c…...

传统IO和NIO文件拷贝过程

参考&#xff1a;https://blog.csdn.net/weixin_57323780/article/details/130250582...

算法思想总结:优先级队列

一、最后一块石头的重量 . - 力扣&#xff08;LeetCode&#xff09; 我们每次都要快速找到前两个最大的石头进行抵消&#xff0c;这个时候用优先级队列&#xff08;建大堆&#xff09;,不断取堆顶元素是最好的&#xff01;每次删除堆顶元素后&#xff0c;可以自动调整&#xf…...

《米小圈日记魔法》边看边学,轻松掌握写日记的魔法!

在当今充满数字化娱乐和信息快速变迁的时代&#xff0c;如何创新引导孩子们学习&#xff0c;特别是如何培养他们的写作能力&#xff0c;一直是家长和教育者们关注的焦点。今天就向大家推荐一部寓教于乐的动画片《米小圈日记魔法》&#xff0c;该系列动画通过其独特的故事情节和…...

鸿蒙应用实践:利用扣子API开发起床文案生成器

前言 扣子是一个新一代 AI 应用开发平台&#xff0c;无需编程基础即可快速搭建基于大模型的 Bot&#xff0c;并发布到各个渠道。平台优势包括无限拓展的能力集&#xff08;内置和自定义插件&#xff09;、丰富的数据源&#xff08;支持多种数据格式和上传方式&#xff09;、持…...

二手物品交易小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;管理员管理&#xff0c;商品信息管理&#xff0c;论坛管理&#xff0c;收货地址管理&#xff0c;基础数据管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;商品信息&…...

基于Spring Boot的高校智慧采购系统

1 项目介绍 1.1 摘要 随着信息技术与网络技术的迅猛发展&#xff0c;人类社会已跨入全新信息化纪元。传统的管理手段因其内在局限&#xff0c;在处理海量信息资源时日渐捉襟见肘&#xff0c;难以匹配不断提升的信息管理效率和便捷化需求。顺应时代发展趋势&#xff0c;各类先…...

数字流的秩

题目链接 数字流的秩 题目描述 注意点 x < 50000 解答思路 可以使用二叉搜索树存储出现的次数以及数字的出现次数&#xff0c;方便后续统计数字x的秩关键在于构建树的过程&#xff0c;如果树中已经有值为x的节点&#xff0c;需要将该节点对应的数字出现次数加1&#xf…...

【mybatis】mybatis-plus中Wrapper(条件构造器)简介_常用方法及说明

1、简介 MyBatis-Plus 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。MyBatis-Plus 提供了强大的条件构造器&#xff08;Wrapper&#xff09;&#xff0c;用于构建复杂的 SQL 查询条件&#xff0c;使得我们…...

IT专业入门:高考假期预习指南

七月&#xff0c;是一个充满转折与希望的月份。随着各省高考分数的揭晓&#xff0c;许多有志于踏入IT领域的少年们正站在新旅程的起点上。高考的完结并不意味着学习的结束&#xff0c;相反&#xff0c;它是一个全新的开始&#xff0c;一个探索未知世界的绝佳时机。作为IT领域的…...

推动高效能:东芝TB67H301FTG全桥直流电机驱动IC

在如今高度自动化的时代&#xff0c;电子产品的性能和效率成为了工程师们关注的焦点。东芝的TB67H301FTG全桥直流电机驱动IC应运而生&#xff0c;以其卓越的技术和可靠性&#xff0c;成为众多应用的理想选择。无论是在机器人、家用电器、工业自动化&#xff0c;还是在其他需要精…...

Matplotlib 中文显示

Matplotlib 中文显示 Matplotlib 是一个强大的 Python 绘图库,广泛应用于数据可视化领域。然而,对于中文用户来说,Matplotlib 的默认设置可能不支持中文显示,这给使用带来了一定的不便。本文将详细介绍如何在 Matplotlib 中正确显示中文,包括中文字符的字体选择、字体大小…...

【LeetCode:841. 钥匙和房间 + DFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…...

1)并发事务的问题

1) 并发事务的问题&#xff1f; &#xff08;1&#xff09;读“脏”数据 事务T1修改数据后T2读取了该数据&#xff0c;但是T1撤消了修改&#xff0c; 事务T1进行了回滚&#xff0c;导致事务T2读取的数据与数据库中的数据不一致。&#xff08;2&#xff09;丢失修改 两个事务…...

Python缓存利器:cachetools库详解

Python缓存利器:cachetools库详解 1. cachetools简介2. 安装3. 基本概念3.1 LRU Cache (Least Recently Used)3.2 TTL Cache (Time-To-Live)3.3 LFU Cache (Least Frequently Used) 4. 使用示例4.1 使用LRU Cache4.2 使用TTL Cache4.3 使用LFU Cache4.4 缓存装饰器 5. 进阶用法…...

【Python实战因果推断】20_线性回归的不合理效果10

目录 Neutral Controls Noise Inducing Control Feature Selection: A Bias-Variance Trade-Off Neutral Controls 现在&#xff0c;您可能已经对回归如何调整混杂变量有了一定的了解。如果您想知道干预 T 对 Y 的影响&#xff0c;同时调整混杂变量 X&#xff0c;您所要做的…...

在Ubuntu 16.04上安装和配置ownCloud的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 ownCloud 是一个文件共享服务器&#xff0c;允许您将个人内容&#xff08;如文档和图片&#xff09;存储在一个类似 Dropbox 的集…...

Java | Leetcode Java题解之第213题打家劫舍II

题目&#xff1a; 题解&#xff1a; class Solution {public int rob(int[] nums) {int length nums.length;if (length 1) {return nums[0];} else if (length 2) {return Math.max(nums[0], nums[1]);}return Math.max(robRange(nums, 0, length - 2), robRange(nums, 1,…...

使用 ESP32 接收 MAX4466 模拟麦克风模块的数据,通过 DAC 转码成 PCM 格式,并通过 MQTT 发送给另一台设备,可以通过以下步骤实现。

硬件准备 两个 ESP32 开发板MAX4466 模拟麦克风模块MQTT 服务器&#xff08;例如 Mosquitto&#xff09; 接线 MAX4466 模块输出&#xff08;AO&#xff09; -> ESP32 ADC 引脚&#xff08;如 GPIO 34&#xff09; 软件准备 音频采集DAC 转码MQTT 发送和接收 代码实现…...

SQL二次注入原理分析

二次注入在测试的时候比较少见&#xff0c;或者说很难被测出来&#xff0c;因为测的时候首先要去找注入的位置&#xff0c;其次是去判断第一次执行的SQL语句&#xff0c;然后还要去判断第二次进行调用的 SQL 语句。而关键问题就出在第二次的调用上面。 下面以一个常用过滤方法…...

在线签约如何选择?2024年10款顶级app大比拼

支持电子合同签约的10大app&#xff1a;e签宝、上上签、DocuSign、契约锁、Adobe Sign、法大大、SignNow、安心签、HelloSign、PandaDoc。 无论是企业之间的交易还是个人服务合同&#xff0c;线上电子合同签约提供了一种便捷、高效且安全的方式来处理法律文档。本文将介绍几款优…...

gcc: warning: -Wunused-function;加了选项,为什么就不报警告呢?

文章目录 问题clang的编译而使用gcc是就不报问题分析原因如果是非static的函数问题 下面这个代码段,其中这个函数hton_ext_2byte,在整个程序里就没有使用。 static inline uint16_t hton_ext_2byte(uint8_t **p) {uint16_t v;******return v;...

系统提示我未定义与 ‘double‘ 类型的输入参数相对应的函数 ‘finverse‘,如何解决?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…...

【电路笔记】-B类放大器

B类放大器 文章目录 B类放大器1、概述2、B类放大器介绍3、推挽式配置4、限制交叉失真5、B类放大器效率6、总结1、概述 我们在之前的文章中已经知道,A 类放大器的特点是导通角为 360,理论最大效率为 50%。 在本文中,我们将详细介绍另一类放大器,称为B类放大器,它是为解决A…...

Ubuntu 22.04 安装中文字体

笔者在用OpenCV4.9处理图片加水印时&#xff0c;中文乱码。原来是Ubuntu 22.04发行版缺少中文字体支持&#xff0c;因此&#xff0c;笔者就找资料安装了需要的中文字体&#xff0c;特此记录&#xff0c;以备后查。 1、打开终端&#xff1a; 2、更新软件包列表&#xff1a; su…...

「树莓派入门」树莓派进阶04-直流电机控制与PWM应用

直流电机控制是树莓派硬件项目中的一项重要技能。通过PWM技术,你可以实现对电机速度的精确控制。在实验过程中,请注意电机的电源匹配和GPIO引脚的保护。 一、直流电机基本原理 直流电机通过直流电源供电,其工作原理基于洛伦兹力定律,即电流通过线圈时,会在磁场中受到力的…...

利用数据集,用机器学习模型对股市预测,聊聊看!

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…...

015-GeoGebra基础篇-定点旋转物体、动态显示数值并显示运动轨迹

这可能是我能想到的最大概率可以被你搜索到的标题了&#xff0c;容我先喘口气~ 目录 一、成品展示二、涉及内容三、做图步骤&#xff08;1&#xff09;绘制三角形t&#xff08;2&#xff09;建立定点D&#xff08;3&#xff09;制作角度滑动条&#xff08;4&#xff09;图形绕点…...

2024年6月份找工作和面试总结

转眼间6月份已经过完了&#xff0c;2024年已经过了一半&#xff0c;希望大家都找到了合适的工作。 本人前段时间写了5月份找工作的情况&#xff0c;请查看2024年5月份面试总结-CSDN博客 但是后续写的总结被和谐了&#xff0c;不知道这篇文章能不能发出来。 1、6月份面试机会依…...