专栏首页IT技术精选文摘ContainerDNS性能优化之路 17W到1000W QPS超高性能DNS技术实践

ContainerDNS性能优化之路 17W到1000W QPS超高性能DNS技术实践

一、 引入

随着TIG阿基米德平台全面应用。组成京东容器生态技术栈的分布式域名解析服务ContainerDNS(go版https://github.com/tiglabs/containerdns )全量生产环境应用,承载着每天百亿的访问量,单实例峰值每秒请求达到15W QPS,已经接近ContainerDNS的性能极限(17W QPS)。为了更好的提高系统的并发服务,对ContainerDNS 的优化也势在必行。

本文对ContainerDNS性能优化思考和技术实践历程,希望对业内在容器领域和域名解析方向技术实践一些启迪。

ContainerDNS 的DNS Server 代码用Go 语言实现,我们在后期的优化中,通过各种尝试,并通过pprof 采集数据分析,发现性能损耗最大的是收发包的地方。同时我们对bind9 进行了压测、采集分析发现同样是收发包函数最为耗时。

数据平面开发套件DPDK(Data Plane Development Kit)可以极大提高数据处理性能和吞吐量,提高数据平面应用程序的工作效率。灵感来自TIG容器生态技术栈另外一个重要的服务高性能负载均衡服务Jupiter (https://github.com/tiglabs/jupiter )实现单实例200万QPS的高性能。因此TIG团队工程师想到用DPDK 来实现DNS数据报文的收发是一个有挑战和前景的尝试。

二、系统概述

让我们先来回顾下ContainerDNS设计之初的愿景和初心。ContainerDNS作为京东商城新一代软件定义数据中心的关键基础服务之一,具有以下特点:

  • 分布式设计 多数据中心数据同步复制 避免维护多个域名解析元数据副本
  • 支持自动发现服务域名 支持容器Service
  • 支持后端探活
  • 易于维护、易于动态扩展

图一 ContainerDNS 架构图

ContainerDNS 包括四大组件 DNS server、service to DNS 、user API 、IP status check。这四个组件通过etcd 数据库集群结合在一起,彼此独立,降低了耦合性,每个模块可以单独部署。DNS server 用于提供DNS 查询服务的主体。service to DNS 组件是k8s 集群与DNS server的中间环节,会实时监控k8s集群的服务的创建,将服务转化为域名信息,存入etcd 数据库中。user API 组件提供restful api,用户可以创建自己的域名信息,数据同样保持到etcd数据库中。IP status check 模块用于对系统中域名所对应的ip做探活处理,数据状态也会存入到etcd数据库中。如果某一个域名对应的某一个ip地址不能对外提供服务,DNS server 会在查询这个域名的时候,将这个不能提供服务的ip地址自动过滤掉。

三、 KDNS系统设计与实现

DNS server 是提供DNS的主体模块实现架构如下图:

如上图所示,系统中用到的CPU核有两种角色:主核和从核。主核相当于控制通道,域名数据、交给协议栈的数据都是主核处理。从核主要处理数据通道的数据,通过DPDK网口收包,报文解析处理,解析结果发包给用户。

Data Plane Development Kit(DPDK):是运行在Linux用户态,实现X86通用平台网络报文快速处理的库和驱动的集合,其主要特点:

  • 多核编程框架及CPU亲和性
  • 巨页(HugePage),减少页表项数目,降低TLB miss
  • 无锁队列
  • UIO支持,用户态驱动,减少报文copy
  • poll-mode网卡模式,无中断轮询收包

下面是主核的处理流程:

从核的处理逻辑较为简单,首先调用处理主核发过来的域名数据,从而及时改变自己的域名数据缓存信息。然后调用DPDK收包函数rte_eth_rx_burst 收取报文,如果有数据则进行数据包解析处理,参考下面的协议解析处理模块。如果是本地zone 的域名查询,将查询的结果直接发送给客户端。如果是ARP请求,则将数据包放入kni-pkt-ring 中交由主核处理。如果是转发域名,则交由转发报文处理线程处理。

数据收发模块:采用DPDK的收发包接口,开DPDK启RSS (Receive Side Scaling,多 CPU之间高效分发的网卡驱动技术),由于DNS 访问基本是UDP包端口是53,RSS采用了对IP和端口进行Hash的方式,当客户端很多的时候可以有效地实现多核的均衡。为了更好地提高性能,系统中每一个从核只处理一个收包队列上面的数据。发包也是只发送对应队列上的数据。所以收发包数据间,所有的核都是独立的,没有任何耦合不需要任何锁机制,更加快速。

协议解析处理模块:每一个从核通过DPDK 接口收到数据包,进行数据包解析。并将结果返回给客户端。流程图如下:

转发报文处理模块:系统所有的域名数据都是基于某一个或者多个zone进行的,如果域名不在本地支持的zone内就要将请求发送给上级的DNS Server,比如我们的DNS Server 支持本地的zone是 tst.local,也就是说所有访问*.tst.local的域名本地的DNS Server 都会查询解析,如果用户访问的不是*.tst.local的域名就得转发给上级的DNS 进行解析,这个转发的处理流程较慢,我们采用了一组后台的线程进行处理,这些线程不会绑定到CPU上,完全与主核、从核的功能分离开来,这样主、从核都不会处理这样的慢速数据请求。

首先数据处理从核收到数据包,发现如果请求的域名不是本地的zone配置的域名后缀,走慢速流程即转发流程。从核会将本请求入放在和转发处理线程共享的数据队列中,这样做的好处是把从核解放出来,只处理快速的查询请求,不会block住,从而能全速的处理本地数据。转发报文处理线程是一个死循环,首先从队列中读取数据,没有数据则休眠。如果有数据则将预处理数据并调用转发接口转发给上级DNS Server,并将上级DNS Server的回包处理后放入与主核共享的rte_mbuf无锁队列中。主核会及时的出队转发报文处理线程放入的数据,调用DPDK的网卡发送接口,将数据从主核的发送队列发送出去。需要说明的是这期间数据都是公用一个rte_mbuf 内存,没有任何的数据复制的过程,从而更好地提高性能。

域名信息数据处理模块: 这个是一个后台的线程提供Restful API,可以和agent进行数据交互,从而获取系统的域名数据。

首先注册支持url和方法,目前支持GET、POST、DELETE分别对应着域名的查询、增加、删除三个接口。同时提供状态的查询接口,目前只有两种状态Init和Runing,当agent 检测到进程是刚启动(Init 状态)时,会将所有的域名信息下发到DPDK DNS Server,之后将DPDK DNS Server的状态设置为Runing状态。后面如果有域名信息变更,agent 会调用POST或者DELETE 接口将域名数据同步到DNS Server。为了提高数据的安全性,DNS Server的API支持ssl证书,这样可以有效的防止域名数据被恶意的窃取、修改。同时域名数据插入删除操作的时候,采用了Hash 表的设计,每一个域名先计算出Hash值,如果发生冲突先比较Hash值,如果相同再进行字符串匹配。由于Hash值远远大于Hash桶的长度,当发生Hash冲突的时候先匹配Hash值会增加大大提高匹配的效率。

ARP/BGP报文处理:这模块较为简单,从核解析数据包如果发现是ARP协议报文,将数据传送给主核,主核在将数据通过DPDK的KNI将数据报文发给Linux 协议栈,主核后面再通过KNI 读取Linux协议栈处理的结果,然后调用DPDK的发送接口,将数据发送出去。BGP 协议的处理模式类似,也是交与Linux 内核协议栈处理。

四、性能优化及测试

  1. 恰当地使用rte_prefetch0(),可以减少cache-miss次数
  2. likely()和unlikely()的使用,可以减少分支预测失败的次数
  3. 数据处理全程无锁,交互部分利用无锁队列实现
  4. 整个处理过程无包copy,发送包复用收包的mbuf内存,减少mbuf的申请

性能测试:

1)测试环境

CPU:Intel(R) Xeon(R) CPU E5-2698 v4 @ 2.20GHz NIC:intel 82599ES 10-Gigabit SFI/SFP+ Network Connection

2)测试配置

KDNS(八个数据核一个控制核),bind9 (16个核,版本bind-9.10.6-P1)

3)测试结果

bind9 五分钟单域名测试结果(47W QPS):

上图是bind9 稳定运行5分钟的数据采集结果,平均47W QPS。

KDNS 20分钟单个域名测试结果(1000W QPS):

如上图所示,优化后的KDNS性能达到1000万QPS,而且二十分钟运行很平稳,并发性能是bind9 20多倍、ContainerDNS(go版)的50倍。

KDNS 多个域名测试结果,其中系统域名记录大概20亿条。

相同网络环境下响应时间对比(queryperf 测试):

Queryperf数量

最慢响应us(bind9/ KDNS)

最块响应us(bind9/ KDNS)

平均响应us(bind9/ KDNS)

1

1140/226

15/16

102/68

3

1138/654

18/17

172/83

如上图所示,可以看到在相同的测试服务器、客户端主机、网络的环境下测试,利用DPDK收发包实现的DNS,对于访问的响应更加优秀和稳定,最慢响应由bind9的1140微妙提高到226微妙,平均响应时间也提高了一倍。

五、总结

本文主要介绍了KDNS,一种基于Intel DPDK平台开发的DNS Server。其接近网卡线速处理能力,灵活的部署,多样的监控以及可靠的稳定性,同时兼顾ContainerDNS的所有的分布式模块功能。作为TIG阿基米德平台京东数据中心操作系统(JDOS)的一个重要的组成部分,在京东数据中心发挥至关重要的作用。

