【流分类与多队列】RSS 和 Flow Director

一、RSS

1.多队列网卡硬件实现

多队列网卡是一种技术,最初是用来解决网络IO QoS (quality of service)问题的,后来随着网络IO的带宽的不断提升,单核CPU不能完全处满足网卡的需求,通过多队列网卡驱动的支持,将各个队列通过中断绑定到不同的核上,以满足网卡的需求。

图1.1是Intel 82575硬件逻辑图,有四个硬件队列。当收到报文时,通过hash包头的SIP、Sport、DIP、Dport等元组信息,将同一条流总是收到相同的队列。同时触发与该队列绑定的中断。

在这里插入图片描述

图1.1 82575硬件逻辑图

2.什么是RSS

RSS(Receive Side Scaling)是一种能够在多处理器系统下使接收报文在多个CPU之间高效分发的网卡驱动技术。

  • 网卡对接收到的报文进行解析,获取IP地址、协议和端口五元组信息
  • 网卡通过配置的HASH函数根据五元组信息计算出HASH值,也可以根据二、三或四元组进行计算。
  • 取HASH值的低几位(这个具体网卡可能不同)作为RETA(redirection table)的索引
  • 根据RETA中存储的值分发到对应的CPU

基于RSS技术程序可以通过硬件在多个CPU之间来分发数据流,并且可以通过对RETA的修改来实现动态的负载均衡。

3.对称RSS

在网络应用中,如果同一个连接的双向报文在开启RSS之后被分发到同一个CPU上处理,这种RSS就称为对称RSS。 对于需要为连接保存一些信息的网络应用来说,对称RSS对性能提升有很大帮助。 如果同一个连接的双向报文被分发到不同的CPU,那么两个CPU之间共享这个连接的信息就会涉及到锁,而锁显然是会影响性能的。

RSS一般使用Toeplitz哈希算法,该算法有两个输入:一个默认的hash key和从报文中提取的五元组信息。 DPDK使用的默认hash key是微软推荐的,具体定义见lib/librte_pmd_e1000/igb_rxtx.c:1539, 同一个连接的不同方向使用这个默认值计算出来的hash值是不一样的。

具体讲就是{src: 1.1.1.1, dst: 2.2.2.2, srcport: 123, dstport: 456}和{src: 2.2.2.2, dst: 1.1.1.1, srcport: 456, dstport: 123} 计算出来的hash值是不一样的,hash值不一样就会导致两个方向的报文被分发到不同的接收队列,由不同的CPU进行处理。

4.在DPDK中配置RSS

DPDK支持设置静态hash值和配置RETA。 不过DPDK中RSS是基于端口的,并根据端口的接收队列进行报文分发的。 例如我们在一个端口上配置了3个接收队列(0,1,2)并开启了RSS,那么 中就是这样的:
{0,1,2,0,1,2,0…}
运行在不同CPU的应用程序就从不同的接收队列接收报文,这样就达到了报文分发的效果。
在DPDK中通过设置rte_eth_conf中的mq_mode字段来开启RSS功能, rx_mode.mq_mode = ETH_MQ_RX_RSS
当RSS功能开启后,报文对应的rte_pktmbuf中就会存有RSS计算的hash值,可以通过pktmbuf.hash.rss来访问。 这个值可以直接用在后续报文处理过程中而不需要重新计算hash值,如快速转发,标识报文流等。
RETA是运行时可配置的,这样应用程序就可以动态改变CPU对应的接收队列,从而动态调节报文分发。 具体通过PMD模块的驱动进行配置,例如ixgbe_dev_rss_reta_update和ixgbe_dev_rss_reta_query。

二、 Flow Director

Intel 以太网Flow Director技术(Intel Ethernet Flow Director,简称FDIR)是Intel公司提出的根据包的字段精确匹配,将其分配到某个特定队列的技术。

在这里插入图片描述
图8-6 Flow Director与队列选择

从图8-6可以了解到Flow Director是如何工作的:网卡上存储了一个Flow Director的表,表的大小受硬件资源限制,它记录了需要匹配字段的关键字及匹配后的动作;驱动负责操作这张表,包括初始化、增加表项、删除表项;网卡从线上收到数据包后根据关键字查Flow Director的这张表,匹配后按照表项中的动作处理,可以是分配队列、丢弃等。其中关键字的选取同8.2.1节中所述,也与包的类型相关,表8-2给出了Intel网卡中它们的对应关系。更为灵活的是,使用者也可以为不同包类型指定关键字以满足不同的需求,比如针对IPV4 UDP类型的包只匹配目的端口,忽略其他字段。

在这里插入图片描述

表8-2 Flow Director关键字

相比RSS的负载分担功能,Flow Director更加强调特定性。比如,用户可以为某几个特定的TCP对话( S-IP + D-IP + S-Port + D-Port)预留某个队列,那么处理这些TCP对话的应用就可以只关心这个特定的队列,从而省去了CPU过滤数据包的开销,并且可以提高cache的命中率。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java 中,可以使用多线程和队列来实现控制。以下是一个简单的示例代码: ```java import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class QueueFlowControlExample { public static void main(String[] args) { BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(10); // 创建大小为10的阻塞队列 ExecutorService executorService = Executors.newFixedThreadPool(5); // 创建线程池 // 生产者线程,将任务加入队列 Thread producerThread = new Thread(() -> { try { for (int i = 0; i < 100; i++) { queue.put(() -> { // 执行任务的逻辑 System.out.println("Task executed"); }); } } catch (InterruptedException e) { e.printStackTrace(); } }); // 消费者线程,从队列中取出任务并执行 Thread consumerThread = new Thread(() -> { try { while (true) { Runnable task = queue.take(); executorService.execute(task); } } catch (InterruptedException e) { e.printStackTrace(); } }); producerThread.start(); consumerThread.start(); } } ``` 在上述示例中,我们创建了一个大小为10的阻塞队列,并创建了一个固定大小为5的线程池。生产者线程不断地将任务放入队列中,消费者线程从队列中取出任务并提交给线程池执行。 通过控制队列的大小,我们可以限制并发执行的任务数量。当队列已满时,生产者线程会被阻塞,直到队列中有空闲位置。这样就实现了简单的控制。 需要注意的是,上述示例只是演示了基本的控制原理,并没有考虑线程池的关闭和异常处理等情况。在实际应用中,你可能需要根据具体需求进行适当的调整和完善。 另外,还可以根据具体需求使用其他类型的队列,如 LinkedBlockingQueue、PriorityBlockingQueue 等,或者使用自定义的队列实现。根据实际情况,也可以使用其他并发工具类来实现控制,如信号量、计数器等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值