{"id":37331,"date":"2021-11-09T08:00:32","date_gmt":"2021-11-09T15:00:32","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=37331"},"modified":"2021-11-17T11:50:49","modified_gmt":"2021-11-17T18:50:49","slug":"announcing-yarp-1-0-release","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-yarp-1-0-release\/","title":{"rendered":"Announcing YARP 1.0 Release"},"content":{"rendered":"<p>Today we announce the release of YARP 1.0, which can be downloaded from NuGet. YARP (Yet Another Reverse Proxy) is a highly customizable reverse proxy built using .NET. The biggest differentiator between YARP and other reverse proxies is how it is built and packaged \u2013 YARP is supplied as a library and samples showing how to create a proxy that is customized to the needs of your specific scenarios.<\/p>\n<h2>What is a reverse proxy?<\/h2>\n<p>Reverse proxies are used to listen to incoming HTTP requests and to forward the requests to appropriate servers based on the contents of the request. Unlike a typical firewall\/router which acts at layer 4 (TCP\/IP), reverse proxies typically work at layer 7 so they understand http and work based on http fields.<\/p>\n<p>When YARP proxies a request, it handles the HTTP connection from the client, and then creates its own connections to the destination server, and both sides can benefit from connection pooling.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/11\/image1.png\" alt=\"Illustration of the role of a reverse proxy\" \/><\/p>\n<p>Using a reverse proxy has a number of advantages:<\/p>\n<ul>\n<li>It acts as the public endpoint for a site or set of services, enabling the url-space exposed to be independent from the actual implementation<\/li>\n<li>Forwards calls to backend servers to perform real work, balancing load between them<\/li>\n<li>Can offload work from backend servers such as TLS Encryption, Auth<sup>2<\/sup>, Compression, Caching<\/li>\n<\/ul>\n<h2>Introducing YARP<\/h2>\n<p><a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\">YARP<\/a> is a project to deliver an open-source reverse proxy server based on .NET. It started almost two years ago when we noticed a pattern of questions from teams at Microsoft who were either building a reverse proxy for their service or had been asking about APIs and technology for building one. We decided to get them all together to work on a common solution, which became YARP.<\/p>\n<p>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 is being designed to be easily customized and tweaked to match the specific needs of each deployment scenario.<\/p>\n<p>The thing we found from talking with teams creating Microsoft services is that each service is slightly off the beaten path, and they had all been building their own solutions, or trying to customize a 3rd party proxy. While they had solutions for HTTP\/1.1, they needed HTTP\/2 &#8211; commonly for gRPC, and HTTP\/2 uses a binary framing format which is much more complicated to implement. YARP enables developers to have full control while leveraging the proven feature set of ASP.NET Core and .NET, with the productivity of C# (or other .NET languages).<\/p>\n<p>YARP plugs into ASP.NET as middleware for handling incoming requests, and YARP offers two main paths for use &amp; customization:<\/p>\n<ul>\n<li>As a full featured proxy &#8211; YARP uses configuration to define a set of routes based on URL patterns, these routes map to clusters of destination servers, each destination in a cluster should be able to handle requests for the routes the cluster is mapped to. The destination list is filtered based on session affinity, and server health, then uses a load balancing algorithm to choose between the remaining destinations.Each part of this can be customized through configuration and customers can add additional modules, or replace stock modules as needed. The configuration system is extensible so for example route and destination information can be pulled from a source such as Service Fabric.<\/li>\n<li>Alternatively, for highly custom environments the YARP request forwarder can be called directly, bypassing the routing, load-balancing modules etc. For example, this is how YARP is being used by Azure App Service for routing requests to specific instances, where the instances are spun up on demand.<\/li>\n<\/ul>\n<p>These can even be used together in the same process, switching between them based on the route.<\/p>\n<h2>Getting started<\/h2>\n<p>Unlike other proxies that are supplied as an executable that you can extend, YARP reverses the model. You create a proxy using a template that calls into YARP, this makes it much easier to add your own customization and features to YARP.<\/p>\n<p>The following sample is based on the new simplified templates for .NET 6. Examples are <a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/tree\/main\/samples\/BasicYarpSample\">available<\/a> for .NET Core 3.1 and .NET 5.<\/p>\n<ol>\n<li>Install .NET 6 if not already installed from <a href=\"https:\/\/dotnet.microsoft.com\/download\">https:\/\/dotnet.microsoft.com\/download<\/a><\/li>\n<li>Create a new web project using<\/li>\n<\/ol>\n<pre><code class=\"language-console\">dotnet new web --name MyYarpProxy<\/code><\/pre>\n<ol start=\"3\">\n<li>Add a reference to the YARP nuget package:<\/li>\n<\/ol>\n<pre><code class=\"language-console\">dotnet add package MyYarpProxy Yarp.ReverseProxy <\/code><\/pre>\n<ol start=\"4\">\n<li>Replace the code in program.cs with:<\/li>\n<\/ol>\n<pre><code class=\"language-c#\">var builder = WebApplication.CreateBuilder(args);\r\n\r\nbuilder.Services.AddReverseProxy()\r\n    .LoadFromConfig(builder.Configuration.GetSection(\"ReverseProxy\"));\r\n\r\nvar app = builder.Build();\r\n\r\napp.MapReverseProxy();\r\n\r\napp.Run();<\/code><\/pre>\n<ol start=\"5\">\n<li>Replace the configuration file in appsettings.json with:<\/li>\n<\/ol>\n<pre><code class=\"language-json\">{\r\n    \"Urls\": \"http:\/\/localhost:5000;https:\/\/localhost:5001\",\r\n    \"Logging\": {\r\n        \"LogLevel\": {\r\n            \"Default\": \"Information\",\r\n            \"Microsoft.AspNetCore\": \"Warning\"\r\n        }\r\n    },\r\n    \"AllowedHosts\": \"*\",\r\n    \"ReverseProxy\": {\r\n        \"Routes\": {\r\n            \"minimumroute\": {\r\n                \"ClusterId\": \"minimumcluster\",\r\n                \"Match\": {\r\n                    \"Path\": \"{**catch-all}\"\r\n                }\r\n            }\r\n        },\r\n\r\n        \"Clusters\": {\r\n            \"minimumcluster\": {\r\n                \"Destinations\": {\r\n                    \"httpbin.org\": {\r\n                        \"Address\": \"https:\/\/httpbin.org\/\"\r\n                    }\r\n                }\r\n            }\r\n        }\r\n    }\r\n}<\/code><\/pre>\n<p>This will create a proxy that will listen to http:\/\/localhost:5000 and https:\/\/localhost:5001 and route any requests to https:\/\/httpbin.org (a useful site for http debugging.) <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/config-files.html\">Further details on what can be added through configuration<\/a>.<\/p>\n<h2>What is in YARP 1.0<\/h2>\n<p>This 1.0 release of YARP includes the following features:<\/p>\n<h3>Configuration<\/h3>\n<ul>\n<li>YARP configuration defines the routes and destinations. It can be supplied via:\n<ul>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/config-files.html\">Static config files<\/a>, with file change detection for dynamic updates<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/config-providers.html\">Programatic configuration extensibility<\/a> to interface with other sources<\/li>\n<\/ul>\n<\/li>\n<li>For hyper-scale hosting, routing can be <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/direct-forwarding.html\">fully dynamic and determined by app code<\/a> and handled by YARP on a per-request basis<\/li>\n<\/ul>\n<h3>Routing &amp; inbound connections<\/h3>\n<ul>\n<li>YARP can front multiple sites and route based on SNI\/Host<\/li>\n<li>Routing can be based on request URL &amp; <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/header-routing.html\">header values<\/a><\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/dests-health-checks.html#active-health-checks\">Active &amp; passive health checks<\/a> to confirm the availability of destinations, and filter out bad entries<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/session-affinity.html\">Session Affinity<\/a> will route subsequent requests to the same destination if required<\/li>\n<li>Multiple algorithms for <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/load-balancing.html\">load balancing<\/a> across destinations<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/authn-authz.html\">Authentication, authorization<\/a> and CORS for specific routes<\/li>\n<\/ul>\n<h3>Proxying &amp; outbound connections<\/h3>\n<ul>\n<li>Incoming request Url can be <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/transforms.html#request-transforms\">transformed<\/a> before passing to destination(s)<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/transforms.html#requestheaderscopy\">Request<\/a> and <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/transforms.html#response-and-response-trailers\">response<\/a> headers can be transformed<\/li>\n<li>Http <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/transforms.html#httpmethodchange\">Methods can be transformed<\/a> (eg POST to PUT)<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/http-client-config.html\">Outbound http connections<\/a> to destinations are configurable<\/li>\n<li>Proxy <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/transforms.html#defaults\">adds standard headers<\/a> related to request forwarding<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/grpc.html\">gRPC<\/a> and web sockets traffic including streaming<\/li>\n<\/ul>\n<h3>Diagnostics<\/h3>\n<ul>\n<li><a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/tree\/main\/samples\/ReverseProxy.Metrics.Sample\">Metrics<\/a> for monitoring performance<\/li>\n<li>Logging for detailed tracking of each request<\/li>\n<\/ul>\n<h3>General<\/h3>\n<ul>\n<li>Proxy has cloud scale performance<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/index.html\">Documentation<\/a><\/li>\n<li>Easy extensibility &#8211; Customers can add <a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/middleware.html\">middleware<\/a> to customize the proxy functionality such as routing, header manipulation<\/li>\n<li><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/runtimes.html\">Support for .NET Core 3.1, .NET 5 &amp; .NET 6<\/a><\/li>\n<\/ul>\n<h2>Documentation<\/h2>\n<p><a href=\"https:\/\/microsoft.github.io\/reverse-proxy\/articles\/index.html\">YARP documentation<\/a>.<\/p>\n<h2>Performance<\/h2>\n<p>Performance of the proxy will depend on a number of factors:<\/p>\n<ul>\n<li>Version of http used by clients to the proxy<\/li>\n<li>Version of http used by the proxy to the destination<\/li>\n<li>Whether TLS encryption is used<\/li>\n<li>Size of request\/response headers and content payloads<\/li>\n<\/ul>\n<p>We have a set of benchmarks that get run daily against YARP and other proxy servers. This is measured in a lab using the &#8220;<a href=\"https:\/\/www.techempower.com\/benchmarks\/#section=environment\">citrine<\/a>&#8221; hardware definition created to measure the TechEmpower benchmarks. The results are presented using a PowerBI dashboard that can be used to compare against other proxies. For example, comparing YARP and Envoy for (incoming-outgoing protocol) http-http1.1 &amp; https-https1.1 with results in October &#8217;21 looks like:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/11\/image3.png\" alt=\"Graph of performance over time\" \/><\/p>\n<p>The dashboard can be found at <a href=\"https:\/\/aka.ms\/aspnet\/benchmarks\">https:\/\/aka.ms\/aspnet\/benchmarks<\/a>. Once there, at the bottom of the page is a widget to select the page. Proxy results are on page 16.<\/p>\n<blockquote><p><strong>Hint:<\/strong> Clicking the text &#8220;1 of 21&#8221; will bring up a menu of pages, where &#8220;Proxies&#8221; can be selected directly.<\/p><\/blockquote>\n<h2>Open Source<\/h2>\n<p>YARP is being developed and delivered as an open source project. It is hosted on github at <a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\">https:\/\/github.com\/microsoft\/reverse-proxy<\/a>. We welcome contributions, issues and discussions at the repo.<\/p>\n<h2>Support<\/h2>\n<p>YARP support is provided by the product team &#8211; the engineers working on YARP &#8211; which is a combination of members from ASP.NET and the core libraries networking teams. We do not provide 24\/7 support or &#8216;carry pagers&#8217;, but as we have team members located in Prague and Redmond we generally have good time zone coverage. Bugs should be reported in github using the issue <a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/issues\/new?assignees=&amp;labels=Type%3A+Bug&amp;template=bug.md\">templates<\/a> and will typically be responded to within 24hrs. If you find a security issue we ask you to <a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/blob\/main\/SECURITY.md\">report it via the Microsoft Security Response Center (MSRC)<\/a>.<\/p>\n<p>We will service 1.0 for security or other significant issues. New features will be considered for future versions. We expect to start releasing preview builds of the next version in the next couple of months.<\/p>\n<h2>Thank you to contributors<\/h2>\n<p>In addition to the contributions from Microsoft employees, we are very grateful to have received a number of PRs and issues from the community. Thank you to those who contributed PRs to make this release happen &#8211; @amweiss, @anorborg, @BennyM, @dpbevin, @danirzv, @epignosisx, @ericwj, @ganesanarun, @gustavopaes, @hughesjon, @ihvo, @Insomniak47, @isaacabraham, @jboelter, @jmezach, @jrunyen, @jtkech, @Marusyk, @MeladKamari, @MoienTajik, @NoahStahl, @rwkarg, @sharkAndshark, @sleemer, @stefanolsenn, @Tornhoof, @vdjuric, @WeihanLi, @William-Yeh.<\/p>\n<p>I want to make a special call out to @Kahbazi who made an amazing 86 commits and was a more prolific contributor than many of the people assigned to the project.<\/p>\n<h2>What&#8217;s next<\/h2>\n<p>Work on the reverse proxy will continue. Items we have on our list to work on for the next version include:<\/p>\n<ul>\n<li>Support for HTTP\/3 \u2013 initial testing shows that it mostly works, but we want to have a solid implementation in YARP <a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/issues\/1208\">#1208<\/a><\/li>\n<li>More performance optimization \u2013 We will have another push on performance, and use YARP to drive additional performance features into .NET<\/li>\n<li>Use <a href=\"https:\/\/github.com\/dotnet\/runtimelab\/tree\/feature\/LLHTTP2\">LLHTTP<\/a> to provide more control over outbound connections and more efficient processing of headers. LLHTTP is an experiment to develop a lower level HTTP API than HttpClient to enable much more control over how HTTP requests are made and handled.<\/li>\n<li>Support for Service Fabric \u2013 Early previews of YARP included a module for Service Fabric integration. That was insufficient for large scale site deployments typical of sites using Service Fabric. We are working with SF team members to implement a more robust and scalable solution for dynamically configuring the proxy based on SF data<a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/pull\/257\"> #257<\/a><\/li>\n<li>@jkotalik wrote a prototype implementation for integration with Kubernetes. The Microsoft team members working on YARP are not experts in k8s deployments, so we are working with community members to further develop this integration.<a href=\"https:\/\/github.com\/microsoft\/reverse-proxy\/issues\/200\"> #200<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>YARP, an open-source, highly customizable reverse proxy using .NET has been released.<\/p>\n","protected":false},"author":8635,"featured_media":37332,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196,197,7591],"tags":[],"class_list":["post-37331","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core","category-aspnet","category-networking"],"acf":[],"blog_post_summary":"<p>YARP, an open-source, highly customizable reverse proxy using .NET has been released.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/37331","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/8635"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=37331"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/37331\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/37332"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=37331"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=37331"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=37331"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}