百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 优雅编程 > 正文

阿里云用DPDK如何解决千万级流量并发

sinye56 2024-11-09 13:38 3 浏览 0 评论

目录

1. Linux虚拟网卡的实现

2. DPDK的KNI讲解

3. DPDK的项目实战

很多平台一旦做大了,平台的流量就会陡增,同时并发访问的流量也会暴增,原本规划的硬件配置就无法满足当下的流量问题。

那么如何处理好高并发的流量问题呢?

Linux虚拟网卡的实现

一、最终的效果,实现了一个名为sn0的虚拟网卡接口


  [root@xxx snull]# cat /proc/net/dev 
  Inter-|   Receive                        
   face |bytes    packets errs drop fifo 
      lo:    6528      76    0    0    0   
    eth0:148681882  216304    0    0    0 
    eth1:       0       0    0    0    0   
    eth2:       0       0    0    0    0   
    sit0:       0       0    0    0    0   
     sn0:       0       0    0    0    0   
     sn1:     210       3    0    0    0 

  [root@xxx snull]# ifconfig sn0  up 
  [root@xxx snull]# ifconfig sn0 
  sn0       Link encap:Ethernet  HWaddr 00:53:4E:55:4C:30   
            inet6 addr: fe80::253:4eff:fe55:4c30/64 Scope:Link 
            UP BROADCAST RUNNING NOARP MULTICAST  MTU:1500  Metric:1 
            RX packets:0 errors:0 dropped:0 overruns:0 frame:0 
            TX packets:1 errors:0 dropped:0 overruns:0 carrier:0 
            collisions:0 txqueuelen:1000 
            RX bytes:0 (0.0 b)  TX bytes:70 (70.0 b) 


二、总体过程
首先需要内核分配一个net_device结构(以下简称dev结构),并初始化dev结构。
struct net_device *snull_devs[2]; //snull 实现的是两个虚拟网卡,用一个两个大小的结构体数组保存net_device结构,我只关注一个。


      snull_devs[0] = alloc_netdev(sizeof(struct snull_priv), "sn%d", 
            snull_init);//内核分配一个dev,此dev由snull_init初始化。然后由alloc_netdev函数返回此dev指针。
 
  
      for (i = 0; i < 2;  i++) 
        if ((result = register_netdev(snull_devs[i])))//dev结构初始化后调用register_netdev向内核注册,注册后就可以对设备(虚拟网卡)操作了。 

            printk("snull: error %i registering device \"%s\"\n", 
                    result, snull_devs[i]->name); 
        else 
            ret = 0; 

三,化过程

