如何将Kestrel + YARP引入Azure App Services

273 阅读9分钟

在这篇文章中,我们可以看到改变一个关键的平台组件所需的工程工作,该组件的代码路径每天都要行使数十亿次,同时最大限度地减少服务中断并为我们的客户保持SLA。我们提供了一个简短的介绍,以帮助涵盖基础知识,回顾做这项工作的动机,解释一些更有趣的挑战、问题和沿途遇到的错误,并以结果和启用的新客户方案结束。

挑战是巨大的,但我们对这给Azure应用服务和我们的客户带来的好处感到兴奋。

  • 在旨在隔离效益的性能测试中,吞吐量提高了近80%。
  • 由于每次请求的CPU使用量大幅减少,Azure数据中心更加环保。
  • 对HTTP/3等现代协议的支持。
  • 支持新的客户场景,如gRPC应用、每个主机的密码套件配置、自定义错误页面等。

简介

2021年,一群跨越多个团队(包括.NET和Azure)的工程师聚集在一起,将App Service Frontend舰队过渡到Kestrel +YARP。在我们庆祝这一重大提升和合作的完成时,我们决定写下这段旅程,并描述完成这种对实时服务的改变的一些挑战,我们取得的胜利,以及这一过渡所带来的未来工作。我们希望你能喜欢它。

Azure应用服务简述

Azure应用服务最近庆祝了它的10周年(我们在2012年6月7日推出了它)。 我们对帮助我们成长为一个大型服务(在Azure内部被亲切地称为XXL服务,只有其他三个服务共享这一称号)的客户表示感谢和谦卑。以下是一些数字,可以窥见我们的规模。

  • 应用程序每天提供16000多个HTTP请求
  • 14M+主机名
  • 1.5K+多租户规模单元和另外10K+专用规模单元(应用服务环境,又称应用服务隔离SKU)

