3

千万并发连接下,如何保障网络性能

 2 years ago
source link: https://my.oschina.net/qcloudcommunity/blog/5306783
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

千万并发连接下,如何保障网络性能 - 腾讯云技术社区 - OSCHINA - 中文开源技术交流社区

 up-50581929a59758dd7cab2d15c8de597569c.jpg

过去几十年互联网呈爆发式的增长,内容的丰富以及层出不穷的DDoS攻击等,对网络性能提出了极大的挑战,也同样促进了网络基础设施的快速发展。运营商的带宽越来越大,CPU/网卡等硬件的性能也会越来越强。但在很长时间内,软件的性能提升落后于硬件的性能提升,并严重限制了应用程序的性能,大部分时间不得不依靠堆机器来应对,造成了大量的资源浪费和成本提高。

随着软件的不断发展,在新世纪的第一个10年时,通过多线程和事件驱动(kqueue/epoll等)解决了C10K的问题。但是在第二个10年却不堪重负,亟需新的解决方案来应对网络流量的增长。

比如腾讯云对外提供的HttpDNS服务每隔几个月请求量都会翻倍,对高性能的网络处理和用户态协议栈都有强烈的需求。HttpDNS早期使用的内核协议栈只能做到单机不到10万QPS的TCP 短连接服务。随着技术的进步和发展,如REUSEPORT等,后续内核协议栈也可以做到几十万QPS了,但依然存在非常大的横向扩展瓶颈。基于这样的瓶颈下,腾讯云迫切需要一个高性能的网络服务框架,所以选择了通过DPDK+用户态协议栈来进行内核旁路来提升网络性能。

Robert David Graham 在2013年针对C10M的演讲中,对于如何达到千万并发连接,最主要的观点就是内核才是阻碍性能提升的问题,我们应该绕过内核(kernel by pass,内核旁路)以及大量其它的技术优化,如轮询、零拷贝、Hugepage等。

Linux内核后续引入的eBPF和XDP同样能够大幅提升网络性能,但是其提升性能的本质依然是绕过内核,目前还未能对Intel DPDK生态造成实质的冲击,尤其是对高内核版本和网卡驱动的依赖,严重限制了在企业的使用推广。

在此次演讲之前,相关的技术已经得到了一定的应用,如演讲中提到的PF_RING,Netmap,IntelDPDK等数据驱动,腾讯云DNSPod在2012年就已经完成了相关软硬件的调研选型工作,并最终选择DPDK(此时尚未开源)实现了新一代的权威DNS服务器达到了单10GE 1100万 QPS的性能,大幅提升了DNS的常规解析和抗攻击能力。但是确实直到该演讲出现后,相关技术才在业界得到了大规模的开发应用,尤其是从中脱颖而出的DPDK,几乎成了高性能网络程序的标配。而我们也是在16年的时候将权威DNS中使用DPDK的网络模块单独抽出来作为一个独立的通用的网络框架,可以复用到多个业务上提升网络性能,也就是现在的F-Stack

F-Stack介绍及技术特点

F-Stack是一个全用户态的高性能的网络接入开发包,基于DPDK、FreeBSD协议栈、微线程接口等,用户只需要关注业务逻辑,简单的接入F-Stack即可实现高性能的网络服务器。将网络包进行内核旁路到应用层进行处理虽然大幅提升了网络性能,但是也无法再使用内核的网络协议栈了,这对4层以下以及简单的UDP 7层应用影响不大,但是对其他的7层应用来说,一个成熟的用户态协议栈是必须的,所以F-Stack就是腾讯云DNSPod给出的方案。

F-Stack是基本完整的网络编程框架,相当于用胶水粘合了了DPDK网络I/O模块、FreeBSD用户态协议栈、POSIX Like API,异步编程接口、部分上层应用等,供用户接入使用。

