Linux network namespace 访问外网以及多命名空间通信(经典容器组网 veth pair + bridge 模式认知)

写在前面


  • 整理K8s网络相关笔记
  • 博文内容涉及 Linux network namespace 访问外网方案 Demo
  • 实际上也就是 经典容器组网 veth pair + bridge 模式
  • 理解不足小伙伴帮忙指正

不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候,眼前的风景已经和从前不一样了。——村上春树


关于什么是 Linux network namespace ,小伙伴可以看我之前的文章,这里不多介绍

我们知道从 Linux network namespace 发包到因特网是无法通信,所以我们需要一些魔法(Linux bridge 桥接设备)

同时两个 network namespace 可以通过 veth pair 虚拟网卡对连接,但要做到两个以上 network namespace 相互连接,veth pair 就显得捉襟见肘了,这里我们也需要 Linux bridge 桥接设备实现多网络命名空间通信

Linux bridge 就是 Linux 系统中的网桥,但是Linux bridge 的行为更像是一台虚拟的 网络交换机,任意的真实物理设备(例如 eth0)虚拟设备(例如,前面讲到的veth pair以及 tap设备)都可以连接到 Linux bridge 上。但是需要注意的是,Linux bridge 不能跨机连接网络设备.

Linux bridge 与 Linux上其他网络设备的区别在于,普通的网络设备只有两端,从一端进来的数据会从另一端出去。例如,物理网卡从外面网络中收到的数据会转发给内核协议栈,而从协议栈过来的数据会转发到外面的物理网络中。

Linux bridge则有多个端口,数据可以从任何端口进来,进来之后从哪个口出去取决于目的MAC地址,原理和物理交换机差不多。

Linux network namespace 访问外网 配置

我们看一个实际的 Demo,使用Linux内部网桥实用程序创建网桥(vnet-br0),创建红色绿色两个网络名称空间。为redgreen命名空间创建两个veth虚拟网卡对,将veth对的一端连接到特定的命名空间,另一端连接到内部网桥,确保红色绿色命名空间中的接口可以于网桥(vnet-bro)与内部和外部网络通信。

创建两个网络命名空间,创建网桥vnet-br0

┌──[root@liruilongs.github.io]-[~]
└─$ip netns list
┌──[root@liruilongs.github.io]-[~]
└─$ip netns add red
┌──[root@liruilongs.github.io]-[~]
└─$ip netns add green

用于在 Linux 上创建一个名为 vnet-br0桥接设备桥接设备是用于连接多个网络设备的虚拟设备。它可以实现数据包的转发和交换,使得连接到桥接设备的网络设备可以相互通信。

┌──[root@liruilongs.github.io]-[~]
└─$ip link add vnet-br0 type bridge

创建桥接设备后,可以将其他网络设备(如物理网卡、虚拟网卡等)添加到桥接设备上,将它们连接在同一个逻辑网络中,实现数据的转发和交换

桥接设备(Bridge Device)是在网络层次结构中工作的二层设备(Data Link Layer),它主要用于连接多个网络设备,类似于网络交换机的功能。桥接设备通过学习和转发数据帧的方式,将连接到它的网络设备组成一个共享的以太网段,使得这些设备可以直接通信。桥接设备工作在数据链路层(第二层),它不涉及 IP 地址或路由。

通过 ip link 查看设备的状态、属性和配置信息

┌──[root@liruilongs.github.io]-[~]
└─$ip link
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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ffaltname enp3s0
5: vnet-br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/ether ce:93:3b:6d:37:48 brd ff:ff:ff:ff:ff:ff

可以看到刚刚添加的虚拟桥接设备,目前处于 DOWN 状态。

添加虚拟网卡对eth0-r 和 veth-reth0-g 和 veth-g

┌──[root@liruilongs.github.io]-[~]
└─$ip link add eth0-r type veth peer name veth-r
┌──[root@liruilongs.github.io]-[~]
└─$ip link add eth0-g type veth peer name veth-g

把两个虚拟网卡对中的一端放到上面创建的网络命名空间

┌──[root@liruilongs.github.io]-[~]
└─$ip link set eth0-r netns red
┌──[root@liruilongs.github.io]-[~]
└─$ip link set eth0-g netns green