本文分享自微信公众号 - IT技术精选文摘(ITHK01)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-03-25

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 基于Kubernetes集群部署skyDNS服务

    在之前几篇文章的基础,(Centos7部署Kubernetes集群、基于kubernetes集群部署DashBoard、为Kubernetes集群部署本地镜像仓...

    用户1263954
  • 面试题:Redis 的持久化有哪几种方式?

    redis 的持久化有哪几种方式?不同的持久化机制都有什么优缺点?持久化机制具体底层是如何实现的?

    用户1263954
  • Nginx/LVS/HAProxy负载均衡软件的优缺点详解

    PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,参考了一些资料,结合自己的一些使用经验,总结一下。 一般对...

    用户1263954
  • 好雨云帮一周问答集锦(1.2-1.8)

    Rainbond开源
  • 保证网站访问安全,没它真不行......

    DNSSec  DNSSEC(Domain Name System Security Extensions,也叫“DNS安全扩展”)是一种使用密码学方法解决D...

    腾讯云DNSPod团队
  • CDN静态资源加速

    静态资源访问的关键点是就近访问。可以考虑在业务服务器的上层加一层特殊缓存,即CDN。

    汐楓
  • Pandas读书笔记0(Anaconda与jupyter安装)

    今天和大家分享一个编辑Python的神器!--Jupyter! 之前使用的是Python自带的IDLE,作为自带的系统,是和IE浏览器一样的存在! 用一张老图...

    用户1332619
  • 记一次对某企业的渗透测试实战

    顾翔老师开发的bugreport2script开源了,希望大家多提建议。文件在https://github.com/xianggu625/bug2testscr...

    小老鼠
  • Cloudflare 1.1.1.1公共DNS上线Cloudflare Public DNS

    Zach
  • 机器学习入门秘笈

    上周,我看到一些非常好的机器学习备忘单(http://t.cn/RY8iUgc),我想这对刚接触机器学习的工程师来说应该是极有帮助的。但是图片超不清晰,花费很多...

    AI研习社

扫码关注云+社区

领取腾讯云代金券