使用纯C开发(部分第三方组件使用了C++,F-Stack进行了封装),容易上手,但也要求用户有一定的DPDK使用基础。使用BSD 2-Clause开源协议,对商业使用非常友好。那对于F-Stack都有哪些技术特点呢?接下来将继续介绍。

多进程架构,轮询模式

这里是F-Stack的一个基本架构,采用多进程模型,全用户态,每个进程与一个CPU核心、网卡收发队列进行绑定,拥有更好的内存局部性,避免缓存失效,且进程内部使用轮询模式,无锁、无调度、无上下文切换。

1620

F-Stack 目前采用多进程架构,各进程拥有自己进程独立的协议栈,应用接口和应用层业务逻辑,规避了内核的多种性能瓶颈,各个进程间无数据共享,有非常好的横向扩展能力。

DPDK 开发套件

DPDK是广泛使用的数据平面开发套件,此处不再对其本身进行过多介绍。

F-Stack对DPDK版本的选用上除了初始开源版本使用了16.07版本之外,很快升级并一直保持使用DPDK的LTS版本(xx.11)版本,但一般会在最新的LTS版本发布之后数个月在dev分支进行升级支持,并在更晚之后的时间(一般1年左右)正式发布,如目前F-Stack主力稳定的1.20和1.21版本分别使用了DPDK 18.11.x和19.11.x版本,在开发分支中则支持了20.11.x版本。

FreeBSD 协议栈

F-Stack对于选用FreeBSD协议栈进行用户态移植,背后其实是有过很多的思考和尝试的,此处仅列觉几个FreeBSD协议栈的优点,更多信息可以通过后面的 F-Stack 背景故事进行了解。

1. 协议栈功能完善,且有大量工具可以对网络进行调试分析,如sysctl、ifconfig、netstat、netgraph、ipfw、ndp等。

2. 可以跟进社区的改进,无需自己开发维护,有原始用户态移植可供参考,大幅减少工作量,见libplebnetlibuinet

3. 相比Linux的协议栈实现复杂,FreeBSD的代码更清晰易懂;Linux遵循GPL协议开源,可能会限制部分用户的使用。

F-Stack 目前发布版本均基于 FreeBSD releng 11.0 版本,并移植了部分后续版本的patch,功能完善但也冗余(去除了部分模块未编译进F-Stack,如SCTP,IPSEC等),调试分析工具完善,运行稳定。后续则会升级到 FreeBSD releng 13.0 版本,并将持续跟进社区的重大改进。

POSIX 兼容接口

F-Stack提供了POSIX like接口,前缀为“ff_”,如“ff_socket”“ff_bind”等,并提供了“ff_kqueue”事件驱动接口并同时基于kqueue封装了“ff_epoll”接口,除“ff_epoll”接口的使用上与linux系统接口略有区别外,其他接口用法完全兼容,现有程序可以做到简单改动即可接入。

需要注意的是,虽然接口用法完全兼容,但是因为很多标记位在Linux和FreeBSD系统的定义并不相同,F-Stack接口内部会进行定义的转换,但是并不能保证100%支持,尤其是后续新增的标记定义,也需要持续进行更新维护

POSIX like接口对原有应用的移植是友好的,并且使用上也比较安全,但是因为涉及到内存拷贝,所以性能上并不能达到最优,后续 F-Stack 也会提供一套独立的零拷贝 API 供有需要的用户选用。

微线程框架

F-Stack 应用程序必须使用异步模式接口进行编程,但也同时提供了微线程(协程)框架,可以供用户进行同步编程,异步执行。

微线程框架使用了同为腾讯开源的 MSEC 中的一部分 micro_thread,需要特别注意的是微线程模块的开源协议是GPL-2.0,并不是F-Stack 主要的必须核心模块,对 F-Stack 主体开源协议并无影响,但是如果用户以 micro_thread 模块进行应用开发,则需关注开源协议可能造成的影响。