为了便于理解初始化过程,帖上一段alloc_netdev的内核实现

 
      struct net_device *alloc_netdev(int sizeof_priv, const char *mask, 
                           void (*setup)(struct net_device *))//最后一个参数为函数指针,即指向传进来的snull_init 
    { 
        void *p; 
        struct net_device *dev; 
        int alloc_size; 
     
        /* ensure 32-byte alignment of both the device and private area */ 
     
        alloc_size = (sizeof(struct net_device) + NETDEV_ALIGN_CONST) 
                & ~NETDEV_ALIGN_CONST; 
        alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; 
     
        p = kmalloc (alloc_size, GFP_KERNEL); 
        if (!p) { 
            printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); 
            return NULL; 
        } 
     
        memset(p, 0, alloc_size); 
     
        dev = (struct net_device *)(((long)p + NETDEV_ALIGN_CONST) 
                    & ~NETDEV_ALIGN_CONST);//为dev结构分配内存空间 
        dev->padded = (char *)dev - (char *)p; 
     
        if (sizeof_priv) 
            dev->priv = netdev_priv(dev); 
     
        setup(dev);//实现调用了snull_init(dev)对dev结构初始化。 
        strcpy(dev->name, mask); 
     
        return dev;//返回已初始化的dev 
    } 

    下面看下这个重要的初始化函数snull_init(),dev的一些重要函数指针均在此赋值 

    void snull_init(struct net_device *dev) 
    { 
        struct snull_priv *priv; 
        /* 
         * Then, assign other fields in dev, using ether_setup() and some 
         * hand assignments 
         */ 
        ether_setup(dev); /* assign some of the fields *///这个函数初始化了dev的许多成员 
     
        dev->open            = snull_open; //打开设备 
        dev->stop            = snull_release; 
        dev->set_config      = snull_config; 
        dev->hard_start_xmit = snull_tx;  //数据发送函数 
        dev->do_ioctl        = snull_ioctl; 
        dev->get_stats       = snull_stats; 
        dev->change_mtu      = snull_change_mtu; 
        dev->rebuild_header  = snull_rebuild_header; 
        dev->hard_header     = snull_header;//建立硬件头,包含源和目的mac地址 
        dev->tx_timeout      = snull_tx_timeout;//数发送超时处理。 
        dev->watchdog_timeo = timeout; 
        if (use_napi) { 
            dev->poll        = snull_poll; 
            dev->weight      = 2; 
        } 
        /* keep the default flags, just add NOARP */ 
        dev->flags           |= IFF_NOARP; 
        dev->features        |= NETIF_F_NO_CSUM; 
        dev->hard_header_cache = NULL;      /* Disable caching */ 
     
        /* 
         * Then, initialize the priv field. This encloses the statistics 
         * and a few private fields. 
         */ 
        priv = netdev_priv(dev); 
        memset(priv, 0, sizeof(struct snull_priv)); 
        spin_lock_init(&priv->lock); 
        snull_rx_ints(dev, 1);      /* enable receive interrupts */ 
        snull_setup_pool(dev); 
    } 


以上内容已经把框架搭出来了,至于net结构成员的理解和细节、数据包的发送的接收、超时传输中断处理及sk_buff数据结构等
信息可参考给出的参考资料。
类似的实现网络驱动程序的源码还有内核源码中的loopback.c、plip.c、e100.c。

DPDK的KNI讲解

安装配置

获取源码


# cd<InstallDir># exporthttps_proxy=https://proxy.austin.hp.com:8080# gitclone https://github.com/pktgen/Pktgen-DPDK.git
Ubuntu14.04,pktgen2.7.7 ,DPDK1.7.1


注:Pktgen-DPDK/dpdk/example目录中包含有pktgen源码

编译安装

Build DPDK

1. 设置运行时环境

# sudo apt-get install libpcap-dev
# export RTE_SDK=<installDir>/Pktgen-DPDK/dpdk
# export RTE_TARGET=x86_64-pktgen-linuxapp-gcc

2. 编译安装

# cd $RTE_SDK
# ./tools/setup.sh

选择安装x86_64-pktgen-linuxapp-gcc,然后配置hugepagemappings for non-NUMA systems。安装成功后在dpdk目录下会出现x86_64-pktgen-linuxapp-gcc文件夹。

DPDK的项目实战

以下是基于DPDK或者支持DPDK的一些项目:

f-stack:基于dpdk的高性能网络框架,其使用纯C粘合了dpdk和freebsd,其提供了基于posix的上层接口,使移植变得非常容易,并且其搭载了一些上层的应用软件,包括DNS server,nginx,redis等。项目地址:http://www.f-stack.org/

6WIND公司的系列产品对DPDK支持很好,有6WINDGATE系列使用了DPDK的支持,其可以完美运行在linux上,但是其实商业性的,应该是所有DPDK应用中最好的。公司地址:http://www.6wind.com/products/6windgate/

intel官方基于DPDK实现的一个项目,利用L4技术和VPP目的是实现一个完整的应用程序协议栈,未来成熟之后,应该非常不错。项目地址:https://fd.io/community/

seastar项目:也是基于DPDK实现一套高性能的纯c++异步框架,使用了c++14的特性,其主要目的是为了 ScyllaDB, 一个高性能的NoSQL数据库,同时其采用无共享设计、高网络性能、一种新的编程模型、CPU核心之间的新的信息共享方式等特性。但是其主要目的是为了ScyllaDB设计,所以其更加适合LAN情况,在WAN情况下,其表现不如f-stack。其中也有丰富的应用程序:

Pedis:Redis兼容的数据结构存储
Scylla:NoSQL专栏数据库,与Apache Cassandra以10倍的吞吐量兼容
Seastar HTTPD:Web服务器
Seastar Memcached:Memcache键值存储的快速服务器

不好的地方大家可以评论出来我们一起讨论学习交流,空余时间我整理了一些学习资料有需要的朋友可以后台私信‘资料’可以送大家学习

相关推荐

linux安装FTP

1、在nkftp目录下安装ftp,进入到nkftp里面[root@localhostbin]#cd/data/nkftp执行安装命令:[root@localhostnkftp]#rpm-i...

LINUX下搭建FTP服务器

FTP服务器介绍FTP是FileTransferProtocol(文件传输协议)的英文简称,而中文简称为“文传协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(App...

Linux下如何进行FTP设置

目录:一、Redhat/CentOS安装vsftp软件二、Ubuntu/Debian安装vsftp软件一、Redhat/CentOS安装vsftp软件1.更新yum源yumupdate-y2.安...

推荐使用集串口 SSH远程登录和FTP传输三合一工具MobaXterm

来源:百问网作者:韦东山本文字数:1216,阅读时长:4分钟在以前的资料里,串口和SSH远程登使用SecureCRT,window与ubuntu数据传输使用filezilla,窗口切换来切换去,麻烦也...

如何搭建FTP服务器(Linux系统)

上次说了Windows操作系统下搭建的FTP服务器,那有朋友问我,说买的XX轻量应用服务器都是属于Linux的操作系统,我该如何为搭建FTP服务器呢?...

Linux 命令 ncftp(文件传输)——想玩转linux就请一直看下去

我是IT悟道,点击右上方“关注”,每天分享IT、科技、数码方面的干货。Linuxncftp命令...

如何用 ftp 实现一键上传

简介ftp是Internet标准文件传输协议的用户界面,它允许用户与远程网络站点之间传输文件...

Linux安装ftp

1安装vsftpd组件安装完后,有/etc/vsftpd/vsftpd.conf文件,是vsftp的配置文件。[root@bogon~]#yum-yinstallvsftpd2添加一个...

一天一点点:linux - ftp命令

linuxftp命令设置文件系统相关功能。FTP是ARPANet的标准文件传输协议,该网络就是现今Internet的前身。语法ftp[-dignv][主机名称或IP地址]参数:-d详细显示指令执...

Centos 7 搭建FTP

目录安装软件以及启动服务添加防火墙规则关闭selinuxftp配置常用常用参数详解特殊参数配置文件没有的参数也可以添加到配置中1.安装软件以及启动服务yuminstall-yvsftpdsys...

【Linux】Linux中ftp命令,没有你想的那么简单

本文介绍了Linux中FTP命令的基本用法,包括连接与登录远程服务器,以及解析了FTP协议中五个最常用的操作命令的使用和解析过程。同时,提供了一个包含常用FTP操作命令的表格,供读者参考。通过熟练掌握...

linux 命令行操作ftp

以下是linuxftp命令参数的详解。FTP>!从ftp子系统退出到外壳?FTP>?显示ftp命令说明??和help相同?格式:?[command]说明:[com...

多学习才能多赚钱之:linux如何使用ftp

linux如何使用ftp步骤1:建立FTP连接想要连接FTP服务器,在命令上中先输入ftp然后空格跟上FTP服务器的域名'domain.com'或者IP地址例如:ftpdom...

linux常用网络操作方法:ftp命令使用方法

常用网络操作方法Linux提供了一组强有力的网络命令来为用户服务,这些工具能够帮助用户登录到远程计算机上、传输文件和执行远程命令等。本节介绍下列几个常用的有关网络操作的命令:ftp传输文件tel...

Linux 5.15有望合并Memory Folios方案 内核构建速度可提升7%

甲骨文公司的长期内核开发人员MatthewWilcox已经研究了“内存对开区”概念相当长的一段时间,这可以改善Linux的内存管理,使其具有更大的效率。例如,使用内存对开的基准测试表明,内核的构建速...

取消回复欢迎 发表评论: