dpvs入门实践1--概念及编译安装
在接触一项新事物时,我习惯从宏观角度去了解。也就是从它的产生背景、基本概念、大致的原理图来了解。如果能找到灵魂paper来读一下是最好。然后就是编译运行,遇到不懂的概念再次反过来理解。然后再抓住一条线,例如四层数据包如何转发来进行代码研读。也就是说先从大图像了解概貌入手,然后运行程序敲几个命令有个感性的认识,然后再沿着一条线去细读反过来再细化最初的大图像。
DPVS是一种基于DPDK的高性能四层负载均衡器。它来源于Linux Virtual Server LVS及其修改后的alibaba/LVS. 那LVS是什么呢?Linux Virtual Server是构建在实服务器集群上的高度可伸缩和高可用的服务器,负载平衡器运行在Linux操作系统上。服务器集群的架构对最终用户是完全透明的,用户之间的交互就好像它是一个高性能的虚拟服务器。因此,DPVS使用了LVS里面的核心概念(这些在http://www.linuxvirtualserver.org/zh/index.html官网有详细说明,这里做个摘要):
- NAT: 通过网络地址转换,调度器重写请求报文的目标地址,根据预设的调度算法,将请求分派给后端的真实服务器;真实服务器的响应报文通过调度器时,报文的源地址被重写,再返回给客户,完成整个负载调度过程。
- TUN: 采用NAT技术时,由于请求和响应报文都必须经过调度器地址重写,当客户请求越来越多时,调度器的处理能力将成为瓶颈。为了解决这个问题,调度器把请求报 文通过IP隧道转发至真实服务器,而真实服务器将响应直接返回给客户,所以调度器只处理请求报文。由于一般网络服务应答比请求报文大许多,采用 VS/TUN技术后,集群系统的最大吞吐量可以提高10倍。
- DR: 通过改写请求报文的MAC地址,将请求发送到真实服务器,而真实服务器将响应直接返回给客户。同VS/TUN技术一样,VS/DR技术可极大地 提高集群系统的伸缩性。这种方法没有IP隧道的开销,对集群中的真实服务器也没有必须支持IP隧道协议的要求,但是要求调度器与真实服务器都有一块网卡连 在同一物理网段上。
- FNAT: IPVS的一种新的报文转发方式,区别于DR/NAT/TUNNEL. 该模式处理原则如下:引入local ip address(即IDC 内部ip地址lip), IPVS转换cip(client ip)--vip to/from lip--rip(remote ip),这里lip和rip都是IDC内部IP地址,因此LVS负载均衡器和真实服务器可以在不同的vlan,真实的服务器只需要能访问到内网即可。
其他概念:
- 单臂(one arm): 指所有的客户端和服务器都在负载均衡器的同一侧,LB通过相同的逻辑网络接口转发流量。
- 双臂(two arms): 客户机位于负载平衡器(LB)的一端,服务器位于负载平衡器(RS)的另一端,然后LB在其两个逻辑网络接口之间转发数据包。例如广域网到局域网的负载均衡.
编译安装
虽然github官方上说明不再支持dpdk-stable-20.11.1之前的版本了,但是目前新分支还出与开发阶段,我没有编译通过。所以我用的版本还是dpdk18.11.2 + dpvs1.8. 首先安装dpvs1.8版本在github上的官方介绍一样下载1.8版本的dpvs源代码。
$ git clone https://github.com/iqiyi/dpvs.git
$ cd dpvs
下不来的话可以直接去码云网站https://gitee.com 下载release包。然后进到dpvs目录,再下载dpdk源码:
$ wget https://fast.dpdk.org/rel/dpdk-20.11.1.tar.xz # download from dpdk.org if link failed.
$ tar xf dpdk-20.11.1.tar.xz
接下来打补丁,在打补丁之前我们先来安装一些工具包防止在后面的编译过程中报错,有的话可以跳过:
yum install python3 (Python 3.5 or later.)
pip3 install meson ninja //Meson (version 0.49.2+) and ninja
pip3 install pyelftools 或者yum install pyelftools
yum install -y popt-devel automake libnl3 libnl3-devel openssl openssl-devel numactl kernel-devel libpcap-devel unzip patch numactl-devel
另外,注意安装gcc前要安装和内核版本匹配的kernel-devel, 查看 ls /usr/src/kernels/, 并且 ldd --version 查看glibc版本要求 glibc >= 2.7(拜托2.17 大于 2.7)
编译dpdk
在编译dpvs之前要先编译DPDK:
cd dpvs-1.8/
cp patch/dpdk-stable-18.11.2/*.patch dpdk-stable-18.11.2/
cd dpdk-stable-18.11.2/
patch -p1 < 000
...
make config T=x86_64-native-linuxapp-gcc
make
export RTE_SDK=$PWD
export RTE_TARGET=build
echo 8192 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
echo 8192 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages
// 如果很多个numa节点,可以用如下命令:
for i in {0..7};do echo 8192 > /sys/devices/system/node/node$i/hugepages/hugepages-2048kB/nr_hugepages;done
mkdir /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
grep Huge /proc/meminfo
# 需要开机自动挂载的话可以在
$ echo "nodev /mnt/huge hugetlbfs defaults 0 0" >> /etc/fstab
modprobe uio
cd dpdk-stable-18.11.2
insmod build/kmod/igb_uio.ko
insmod build/kmod/rte_kni.ko carrier=on
./usertools/dpdk-devbind.py --status
// 172.18.8.129: eno4 100.200.0.129 30:fd:65:32:e8:c3 0000:1a:00.3
// 172.18.8.129: eno1 30:fd:65:32:e8:c0 0000:1a:00.0
ifconfig eno4 down
./usertools/dpdk-devbind.py -b igb_uio 0000:1a:00.3
./usertools/dpdk-devbind.py --status
./usertools/dpdk-devbind.py -u 0000:1a:00.0
./usertools/dpdk-devbind.py -b i40e 0000:1a:00.0
编译dpvs
编译dpvs比较简单,只需要配置export PKG_CONFIG_PATH=/opt/sj/dpvs-1.8/dpdk-stable-18.11.2/dpdklib/lib64/pkgconfig/libdpdk.pc 然后到dpvs目录下编译即可
cd ..
make // 报 inline 函数未定义的错误,需要在 src/Makefile CFLAGS 参数最后-mcmodel=medium之前加上 -fgnu89-inline
make install
运行DPVS
拷贝./conf/下合适的配置文件到 /etc/dpvs.conf
总结一下,我遇到过的问题:
- 运行./bin/dpvs 如果报段错误退出则需要调整配置文件中的pktpool_size,我猜测是因为这个值太大了导致内存不足。可以把这个值改小一些,并且屏蔽一些cpu,减少消耗。我这样操作之后能跑起来了。
- 我遇到另外一个coredump退出的情况,使用1中的方法不生效。于是我打开src/Makefile中的DEBUG开关,用gdb跑dpvs,因为不知道断点在哪里只能run,得到的信息如下,基本没用
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff440d700 (LWP 47658)]
0x00000000006162f9 in conn_term_lcore ()
Missing separate debuginfos, use: debuginfo-install glibc-2.17-196.el7.x86_64 libgcc-4.8.5-16.el7.x86_64 li.0.2k-24.el7_9.x86_64 zlib-1.2.7-19.el7_9.x86_64
于是,我又打开了/etc/dpvs.conf中的log_level为DEBUG,再次启动程序得到有效信息如下所示:
EAL: rte_mem_virt2phy(): cannot open /proc/self/pagemap: Too many open files
应该是系统允许最大打开文件数太小所致,用ulimit -a查看果然只有1024,用ulimit -n 1048576改成较大的数量,再次启动DPVS进程这次可以了。
3. 报错“DPVS_MAX_SOCKET is smaller than system numa nodes!”,查看源码发现是numa节点数小于系统常量DPVS_MAX_SOCKET,再次查找这个DPVS_MAX_SOCKET,发现它是在src/config.mk文件中定义并被编译到源码里,因此需要修改成numa节点数(numactl --hardware查看numa节点数)并再次编译。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现