然后将虚拟网卡对的另一端连接到vnet-br0桥。

┌──[root@liruilongs.github.io]-[~]
└─$ip link set veth-r master vnet-br0
┌──[root@liruilongs.github.io]-[~]
└─$ip link set veth-g master vnet-br0

查看根网络命名空间的桥接设备类型的网络设备(桥接表)。

┌──[root@liruilongs.github.io]-[~]
└─$ip link show type bridge
5: vnet-br0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000link/ether 62:2b:41:f9:39:b3 brd ff:ff:ff:ff:ff:ff

查看桥接设备(vnet-br0)关联的网络设备。

┌──[root@liruilongs.github.io]-[~]
└─$ip link show master vnet-br0
6: veth-r@if7: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master vnet-br0 state DOWN mode DEFAULT group default qlen 1000link/ether 62:2b:41:f9:39:b3 brd ff:ff:ff:ff:ff:ff link-netns red
8: veth-g@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master vnet-br0 state DOWN mode DEFAULT group default qlen 1000link/ether be:a3:9a:1c:a1:06 brd ff:ff:ff:ff:ff:ff link-netns green

根据输出,有两个网络设备与 vnet-br0 桥接设备关联:

veth-r@if7:这是一个虚拟网络设备(veth pair),它与 vnet-br0 桥接设备关联。它的状态是 DOWN,表示当前处于未激活状态。它的 MAC 地址为 62:2b:41:f9:39:b3。此设备属于 red 网络命名空间。

veth-g@if9:这是另一个虚拟网络设备(veth pair),也与 vnet-br0 桥接设备关联。它的状态是 DOWN,表示当前处于未激活状态。它的 MAC 地址为 be:a3:9a:1c:a1:06。此设备属于 green 网络命名空间。

激活桥接对应的网络设备

┌──[root@liruilongs.github.io]-[~]
└─$ip link set vnet-br0 up
┌──[root@liruilongs.github.io]-[~]
└─$ip link set veth-r up
┌──[root@liruilongs.github.io]-[~]
└─$ip link set veth-g up

激活 网络命名空间中的回环地址和对应的虚拟网卡对

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red ip link set lo up
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red ip link set eth0-r up
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green ip link set lo up
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green ip link set eth0-g up

ip link 确认设备状态

┌──[root@liruilongs.github.io]-[~]
└─$ip link
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: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ffaltname enp3s0
5: vnet-br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000link/ether 62:2b:41:f9:39:b3 brd ff:ff:ff:ff:ff:ff
6: veth-r@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vnet-br0 state UP mode DEFAULT group default qlen 1000link/ether 62:2b:41:f9:39:b3 brd ff:ff:ff:ff:ff:ff link-netns red
8: veth-g@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vnet-br0 state UP mode DEFAULT group default qlen 1000link/ether be:a3:9a:1c:a1:06 brd ff:ff:ff:ff:ff:ff link-netns green

进入网络命名空间 shell 环境,分配 IP

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red bash
┌──[root@liruilongs.github.io]-[~]
└─$ip address add 192.168.20.2/24 dev eth0-r
┌──[root@liruilongs.github.io]-[~]
└─$ip r
# 对于目标网络 192.168.20.0/24 的数据包,它们将使用 eth0-r 设备进行本地通信。
192.168.20.0/24 dev eth0-r proto kernel scope link src 192.168.20.2
┌──[root@liruilongs.github.io]-[~]
└─$ip a
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 hostvalid_lft forever preferred_lft forever
7: eth0-r@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000link/ether ca:b0:b2:80:25:43 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.20.2/24 scope global eth0-rvalid_lft forever preferred_lft foreverinet6 fe80::c8b0:b2ff:fe80:2543/64 scope linkvalid_lft forever preferred_lft forever
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit

对另一个命名空间操作

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green bash
┌──[root@liruilongs.github.io]-[~]
└─$ip address add 192.168.20.3/24 dev eth0-g
┌──[root@liruilongs.github.io]-[~]
└─$ip a
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 hostvalid_lft forever preferred_lft forever
9: eth0-g@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000link/ether 36:5e:d9:8d:04:a8 brd ff:ff:ff:ff:ff:ff link-netnsid 0inet 192.168.20.3/24 scope global eth0-gvalid_lft forever preferred_lft foreverinet6 fe80::345e:d9ff:fe8d:4a8/64 scope linkvalid_lft forever preferred_lft forever
┌──[root@liruilongs.github.io]-[~]
└─$ip r
192.168.20.0/24 dev eth0-g proto kernel scope link src 192.168.20.3
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit

两个命名空间之间的连通性测试

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green bash
┌──[root@liruilongs.github.io]-[~]
└─$ping -c 2 192.168.20.2
PING 192.168.20.2 (192.168.20.2) 56(84) bytes of data.
64 bytes from 192.168.20.2: icmp_seq=1 ttl=64 time=0.252 ms
64 bytes from 192.168.20.2: icmp_seq=2 ttl=64 time=0.047 ms--- 192.168.20.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1034ms
rtt min/avg/max/mdev = 0.047/0.149/0.252/0.102 ms┌──[root@liruilongs.github.io]-[~]
└─$exit
exit
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red bash
┌──[root@liruilongs.github.io]-[~]
└─$ping -c 2 192.168.20.3
PING 192.168.20.3 (192.168.20.3) 56(84) bytes of data.
64 bytes from 192.168.20.3: icmp_seq=1 ttl=64 time=0.241 ms
64 bytes from 192.168.20.3: icmp_seq=2 ttl=64 time=0.129 ms--- 192.168.20.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1038ms
rtt min/avg/max/mdev = 0.129/0.185/0.241/0.056 ms
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit

将 IP 192.168.20.1/24 分配给根网络命名空间中的 vnet-br0 桥接口,以允许来自红色和绿色名称空间的外部通信,它将成为该网络的默认网关

┌──[root@liruilongs.github.io]-[~]
└─$ip address add 192.168.20.1/24 dev vnet-br0

192.168.20.1配置为绿色和红色命名空间中的默认网关。将所有目标不在本地网络中的数据包发送到该网关进行进一步路由。

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red bash
┌──[root@liruilongs.github.io]-[~]
└─$route add default gw 192.168.20.1
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green bash
┌──[root@liruilongs.github.io]-[~]
└─$route add default gw 192.168.20.1
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit

在 NAT 表中添加一个规则,将源 IP 地址为 192.168.20.0/24 的数据包进行源地址转换 (Source NAT)。

┌──[root@liruilongs.github.io]-[~]
└─$iptables -s 192.168.20.0/24 -t nat -A POSTROUTING -j MASQUERADE

执行该命令后,数据包从子网 192.168.20.0/24 发送到外部网络时,源 IP 地址将被替换为执行 NAT 的接口的 IP 地址。这通常用于实现网络地址转换 (NAT),将内部网络的私有 IP 地址转换为公共 IP 地址,以便与外部网络进行通信。

根命名空间做内网和公网地址Ping

┌──[root@liruilongs.github.io]-[~]
└─$ping 192.169.26.149 -c 3
PING 192.169.26.149 (192.169.26.149) 56(84) bytes of data.
64 bytes from 192.169.26.149: icmp_seq=1 ttl=128 time=199 ms
64 bytes from 192.169.26.149: icmp_seq=2 ttl=128 time=199 ms
64 bytes from 192.169.26.149: icmp_seq=3 ttl=128 time=216 ms--- 192.169.26.149 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 199.020/204.755/215.909/7.888 ms
┌──[root@liruilongs.github.io]-[~]
└─$ping baidu.com -c 3
PING baidu.com (39.156.66.10) 56(84) bytes of data.
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=1 ttl=128 time=11.9 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=2 ttl=128 time=11.9 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=3 ttl=128 time=12.1 ms--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 11.919/11.999/12.142/0.100 ms

在主机系统上启用IPV4转发以允许外部通信。执行该命令后,系统将开启 IP 转发功能,允许数据包在不同的网络接口之间进行转发。

┌──[root@liruilongs.github.io]-[~]
└─$sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

