全用户态网络开发套件F-Stack架构分析

F-Stack是一个全用户态(kernel bypass)的高性能的网络接入开发包,基于DPDK、FreeBSD协议栈、微线程接口等,适用于各种需要网络接入的业务,用户只需要关注业务逻辑,简单的接入F-Stack即可实现高性能的网络服务器。 本文介绍F-Stack的详细架构及如何解决内核协议栈面临的问题。

传统内核协议栈的性能瓶颈

在传统的内核协议栈中,网络包处理存在诸多瓶颈,严重影响网络包的收发性能。性能瓶颈主要包括以下几个方面

  1. 局部性失效 - 一个数据包的处理可能跨多个CPU核心、缓存失效、NUMA不友好 一个数据包可能中断在cpu0,内核态处理在cpu1,用户态处理在cpu2, 这样跨越多个核心,造成局部性失效,CPU缓存失效, 同时可能存在跨NUMA访问内存,性能受到很大影响。
  2. 中断处理 - 硬件中断、软中断、上下文切换 当网络中数据量很大时,大量的数据包产生频繁的硬件中断请求, 这些硬件中断可以打断之前较低优先级的软中断或者系统调用的执行过程, 如果这种打断频繁进行的话,将产生较高的性能开销。 用户态内核态的上下文切换和软中断都增加了额外的开销。
  3. 内存拷贝 - 内核态和用户态之间的内存拷贝 网络数据包从网卡到应用程序需要经过如下的过程: 数据从网卡通过DMA等方式传到内核开辟的缓冲区; 数据从内核空间复制到用户态空间。 在Linux内核协议栈中,这个耗时甚至占到了数据包整个处理流程的一半。
  4. 系统调用 - 软中断、上下文切换、锁竞争 频繁到达的硬件中断或者软中断都可能随时抢占系统调用的运行,这也将产生大量的上下文切换开销。 内核中一些资源如PCB表等都需要加锁处理,大量的并发操作造成很大的性能浪费,特别是大量短连接的创建。

F-Stack总体架构

无共享架构

F-Stack使用了多进程的无共享架构,每个进程CPU、网卡队列绑定,具有无竞争、零拷贝、线性扩展、NUMA友好等特点。

  • 各进程绑定独立的网卡队列和CPU,每个NUMA节点使用独立的内存池,请求通过设置网卡RSS散落到各进程进行处理,解决了局部性失效的问题。
  • 使用DPDK的轮询模式,排除中断处理造成的性能影响。
  • 使用DPDK作为网络I/O模块,将数据包从网卡直接接收到用户态,减少内核态到用户态的内存拷贝。
  • 请求平均分配到每个核上,通过设置DPDK的rss hash函数保证相同ip、port的请求落到同一个核上。
  • 各进程拥有独立的协议栈、PCB表等资源,消除了协议处理过程中的各种资源竞争。
  • 进程之间不共享内存,通过无锁环形队列(rte_ring)传递通信,如ARP包等。

用户态协议栈

移植FreeBSD协议栈至用户态。 通过外加头文件、宏控制、以及hook相关实现进行的移植,对FreeBSD源代码的修改不到100行, 对后续的跟进社区,升级版本非常友好。

  • 内存分配相关函数重新hook实现。(当前使用mmap和malloc,后续会替换成rte_mempool和rte_malloc)
  • 定时器使用rte_timer驱动,ticks定时更新,timecounter定时执行。
  • 移除内核线程、中断线程等,统一进行轮询处理。
  • 移除文件系统相关的绑定。
  • 移除FreeBSD内核中的所有锁,用空的宏替换掉。
  • 其他glue code。

类posix接口和微线程框架

提供了类posix接口和微线程框架,方便现有应用接入,替换接口。 后续我们会提供类似LD_PRELOAD的方式,使得现有程序尽量无改动迁移到F-Stack。 微线程框架,移植自腾讯开源的毫秒服务MSEC里使用的spp_rpc。 具有同步编程、异步执行的特点,无需处理复杂的异步逻辑。