F-Stack目前是提供 lib 库接入的方式,需要与业务应用程序一起编译打包,并直接提供了已经移植好的 Nginx 和 Redis 应用供用户直接使用。

对于部分原多线程架构的应用程序,尤其是有资源共享时,为了达到更好的性能和横向扩展能力,我们的建议是尽量能够拆分并减少资源的共享。如果实在无法拆分,F-Stack后续也会考虑提供独立的网络 I/O 和协议栈模块,但是性能的下降也将不可避免。

这里我们先来看下Nginx分别使用F-Stack和内核协议栈的一个性能对比,分别是短链接和长链接,需要说明的是内核协议栈也是经过了多种调优之后的测试数据,比如网卡队列、worker的 CPU 亲和性绑定,开启 REUSEPORT 和其他内核网络参数的优化调整。

1620
1620

这里F-Stack对内核协议栈都有明显的提升,但是其中超过12核之后的短链接的提升尤其明显,F-Stack 对大部分高并发的网络应用场景都有较好的性能优化和使用价值,其中最适合的是超大并发的 TCP 短链接业务场景,这也是我们HttpDNS的主要业务场景。

当然,想要全面的了解F-Stack的业务应用,就必须要从其发展历史的开启来看待。

F-Stack 发展历史

目前对外开源的 F-Stack已经是3.0版本,1.0版本是12-13年 DNSPod的权威 DNS 选用 DPDK 来提升性能时候,是一个简易的用户态 TCP 协议栈用来支持 TCP DNS,13年上线后一直在线上持续运行,近两年已经全部升级到3.0了。

为了支持 DNS 业务的快速发展,不能缺少一个高性能的用户态协议栈,而维护一个功能完善的 TCP 协议栈需要耗费大量的精力,这也是开发 F-Stack 2.0和3.0的一个很重要的原因。

16年的时候当时的 leader拍板下,我们放弃了继续维护1.0的协议栈,选用开源协议栈进行适配升级并对外开源,通过调研先选择了 seastar(排除了MTCP、LwIP等),并在当年做了2.0版本,也做了一些应用适配,比如 HttpDNS,腾讯云动态加速CDN(DSA,现在已经合并到全站加速ECDN中)等,但是理想是美好的,现实是残酷的,虽然基于F-Stack2.0版本的 HttpDNS在实验室表现堪称完美,性能优异,可扩展插件式架构等,但是在现网少量灰度运营时踩了无数坑,这和Seastar本身的使用场景是相关的,作为 ScyllaDB的组件,其主要应用场景是在内网的,并不能很好的适应外网复杂的网络环境。

在团队填了不少坑,也提交了多个 Pull Request到Seastar后我们发现又陷入了1.0版本的循环,所以坚持一段时间后还是放弃了 Seastar,转而从更成熟的 Llinux和 FreeBSD 协议栈中选择了 FreeBSD 来开发 F-Stack 3.0,也就是目前对外开源的版本。当然 F-Stack 2.0 的框架其实也并没有完全废弃,虽然在主要服务于外网的 HttpDNS上水土不服,但是在以内网互联加速为主要场景的CDN动态加速 DSA 中是运行了多年才进行升级的。

17年上半年我们基于 DPDK 和 FreeBSD 协议栈开发完成了 F-Stack 3.0,并对外开源,并很快重新适配了 HttpDNS,因为 HttpDNS的请求量一直在快速增长,业务性能压力非常大,所以优先适配 HttpDNS,并逐步上线对外提供服务,虽然后续也遇到了一些问题,但是都很快优化并稳定下来,到目前支撑了日请求量万亿的HttpDNS请求并保持了10倍

F-Stack 开源版本历史

  • 2017.4.14 正式开源
  • 2017.11.27 Release 1.11
  • 2018.5.21 Release 1.12
  • 2019.11.15 Release 1.13
  • 2019.11.23 Release 1.20
  • 2021.1.29 Release 1.21