这个系统的关键架构之一是我们的FrontEndRoleFrontEndRole的主要用途是。

  • 接收来自与规模单位相关的公共虚拟IP地址的HTTP/HTTPS的流量
  • 终止SSL(如果需要的话
  • 确定哪一组虚拟机是应用程序的源服务器(称为Workers),然后路由到它们。

FrontEndRole diagram

应用程序服务最初是作为云服务建立的,这个角色只是称为FrontEndRole。随着我们向虚拟机规模集的过渡,FrontEndRole是一个单独的规模集,是每个规模单元的一部分。

最初的应用服务FrontEndRole,在Windows服务器上运行,由以下部分组成。

  • 运行在HTTP.sys上的IIS,都是Windows Server的操作系统组件
  • 应用请求路由(ARR),它使用WinHTTP进行请求转发

Kestrel和YARP的简述

.NET Core的第一个版本引入了Kestrel webserver:一个使用现代.NET构建的开源、跨平台和快速的webserver实现。性能是.NET团队关注的重点,随着每个.NET版本的发布,Kestrel变得越来越快,功能越来越全。例如,最近对Kestrel所作的改变包括。

  • 在多核机器上的可扩展性有了明显的改善
  • 在许多并发流中运行时,HTTP/2的性能得到了极大的提升
  • 支持新的标准,如HTTP/3

YARP("Yet Another Reverse Proxy")是一个反向代理工具包,能够使用ASP.NET和.NET的基础设施构建快速的代理服务器,重点是易于定制。它是在github.com/microsoft/r… 上公开开发的YARP的工具包/可扩展性模型使我们很容易将我们的路由和TLS处理与它的请求转发功能相结合。YARP包括对HTTP/2和HTTP/3等现代协议的支持,App Service客户现在可以公开这些协议。 此外,基于快速发展的.NET平台,意味着每一个版本,KestrelYARP都受益于.NET堆栈上下的改进,包括从网络库一直到改善生成代码质量的JIT编译器的一切改进。

将赌注押在Kestrel + YARP的应用服务上。为什么?

先前建立在IIS/HTTP.SYS上的App Service的FrontEndRole架构为我们提供了良好的服务,但Kestrel + YARP中现代HTTP堆栈的承诺可以为所有App Service客户提供新的好处。 具体而言。

  • 性能改进,包括大幅降低每个请求的CPU成本和每个连接的内存成本。
  • 更灵活地将可扩展性点纳入SSL终止路径,使动态SNI主机选择更容易。
  • 启用新的客户方案,如支持gRPC、每个主机密码套件配置、自定义错误页面等。

有了所有这些背景和动力,V-Team的目标很明确。

"将运行FrontEndRole的20多万个专用内核过渡到使用Kestrel + YARP(从而摆脱IIS/HTTP.SYS/ARR)"

挑战:服务器框架的多样性

App Service并不是第一个向Kestrel和YARP过渡的微软服务。微软已经记录了Bing、Azure Active Directory(AAD)和Dynamics 365转向.NET的历程;这些努力已经证明了.NET在关键服务工作负载方面的稳定性和性能。

App Service所带来的独特挑战是服务器实现的多样性。 前面提到的微软服务是由为...微软工作的服务器工程师编写的。 App Service绝对不是这种情况,它使客户能够带来他们自己的服务器框架,并编写他们自己的应用程序,具有不同程度的标准合规性。 托管客户的应用程序带来了一系列独特的挑战,如下所述。

挑战:平台与有机健康

由于App Service使客户能够编写自己的应用程序,*"服务健康 "*的概念是一个细微的讨论。 App Service测量平台的健康状况;我们确保客户有一个运行中的虚拟机,可以连接到存储,并可以执行一个简单的金丝雀请求。 但是App Service不能轻易测量有机健康(HTTP请求成功率),因为我们不控制应用程序。因此,我们主要关注平台的健康状况,作为我们的主要指标。

对于我们向Kestrel + YARP的过渡,我们需要扩大我们的测量范围,包括有机健康。 我们需要比较*"Kestrel + YARP之前 ""Kestrel + YARP之后 "*的有机成功率,而不是寻找一个绝对的标准(例如>99.99%的成功率),并寻找能指出潜在问题的异常情况。

挑战:快速恢复生产

随着评估由我们平台上的各种应用程序/框架引起的有机健康异常的方法的扩大,我们需要快速的机制来撤销我们在每个规模单位上的Kestrel + YARP过渡;换句话说,当我们遇到问题并返回到使用IIS/HTTP.SYS时,我们需要能够迅速*"打破玻璃"*。

旅程:使用Kestrel/YARP的100% FrontEndRoles

在描述了所有的背景和挑战之后,下面是这个旅程的图片。

FrontEndRole Migration

正如你所看到的,这个旅程花了很多时间。从第一个Kestrel/YARP的部署到100%的部署,6个月过去了。

遇到的错误

我们在使用Kestrel + YARP的过程中遇到了许多错误。除了我们业务逻辑中的错误,我们遇到的一个有趣的问题是HTTP规范中对边缘案例的处理。多种多样的客户端冲击着我们的FrontEndRole。我们需要慷慨地接受那些可能不完全是HTTP规范的文字和意图的行为。

其中一个简单的例子是当一个请求有领先的换行字符(CR和/或LF)。严格地说,这是不允许的,但事实证明,有一些客户发送的请求是这样开始的。

\rGET / HTTP/1.1\r\n
...

这是IIS(和其他一些服务器)允许的情况,但由于Kestrel在历史上采取了相当严格的立场,我们看到它的分析器拒绝这样的请求,BadHttpRequestException 。 通过与ASP.NET Core团队的密切合作,我们能够使Kestrel在接受内容方面更加宽松(上面的例子现在可以在.NET 6.0.5和更新的版本中的Kestrel中运行)。

作为调查和解决这类问题的结果,我们已经使Kestrel成为一个更有能力的服务器,而不影响安全的核心原则。

回报:现在和将来的性能和新功能

现在,我们已经将我们的FrontEndRoles转移到Kestrel + YARP,我们已经在生产中实现了多种好处。

为隔离FrontEndRole变化的好处而进行的性能测试表明,吞吐量提高了近80%(使用测试环境中单个专用工作者的简单1Khelloworld响应进行测试)。 App Service对FrontEndRole实例进行了过度配置,因此,在我们整个团队中实现的好处是CPU%大幅下降,为团队提供了更多的CPU空间。我们仍处于监测移动后的机群的早期阶段;我们最终可能会减少分配给这个角色的核心,以减少运营成本和数据中心的能源使用。更多的调查将随后进行。

随着我们在FrontEndRoles上迁移到Kestrel+YARP,我们也能够将我们的Linux工作者虚拟机迁移到使用Kestrel+YARP。这一变化使我们能够取代nginx,统一代码库,并为我们的应用服务Linux SKU点亮gRPC。gRPC支持一直是Azure应用服务用户的热门功能要求,我们很高兴能够增加这一功能。

随着这项平台工作的完成,我们现在正在努力启用App Service中最常被要求的两项功能;随着我们完成这些改进,很快就会有更多消息。

  • 能够为在前端终止的请求配置自定义错误页面(特别是:HTTP 503、HTTP 502和HTTP 403)。
  • 能够指定每个给定应用程序允许的TLS密码套件。 今天,客户只能在我们的隔离式SKU上配置允许的密码套件。

一个伟大的伙伴关系

一旦你有一个实时的多租户服务,并在全球范围内运行数百万个虚拟机,你就会学会对如何和何时推进它非常小心。也就是说,.NET核心团队正在开发的Kestrel + YARP的创新太有价值了,不能错过。同时,.NET团队会告诉你,支持这种迁移的经验对该团队来说是一个全新的挑战,因为他们体验到了应用服务场景的广泛性和多样性。这对两个团队来说都是一个伟大的旅程,我们成功了。现在我们有了这个新的平台,我们期待着我们团队之间继续创新。