问题及优化

  • CPU 100% 由于使用的DPDK轮询模式,cpu使用率会一直是100%, 后续会引入DPDK的轮询+中断模式,当连续几次轮询没有收到包后, 转为中断模式,有包后持续轮询,直到又没包进来。
  • 常规网络工具(如tcpdump、ifconfig、netstat等)无法使用 由于DPDK接管了网卡,所有的数据包都运行在用户态,常规的网络工具都无法使用, 为此我们对一些工具进行了移植,目前已经完成了sysctl、ifconfig。 抓包可以在config.ini里配置开启,抓包文件也可以在wireshark里直接分析。
  • Nginx reload 当前F-Stack的Nginx是运行在NGX_PROCESS_SINGLE模式下的, 各个进程互不关联,无法使用原有的reload命令。后续会进行修复。

最佳实践

  • 使用性能高的多核CPU,配置config.ini里的lcore_mask(进程运行在哪些cpu上)运行多个进程。
  • 使用10G、25G、40G的多队列网卡,支持硬件卸载功能,支持的RSS队列数越多越好。
  • 配置尽可能多的Hugepage。
  • 配置config.ini关闭抓包。

Roadmap:

  • 继续移植各种网络配置工具,方便F-Stack在各种网络环境(如GIF/GRE/VxLAN等隧道)下的部署使用。
  • 移植SPDK的用户态驱动至F-Stack,提升磁盘I/O性能。
  • 增加对数据流的HOOK点/镜像等,方便对数据包进行自定义处理。
  • 提供协议栈的相关优化模块,如TCP加速、防护等。
  • 类posix接口提供LD_RRELOAD方式,简化已有应用的接入方式。
  • 提供PHP/Python等语言的接口封装,方便相关WEB服务的快速接入。

原文发布于微信公众号 - FStack(F-Stack)

原文发表时间:2017-06-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JAVA高级架构

Redis面试题及分布式集群

29910
来自专栏FreeBuf

CVE-2017-4918:VMware Horizon的macOS客户端代码注入漏洞分析

本文我们将探讨如何通过 VMware Horizon macOS客户端版本4.4.0 (5164329)中存在的代码注入漏洞获取本地root权限。在此文发布前我...

27730

如何在Linux上搭建Terraria 游戏服务器?

Terraria是一款二维沙盒游戏,类似于Minecraft(我的世界),允许玩家在开放的世界中探索,构建和战斗。2015年,Terraria开发者宣布支持Li...

77730
来自专栏杨建荣的学习笔记

Datapump数据迁移前的准备工作(r9笔记第31天)

其实对于Datapump迁移而言,如果参与过XTTS,OGG,Veritas SF,外部表增量等迁移方式的话,会发现Datapump还是很简单清晰的,一个优点...

28230
来自专栏智能合约

crontab定时任务详解

30840
来自专栏Crossin的编程教室

把你开发的网站免费发布到互联网上(2)

前几天,我们介绍了通过 PythonAnywhere 在互联网上创建一个站点: 把你开发的网站免费发布到互联网上(1) 本篇是上一篇的延续,来讲一讲如何将已有的...

38790
来自专栏pangguoming

Ubuntu 14.04 分区方案

我磁盘大概还有70多G的空间吧,我全部拿来使用的。真实的双系统哦。 一般来讲,linux系统分区最少要包括/和/swap两个。这样据说会影响性能,没有这样安装过...

44160
来自专栏木头编程 - moTzxx

Linux crontab 定时任务整理笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

18520
来自专栏同步博客

我对RPC的理解

  这篇文章将会用最直白的方式介绍RPC,以及实现RPC客户端的Ajax跨域调用的例子。

16740
来自专栏张戈的专栏

解决启用WP-Super-Cache后出现的几个问题

近期,随着新版互推联盟自适应 iframe 代码的推出,调用的博友也慢慢增加了 ,这是很高兴的事情,也有博友反应调用的这个页面加载会有点慢。我来说明一下,因为这...

43560

扫码关注云+社区

领取腾讯云代金券