今天在学习和了解一个项目的整体架构时,看到在其网关层有个比较少见的名词(主要是我见的少),就是和Nginx搭配使用的DPVS,我们都学习过Nginx是负载均衡的比较经典的系统,那么这个DPVS是个什么东东,接下来我们就好好研究它。
首先,我们需要知道的是,DPVS来自于哪里?我看到的众多架构图都来自爱奇艺官方给出的一个架构,当然这个名字的来源又是DPDK+LVS,而且这里的LVS还是阿里巴巴的改进版。其中架构图中分别列出了诸如:用户态实现、Master/Worker模型、网卡队列/CPU绑定、关键数据无锁化、跨CPU无锁通信以及其他功能
大家都知道在java中有很多锁为了实现速度更快,就极力避免用户态和核心态的相互切换,而这里就明确的提出了,全程使用用户态。主要是因为DPVS绕过了内核复杂的协议栈,并采用轮询的方式收发数据包,避免了锁、内核中断、上下文切换、内核态和用户态的数据拷贝所产生的性能开销。
和Nginx一样,使用了M/S的模型,其中Master处理控制平面,比如参数配置、统计获取;而Worker则负责核心的一些任务,比如负载均衡。
而且,在运行DPVS时,使用了多线程,并且每个线程都运行一个Master或者Worker,确保不会产生切换角色带来的消耗,并且,每个Master连接多个Worker
现在的服务器大都是多队列网卡,就是说支持多个队列收发数据,并且每个网卡队列的对应一个CPU核心和一个Worker进程,从而实现了对于绑定。从而实现了更大的并行处理能力。
其实跨CPU无锁通信同样也是实现无锁化,从而减少性能消耗。主要是CPU总归是要进行通信的,比如:
既然底层是需要进行通信的,那么就不能存在相互影响、相互等待的情况。而DPVS的无锁通信主要还是依靠DPDK提供的无锁rte_ring库实现的,从底层保证了无锁。
直接开始编译安装,只有在实践中才能找到其内部的奥秘。
git clone https://github.com/iqiyi/dpvs.git
cd dpvs
然后再下载dpdk的源码
wget https://fast.dpdk.org/rel/dpdk-20.11.1.tar.xz
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
然后在编译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,编译他比较简单,只需要配置
export PKG_CONFIG_PATH=/opt/sj/dpvs-1.8/dpdk-stable-18.11.2/dpdklib/lib64/pkgconfig/libdpdk.pc
然后再dpvs目录下编译即可,
cd ..
make
make install
最后就是开始运行dpvs
拷贝./conf/下合适的配置文件到/etc/dpvs.conf
极为简陋
毕竟DPVS并无像Nginx一样使用量大,因此也就并没有继续详细深入的进行研究和分析源码