在两个命名空间中做内网 ping 测试

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green ping baidu.com -c 3
PING baidu.com (110.242.68.66) 56(84) bytes of data.
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=1 ttl=127 time=20.5 ms
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=2 ttl=127 time=20.0 ms
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=3 ttl=127 time=20.3 ms--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 20.031/20.261/20.475/0.181 ms
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red ping baidu.com -c 3
PING baidu.com (110.242.68.66) 56(84) bytes of data.
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=1 ttl=127 time=20.2 ms
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=2 ttl=127 time=20.3 ms
64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=3 ttl=127 time=20.1 ms--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 20.085/20.197/20.278/0.082 ms

在两个命名空间中做公网 ping 测试

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec red ping 192.168.26.149 -c 3
PING 192.168.26.149 (192.168.26.149) 56(84) bytes of data.
64 bytes from 192.168.26.149: icmp_seq=1 ttl=64 time=0.241 ms
64 bytes from 192.168.26.149: icmp_seq=2 ttl=64 time=0.110 ms
64 bytes from 192.168.26.149: icmp_seq=3 ttl=64 time=0.075 ms--- 192.168.26.149 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2074ms
rtt min/avg/max/mdev = 0.075/0.142/0.241/0.071 ms
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec green ping 192.168.26.149 -c 3
PING 192.168.26.149 (192.168.26.149) 56(84) bytes of data.
64 bytes from 192.168.26.149: icmp_seq=1 ttl=64 time=0.258 ms
64 bytes from 192.168.26.149: icmp_seq=2 ttl=64 time=0.097 ms
64 bytes from 192.168.26.149: icmp_seq=3 ttl=64 time=0.094 ms--- 192.168.26.149 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2043ms
rtt min/avg/max/mdev = 0.094/0.149/0.258/0.076 ms
┌──[root@liruilongs.github.io]-[~]
└─$

在这里插入图片描述

到这里,我们实现和两个网络命名空间彼此通信,并且和根命名空间通信,同时可以和公网通信。

简单回顾一下我们干了什么:

  • 在主机的根网络命名空间中创建一个 Linux 网桥,创建两个 Linux 网络命名空间
  • 创建两个 veth pair,将其中一个端口连接到根命名空间中的网桥上,另一个端口放置在目标命名空间中。
  • 在目标命名空间中配置 IP 地址,并将该端口启动起来。
  • 在根命名空间中启用 IP 转发功能(通过设置 net.ipv4.ip_forward=1),分配IP地址,同时在命名空间配置默认网关。
  • 配置 NAT 规则SNAT,将目标命名空间中的流量转发的源IP地址转化为根命名空间中的IP地址。
  • 目标命名空间中的流量将通过默认网关走网桥IP地址转发到根命名空间中,并通过根命名空间中的网络设备连接到互联网。

实际中的应用

实际上上面的 Demo 就是 经典的容器组网模型,veth pair + bridge 的模式,用过 docker 的小伙伴会发现,默认情况下,安装完 docker 会自动创建一个 桥接设备 docker0.

┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ip link show type bridge
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULTlink/ether 02:42:68:f8:90:26 brd ff:ff:ff:ff:ff:ff
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ip link show master docker0
┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$

在不修改网络类型的情况下,docker 也使用桥接的模式,主机中部署的 容器访问公网即通过我们上面配置的方式

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知,这是一个开源项目,如果你认可它,不要吝啬星星哦 😃


https://ramesh-sahoo.medium.com/linux-network-namespace-and-five-use-cases-using-various-methods-f45b1ec5db8f

《Kubernetes 网络权威指南:基础、原理与实践》


© 2018-2024 liruilonger@gmail.com, All rights reserved. 保持署名-非商用-相同方式共享(CC BY-NC-SA 4.0)

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

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

相关文章

java之Maven

1. maven Maven是管理和构建java项目的工具 项目依赖资源(jar包)的管理,避免版本冲突统一项目结构项目构建&#xff0c;标准跨平台(Linux,window,MacOS)的自动化项目管理 2.maven依赖仓库 2.maven安装 maven安装视频教程 3. IDEA集成Maven 4. maven的依赖范围 5. maven生命…

【Linux】进程概念(冯诺依曼体系结构、操作系统、进程)-- 详解

一、冯诺依曼体系结构 1、概念 &#xff08;1&#xff09;什么是冯诺伊曼体系结构&#xff1f; 数学家冯诺伊曼于 1946 年提出存储程序原理&#xff0c;把程序本身当作数据来对待&#xff0c;程序和该程序处理的数据用同样的方式储存。 冯诺伊曼理论的要点是&#xff1a;计算…

GEE:梯度提升树(Gradient Boosting Tree)回归教程(样本点、特征添加、训练、精度、参数优化)

作者:CSDN @ _养乐多_ 对于分类问题,这个输出通常是一个类别标签 ,而对于回归问题,输出通常是一个连续的数值。回归可以应用于多种场景,包括预测土壤PH值、土壤有机碳、土壤水分、碳密度、生物量、气温、海冰厚度、不透水面积百分比、植被覆盖度等。 本文将介绍在Google…

【刷题记录】——时间复杂度

本系列博客为个人刷题思路分享&#xff0c;有需要借鉴即可。 1.目录大纲&#xff1a; 2.题目链接&#xff1a; T1&#xff1a;消失的数字&#xff1a;LINK T2&#xff1a;旋转数组&#xff1a;LINK 3.详解思路&#xff1a; T1&#xff1a; 思路1&#xff1a;先排序&#xf…

08:K8S资源对象管理|服务与负载均衡|Ingress

K8S资源对象管理&#xff5c;服务与负载均衡&#xff5c;Ingress DaemonSet控制器污点策略容忍容忍污点 其他资源对象Job资源对象 有限生命周期CronJob资源对象 集群服务服务自动发现headless服务 实现服务定位与查找 服务类型 Ingress插件 发布服务的方式 DaemonSet控制器 Da…

Vulnhub靶机:DC2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC2&#xff08;10.0.2.55&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-2,311/…

L2-001 紧急救援

一、题目 二、解题思路 迪杰斯特拉算法。求最短路径的条数&#xff1a;在更新T时&#xff0c;如果是 dis[j]>dis[index]map[index][j] &#xff0c;则 cot[j]cot[index] &#xff0c;如果是 dis[j]dis[index]map[index][j] &#xff0c;则 cot[j]cot[index] 。递归输出最短…

RestFul的认识

前言 RESTful 是 Representational State Transfer 的缩写&#xff0c;是一种软件架构风格&#xff0c;用于在网络上构建和整合应用程序。它基于 HTTP 协议&#xff0c;并定义了一组约束和规范&#xff0c;用于规范客户端和服务器之间的通信。 RESTful API 是遵循 REST 架构规…

Tied Block Convolution: 具有共享较薄滤波器的更简洁、更出色的CNN

摘要 https://arxiv.org/pdf/2009.12021.pdf 卷积是卷积神经网络&#xff08;CNN&#xff09;的主要构建块。我们观察到&#xff0c;随着通道数的增加&#xff0c;优化后的CNN通常具有高度相关的滤波器&#xff0c;这降低了特征表示的表达力。我们提出了Tied Block Convolutio…

InternLM大模型实战-6.OpenCompass大模型评测

文章目录 前言笔记正文关于模型评测的三个问题为什么需要评测我们需要测什么怎么测试大语言模型 主流大模型评测框架OpenCompass大模型评测领域的挑战 前言 本文是对于InternLM全链路开源体系系列课程的学习笔记。【OpenCompass 大模型评测】 https://www.bilibili.com/video/…

软件测试 - 测试用例设计方法之等价类划分和边界值分析

1. 等价类划分法 1.1 基本理论 等价类划分法是通过科学的方法找到具有共同特性的测试输入的集合&#xff0c;避免进行穷举测试&#xff0c;大大减少了测试用例的数量&#xff0c;从而提高测试效率。等价类划分法的典型应用场景就是输入框&#xff0c;适用于较少数量输入框的场…

LeetCode 0987.二叉树的垂序遍历:遍历时存节点信息,遍历完自定义排序

【LetMeFly】987.二叉树的垂序遍历&#xff1a;遍历时存节点信息&#xff0c;遍历完自定义排序 力扣题目链接&#xff1a;https://leetcode.cn/problems/vertical-order-traversal-of-a-binary-tree/ 给你二叉树的根结点 root &#xff0c;请你设计算法计算二叉树的 垂序遍历…