浅析微软的网关项目 -- ReverseProxy
浅析微软的网关项目 ReverseProxy
Intro
最近微软新开了一个项目 ReverseProxy ,也叫做 YARP(A Reverse Proxy)
官方介绍如下:
YARP is a reverse proxy toolkit for building fast proxy servers in .NET using the infrastructure from ASP.NET and .NET. The key differentiator for YARP is that it’s been designed to be easily customized and tweaked to match the specific needs of each deployment scenario.
这是一个基于 .net (core) 和 asp.net (core) 的用来代理服务器的反向代理组件,YARP的主要区别在于它的设计易于定制和调整,以适应每种部署方案的特定需求。
你可以基于这个项目来构建自己的 API Gateway 项目
YARP 设计
YARP 主要是基于 endpoint 路由 + asp.net core 中间件来设计实现的
来看一下官方的示例 Startup
配置:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddReverseProxy()
.LoadFromConfig(_configuration.GetSection("ReverseProxy"))
.AddProxyConfigFilter<CustomConfigFilter>();
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapReverseProxy(proxyPipeline =>
{
// Custom endpoint selection
proxyPipeline.Use((context, next) =>
{
var someCriteria = false; // MeetsCriteria(context);
if (someCriteria)
{
var availableDestinationsFeature = context.Features.Get<IAvailableDestinationsFeature>();
var destination = availableDestinationsFeature.Destinations[0]; // PickDestination(availableDestinationsFeature.Destinations);
// Load balancing will no-op if we've already reduced the list of available destinations to 1.
availableDestinationsFeature.Destinations = new[] { destination };
}
return next();
});
proxyPipeline.UseProxyLoadBalancing();
});
});
}
中间件
基于 asp.net core 的中间件的设计可以使得一些现有的 asp.net core 的中间件可以无缝集成,不得不说微软的设计真的是很优秀
相对来说 Ocelot 的的设计就会稍显逊色一些,因为 Ocelot 的设计是 asp.net core 的一个中间件,在 Ocelot 内部有自己的一套中间件,原来基于 asp.net core 的中间件要在 Ocelot 中使用就需要进一步开发,变成 Ocelot 的中间件,才能正常工作,比如 Ocelot 里的限流中间件就是基于一个 asp.net core 的中间件来实现的 AspNetCoreRateLimit
proxy endpoint 实现
public static void MapReverseProxy(this IEndpointRouteBuilder endpoints, Action<IApplicationBuilder> configureApp)
{
if (endpoints is null)
{
throw new ArgumentNullException(nameof(endpoints));
}
if (configureApp is null)
{
throw new ArgumentNullException(nameof(configureApp));
}
var appBuilder = endpoints.CreateApplicationBuilder();
appBuilder.UseMiddleware<DestinationInitializerMiddleware>();
configureApp(appBuilder);
appBuilder.UseMiddleware<ProxyInvokerMiddleware>();
var app = appBuilder.Build();
var routeBuilder = endpoints.ServiceProvider.GetRequiredService<IRuntimeRouteBuilder>();
routeBuilder.SetProxyPipeline(app);
var dataSource = (EndpointDataSource)endpoints.ServiceProvider.GetRequiredService<IProxyDynamicEndpointDataSource>();
endpoints.DataSources.Add(dataSource);
}
从上面的代码可以看到,针对反向代理的处理流程是也是一套中间件管道处理,
首先执行的是 DestinationInitializerMiddleware
在这一中间件,会获取可用的下游节点,并通过 HttpContext
的 Features
来传递给后面的中间件,
然后会调用传进来的自定义中间件的逻辑,在这个逻辑中,可以加一些我们自己的业务逻辑,十分灵活,可扩展性极强
之后会执行 ProxyInvokerMiddleware
,在这个中间件中会去调用下游服务,并生成 response 返回给客户端
More
目前这个项目在还是在积极开发中,可以关注一下,但是暂时不建议在项目中使用,目前还没发布 preview 版本,原本这个项目只支持 .net 5,不支持 .netcore3.1 ,在许多人的呼吁之下,微软打算在 preview2 版本中提供对 dotnetcore 3.1 的支持,详细可以参考 issue: https://github.com/microsoft/reverse-proxy/issues/159,希望提供 .net core 3.1 支持的可以去点个赞哈