云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

天翼云_福利百度云_免费申请

小七 141 0

如何使DNS堆栈速度提高3倍

Cloudflare现在已经进入了第6个年头,从一开始,提供权威的DNS一直是基础设施的核心部分。我们已经成长为互联网上最大和最快的DNS管理服务之一,托管了近10万个Alexa top 1M站点和超过600万个其他web属性(或DNS区域)的DNS。CC-BY 2.0图片作者:Steve Jurvetson如今,Cloudflare的DNS服务通过全球选播网络每秒回答约100万个查询(不包括攻击流量)。自然,作为一家成长中的初创企业,我们几年前用于处理数万或数十万个区域的技术随着时间的推移已经过时,无法跟上我们今天拥有的数百万个区域。去年,我们决定更换DNS基础设施的两个核心元素:负责回答权威查询的DNS服务器部分和接受客户对DNS记录所做更改并将其分发到全球边缘机器的数据管道。系统的粗略架构如上图所示。我们将客户DNS记录和其他源服务器信息存储在一个中央数据库中,将原始数据转换为中间边缘可用的格式,然后使用KV(密钥/值)存储将其分发到我们的100多个数据中心(我们称之为POP-存在点)。查询由一个定制的DNS服务器rrDNS提供服务,rrDNS是我们使用和开发多年的。在Cloudflare早期,我们的DNS服务是在PowerDNS的基础上构建的,但在2013年被逐步淘汰并被RRDN取代。Cloudflare DNS团队拥有两个数据流元素:数据管道本身和rrDNS。第一个目标是用全新的东西取代数据管道,因为当前的软件开始显示出它的时代;任何超过5年的基础设施都会这样。现有的数据管道最初是为与PowerDNS一起使用而构建的,并随着时间的推移而逐渐发展。它包含了许多缺点和晦涩的功能,因为它是用来将我们的DNS记录转换成PowerDNS格式的。一种新的数据模型在旧系统中,数据模型相当简单。我们将DNS记录存储在与UI或API中表示的结构大致相同的结构中:每个资源记录(RR)一个条目。这意味着在生成要分发到边缘的区域数据时,数据管道只需执行基本的编码任务。区域元数据和rr是使用JSON和协议缓冲区的混合编码的,尽管我们没有特别好地利用协议的模式化特性,所以模式非常臃肿,最终得到的数据比必要的要大。更不用说,随着我们数据库中总RR的数量达到1亿,这些编码上的细微差异在聚合上产生了显著的差异。这里值得一提的是,DNS在响应查询时并不是按RR来操作的。您可以查询名称和类型(例如example.com网站和AAAA)你会得到一个RRSet,它是RRs的集合。旧的数据格式将rrset分成多个RR条目(每个记录一个键),这通常意味着要多次往返到我们的KV存储来回答一个查询。我们希望更改此设置并按RRSet对数据分组,这样就可以向KV存储发出一个请求,以检索回答查询所需的所有数据。因为Cloudflare对DNS性能进行了大量优化,多次KV查找限制了我们使rrdn尽快运行的能力。同样,对于a/AAAA/CNAME这样的查找,我们决定将值分组到一个"address"键中,而不是每个RRset一个键。这进一步避免了在最常见的情况下执行额外的查找。将密钥挤在一起也有助于减少我们在KV存储之前使用的缓存的内存使用量,因为我们针对单个缓存密钥存储了更多信息。在解决了这个新的数据模型之后,我们需要弄清楚如何序列化数据并将其传递到边缘。如前所述,我们以前混合使用JSON和协议缓冲区,我们决定用纯粹基于MessagePack的实现来代替它。为什么选择MessagePack?MessagePack是一种类型化的二进制序列化格式,但格式中没有构建严格的架构。在这方面,可以认为它有点像JSON。对于读者和作者来说,额外的字段可以是存在的,也可以是不存在的,这取决于应用程序代码的补偿。相比之下,协议缓冲区(或其他格式,如Cap'nproto)需要一个模式,用于以语言无关的格式定义的数据结构,然后为特定的实现生成代码。由于DNS已经有了一个大型的结构化架构,我们不想用另一种语言复制所有的模式,然后再对其进行维护。在使用协议缓冲区的旧实现中,我们没有为所有DNS类型正确定义模式(以避免这种维护开销),这导致rrDNS的数据模型非常混乱。在寻找新的格式时,我们想要的是快速、易于使用、能够轻松集成到我们已经在使用的代码库和库中的东西。rrDNS大量使用miekg/dns Go库,该库使用大量结构集合来表示每种RR类型,例如:SRV结构类型{Hdr RR U集管优先级uint16重量uint16端口uint16目标字符串`dns:"域名"`}在对rrDNS中的管道写入的数据进行解码时,我们需要将RRs转换成这些结构。事实证明,我们一直在研究的tinylib/msgp库有一套相当不错的代码生成工具。这将允许我们从结构定义自动生成高效的Go代码,而不必以另一种格式维护另一个模式定义。这意味着我们可以在数据管道中使用miekg-RR结构(我们已经从rrDNS中熟悉了这些结构),将它们直接序列化为二进制数据,然后在边缘再次反序列化为我们可以使用的结构。我们不需要担心使用这种技术从一组结构映射到另一组结构,这大大简化了事情。与市场上其他格式相比,MessagePack的性能也非常出色。这是一个Go序列化基准测试的节选;我们可以看到,除了MessagePack对我们的堆栈有利的其他原因之外,它的性能几乎超过了所有其他可行的跨平台选项。切换到这种新模型后,一个意外的惊喜是,我们实际上将存储数据所需的空间减少了9倍左右,这比我们最初的估计要节省得多。它只是用来说明膨胀的数据模型对系统有多大的影响。一种新的数据管道Cloudflare DNS的另一个非常重要的功能是我们能够在几秒钟内而不是几分钟或几小时内将区域更改传播到全球各地。我们现有的管道正在努力跟上不断增长的区域数量,并且每秒钟至少要改变5个区域,即使在最安静的时候我们需要一些新的东西。全球分销很难有一段时间以来,我们已经有了这种监控,我们能够可视化全球的传播时间。下面的图表取自我们的端到端监控:它通过我们的API对DNS进行更改,并监视来自世界各地的各种探测器的变化。图中的每一个点代表一个特定的探针与我们的一个pop进行对话,并且延迟被跟踪为通过API所做的更改在外部可见所花费的时间。由于不同层次的缓存-无论是在我们的控制范围内还是在我们的控制范围之外-我们可以看到一些10秒的间隔在1分钟内,它一直在波动。对于这种性质的监视和警报,我们这里的粒度已经足够了,但我们肯定希望改进它。在正常运行中,99%的全球POP在5秒内就可以获得新的DNS数据。在这段时间内,我们可以看到,由于网络连接,少数POP出现几分钟的延迟,但通常所有探测器报告的传播时间稳定。相比之下,这是同一时期的旧数据管道图。我们可以看到图表如何表示在任何给定时间内所有持久性有机污染物的可见变化的增长延迟。我们设计了一个新的数据模型,可以更好地匹配我们的查询模式,我们开始实施一个新的服务来获取对中央数据存储区的分区的更改,进行任何必要的处理,并将结果输出发送到我们的KV存储区。新服务(用我们最喜欢的语言Go编写)自2016年7月开始投入生产,现在我们已经将99%以上的Cloudflare客户区迁移到it部门。如果我们排除互联网上的拥塞问题影响与特定位置的连接的事件,那么到目前为止,新管道本身已经经历了零延迟。权威rrDNS v2不同类型的dns过滤程序允许我们对不同类型的dns进行注销处理。权威过滤器负责接收一个传入的DNS查询,查找查询名称所属的区域,并执行所有相关逻辑来查找RRSet并将其发送回客户端。由于我们已经在我们的edge上完全修改了底层DNS数据模型,我们需要对rrDNS中的"权威过滤器"进行重大更改。这也是代码库的一个老领域,多年来没有明显变化。与任何老化的代码基一样,这带来了许多挑战,因此我们选择完全重写过滤器。这使我们能够在新的数据模型基础上重新设计它,密切关注性能,并更好地适应我们今天DNS流量的规模和形状。重新开始也使构建良好的开发实践变得更加容易,比如高测试覆盖率和更好的文档。我们在产品中运行权威过滤器的v2版本