微软用它取代了`Nginx`吞吐量提升了百分之八十!

微软用它取代了`Nginx`吞吐量提升了百分之八十!Azure 应用服务用 YARP 取代了 Nginx 获得了 80 以上的吞吐量

大家好,欢迎来到IT知识分享网。

微软用它取代了`Nginx`吞吐量提升了百分之八十!

Azure应用服务用YARP取代了Nginx,获得了80%以上的吞吐量。他们每天处理160B多个请求(1.9 m RPS)。这是微软的一项了不起的技术创新。

首先我们来介绍一下什么是Yarp

Yarp是什么?

YARP(Yet Another Reverse Proxy)是一个开源的、高性能的反向代理库,由Microsoft开发,使用C#语言编写。它旨在作为.NET平台上构建反向代理服务器的基础。YARP主要针对.NET 5及以上版本,允许开发者在.NET应用程序中轻松地实现反向代理的功能。

YARP的主要特点和功能:

  1. 模块化和可扩展性: YARP设计成高度模块化的,这意味着可以根据需要替换或扩展内部组件,如HTTP请求路由、负载均衡、健康检查等。
  2. 性能: YARP针对高性能进行了优化,利用了.NET的异步编程模型和高效的IO操作,以处理大量并发连接。
  3. 配置驱动: YARP的行为可以通过配置来控制,支持从文件、数据库或其他来源动态加载配置。
  4. 路由: 可以基于各种参数(如路径、头部、查询参数)配置请求路由规则。
  5. 负载均衡: 内置多种负载均衡策略,如轮询、最少连接、随机选择等,并且可以自定义负载均衡策略。
  6. 健康检查: 支持后端服务的健康检查,以确保请求只会被转发到健康的后端服务实例。
  7. 转换器: 允许对请求和响应进行转换,如修改头部、路径或查询参数。
  8. 会话亲和性: 支持会话亲和性(Session Affinity),确保来自同一客户端的请求被发送到相同的后端服务实例。

使用YARP的一些场景:

  • 反向代理: 在客户端和后端服务之间提供一个中间层,用于请求转发和负载均衡。
  • API网关: 作为微服务架构中的API网关,提供路由、鉴权、监控等功能。
  • 边缘服务: 在应用程序和外部世界之间提供安全层,处理SSL终止、请求限制等任务。

Yarp简单的使用

创建一个WebApi的项目

安装Nuget

<ItemGroup> <PackageReference Include="Yarp.ReverseProxy" Version="2.0.0" /> </ItemGroup> 

打开appsettings.json

{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "ReverseProxy": { "Routes": { "route1" : { "ClusterId": "cluster1", "Match": { "Path": "{catch-all}" } } }, "Clusters": { "cluster1": { "Destinations": { "destination1": { "Address": "https://cn.bing.com/" } } } } } } 

打开Program.cs

var builder = WebApplication.CreateBuilder(args); builder.Services.AddReverseProxy() .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy")); var app = builder.Build(); app.MapReverseProxy(); app.Run(); 

然后启动项目,访问我们的api就会被代理转发到bing

微软用它取代了`Nginx`吞吐量提升了百分之八十!

Yarp工具代理使用

下面我们在提供一个在中间件使用yarp的方式

我们需要用到IHttpForwarder

先修改Program.cs 在这里我们注入了HttpForwarder,然后提供一个Run中间件,在中间件中手动指定了端点的地址https://cn.bing.com/ 然后我们启动一下项目。

using Yarp.ReverseProxy.Forwarder; var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpForwarder(); // 注入IHttpForwarder  var app = builder.Build(); var httpMessage = new HttpMessageInvoker(new HttpClientHandler()); app.Run((async context => { 
    var httpForwarder = context.RequestServices.GetRequiredService<IHttpForwarder>(); var destinationPrefix = "https://cn.bing.com/"; await httpForwarder.SendAsync(context, destinationPrefix, httpMessage); })); app.Run(); 

也是一样会被代理过去,但是于简单使用不一样的是我们是在代码层面控制代理的。

微软用它取代了`Nginx`吞吐量提升了百分之八十!

使用yarp修改Bing的响应内容

我们继续基于上面的代理使用进行修改bing的相应内容!

打开Program.cs

var builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpForwarder(); // 注入IHttpForwarder  var app = builder.Build(); var httpMessage = new HttpMessageInvoker(new HttpClientHandler() { 
    // 忽略https错误 ServerCertificateCustomValidationCallback = (_, _, _, _) => true, AllowAutoRedirect = false, AutomaticDecompression = DecompressionMethods.GZip, UseCookies = false, UseProxy = false, UseDefaultCredentials = true, }); var destinationPrefix = "https://cn.bing.com/"; var bingTransformer = new BingTransformer(); app.Run((async context => { 
    var httpForwarder = context.RequestServices.GetRequiredService<IHttpForwarder>(); await httpForwarder.SendAsync(context, destinationPrefix, httpMessage, new ForwarderRequestConfig(), bingTransformer); })); app.Run(); 

创建BingTransformer.cs

public class BingTransformer : HttpTransformer { 
    public override async ValueTask TransformRequestAsync(HttpContext httpContext, HttpRequestMessage proxyRequest, string destinationPrefix, CancellationToken cancellationToken) { 
    var uri = RequestUtilities.MakeDestinationAddress(destinationPrefix, httpContext.Request.Path, httpContext.Request.QueryString); proxyRequest.RequestUri = uri; proxyRequest.Headers.Host = uri.Host; await base.TransformRequestAsync(httpContext, proxyRequest, destinationPrefix, cancellationToken); } public override async ValueTask<bool> TransformResponseAsync(HttpContext httpContext, HttpResponseMessage? proxyResponse, CancellationToken cancellationToken) { 
    await base.TransformResponseAsync(httpContext, proxyResponse, cancellationToken); if (httpContext.Request.Method == "GET" && httpContext.Response.Headers["Content-Type"].Any(x => x.StartsWith("text/html"))) { 
    var encoding = proxyResponse.Content.Headers.FirstOrDefault(x => x.Key == "Content-Encoding").Value; if (encoding?.FirstOrDefault() == "gzip") { 
    var content = proxyResponse?.Content.ReadAsByteArrayAsync(cancellationToken).Result; if (content != null) { 
    var result = Encoding.UTF8.GetString(GZipDecompressByte(content)); result = result.Replace("国内版", "Token Bing 搜索 - 国内版"); proxyResponse.Content = new StringContent(GZipDecompressString(result)); } } else if (encoding.FirstOrDefault() == "br") { 
    var content = proxyResponse?.Content.ReadAsByteArrayAsync(cancellationToken).Result; if (content != null) { 
    var result = Encoding.UTF8.GetString(BrDecompress(content)); result = result.Replace("国内版", "Token Bing 搜索 - 国内版"); proxyResponse.Content = new ByteArrayContent(BrCompress(result)); } } else { 
    var content = proxyResponse?.Content.ReadAsStringAsync(cancellationToken).Result; if (content != null) { 
    content = content.Replace("国内版", "Token Bing 搜索 - 国内版"); proxyResponse.Content = new StringContent(content); } } } return true; } /// <summary> /// 解压GZip /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static byte[] GZipDecompressByte(byte[] bytes) { 
    using var targetStream = new MemoryStream(); using var compressStream = new MemoryStream(bytes); using var zipStream = new GZipStream(compressStream, CompressionMode.Decompress); using (var decompressionStream = new GZipStream(compressStream, CompressionMode.Decompress)) { 
    decompressionStream.CopyTo(targetStream); } return targetStream.ToArray(); } /// <summary> /// 解压GZip /// </summary> /// <param name="str"></param> /// <returns></returns> public static string GZipDecompressString(string str) { 
    using var compressStream = new MemoryStream(Encoding.UTF8.GetBytes(str)); using var zipStream = new GZipStream(compressStream, CompressionMode.Decompress); using var resultStream = new StreamReader(new MemoryStream(compressStream.ToArray())); return resultStream.ReadToEnd(); } /// <summary> /// Br压缩 /// </summary> /// <param name="input"></param> /// <returns></returns> public static byte[] BrCompress(string str) { 
    using var outputStream = new MemoryStream(); using (var compressionStream = new BrotliStream(outputStream, CompressionMode.Compress)) { 
    compressionStream.Write(Encoding.UTF8.GetBytes(str)); } return outputStream.ToArray(); } /// <summary> /// Br解压 /// </summary> /// <param name="input"></param> /// <returns></returns> public static byte[] BrDecompress(byte[] input) { 
    using (var inputStream = new MemoryStream(input)) using (var outputStream = new MemoryStream()) using (var decompressionStream = new BrotliStream(inputStream, CompressionMode.Decompress)) { 
    decompressionStream.CopyTo(outputStream); return outputStream.ToArray(); } } } 

得到的效果我们将国内版修改成了Token Bing 搜索 - 国内版

微软用它取代了`Nginx`吞吐量提升了百分之八十!

Yarp AOT尝试

下面我们将Yarp进行AOT尝试,首先打开我们的项目,添加以下参数

<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <InvariantGlobalization>true</InvariantGlobalization> <PublishAot>true</PublishAot> </PropertyGroup> <ItemGroup> <PackageReference Include="Yarp.ReverseProxy" Version="2.0.0" /> </ItemGroup> </Project> 

AOT以后的大小15MB

微软用它取代了`Nginx`吞吐量提升了百分之八十!

优化AOT大小,添加以下参数

<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <InvariantGlobalization>true</InvariantGlobalization> <PublishAot>true</PublishAot> <StackTraceSupport>false</StackTraceSupport> <OptimizationPreference>Size</OptimizationPreference> <PublishTrimmed>true</PublishTrimmed> <BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport> <EventSourceSupport>false</EventSourceSupport> <HttpActivityPropagationSupport>false</HttpActivityPropagationSupport> <EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization> <MetadataUpdaterSupport>false</MetadataUpdaterSupport> <UseNativeHttpHandler>true</UseNativeHttpHandler> <TrimMode>link</TrimMode> </PropertyGroup> <ItemGroup> <PackageReference Include="Yarp.ReverseProxy" Version="2.0.0" /> </ItemGroup> </Project> 

Yarp相关资料

技术交流群:

官方文档:https://microsoft.github.io/reverse-proxy/articles/getting-started.html

来着token的分享

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/113507.html

(0)
上一篇 2025-12-14 08:00
下一篇 2025-12-14 08:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信