F-Stack ROADMAP

目前 F-Stack 也一直在持续维护中,预计2021年底至2022年初将发布1.22版本,可能包含以下新特性

  • DPDK 20.11,dev 分支已经升级支持,相比19.11之前在编译和使用方式上有很大区别,仅支持使用 meson/ninja 进行编译。
  • FreeBSD 13.0,dev 分支已经升级支持,但是目前尚未完全稳定,依然存在一些问题,如 BBR/RACK 尚不能正常工作,多进程性能存在部分问题待优化,部分工具的部分功能异常(如ff_netstat对监听端口的查看等),还需进一步调试优化。
  • 新的零拷贝接口支持。
  • 原有应用一键移植支持,提供的独立的网络 I/O 和协议栈模块,提供类似 LD_PRELOAD 或其他方式简化应用移植门槛,但一定会导致性能下降。
  • Nginx-1.20 支持。
  • Redis 6支持。
  • 接收端网卡分流的默认方式由 RSS 修改为 Flow Director,但依然保持现有默认的 RSS 策略。

【注意】以上功能会视具体时间安排调整,部分功能将很可能无法包含在1.22版本中发布,将会顺延至后续版本进行支持。

F-Stack实践案例

F-Stack 自从开源后获得了全球大量研究机构、高校、公司的肯定,用于进行技术研究工作或线上商业化项目,那在这里会给大家仅列举 F-Stack 用户实际现网业务的实践案例

  • 腾讯云HttpDNS

HttpDNS 服务主要用于移动端 APP,解决其默认 DNS 大量存在的解析失败,解析结果跨网,解析劫持等问题,目前各大 TOP APP 大部分都有使用此类技术,而腾讯云DNSPod 作为最早推出商用 HttpDNS 服务,目前服务大量用户,日请求量万亿级,历史版本介绍可参考公众号“鹅厂网事”上的文章《千亿级HttpDNS服务是怎样炼成的》,当然目前最新的HttpDNS 也已经迭代更新了多个版本,新的专业版支持了更多的特性功能,如IPv6,DNSPod 权威数据推送,用户自定义域名解析,危险域名拦截(用户自定义是否开启及拦截哪些类别的危险域名),黑白名单,请求统计等一系列功能,也都构建在 F-Stack 基础架构之上。

  • DNSPod 权威DNS

作为 F-Stack 的父项目,DNSPod 权威 DNS 为近千万域名提供权威解析服务,受益于 F-Stack 的高性能网络服务,最新版本的权威 DNS 已经在百G机型上达到了单机 1 亿 QPS 的性能,具体见本人之前的一篇文章基于 F-Stack 的权威 DNS 单机 1 亿 QPS 性能优化实践,目前 DNSPod 总线上容量达到了数十亿 QPS,结合腾讯集团遍布全球的大带宽节点部署和先进的防护设备及算法,DNSPod 在客户无感知情况下多次成功防护 TB 级以上的 DDoS 攻击,最近一次发生在2021.8.27周五下午,多种攻击方式混合攻击,平台受攻击合计峰值超过5T。

  • 其他用户态协议栈介绍

VPP 由思科主导,多个大厂参与,其用户态协议栈 Host Stack 由思科交换机协议栈发展而来,开源时间晚于 F-Stack,但是是目前社区活跃度最高的用户态协议栈。

MTCP Stack 来自韩国 KAIST,在业界也有广泛的使用,主要问题是如其名字所示仅支持 TCP。

Seastar

Seastar作为ScyllaDB的子项目,其 Native stack 在内网有较好的表现,内网场景使用较多。

LwIP 来自瑞典计算机科学院,轻量级协议栈,主要用于嵌入式系统等,但也有不少厂商基于 LwIP 进行修改移植支持自己的应用。

欢迎点击一键订阅《云荐大咖》专栏,获取更多精品内容。

看云端技术起落,听大咖指点迷津。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK