网关介绍
网关其实就是将我们写好的API全部放在一个统一的地址暴露在公网,提供访问的一个入口。在 .NET Core下可以使用Ocelot来帮助我们很方便的接入API 网关。与之类似的库还有ProxyKit,微软也发布了一个反向代理的库YARP。
关于网关的介绍不多说了,网上文章也挺多的,这些都是不错的选择,听说后期Ocelot将会使用YARP来重写。本篇主要实践一下在.NET Core环境下使用YARP。
YARP介绍
YARP 在 .NET Core 基础结构之上实现,可在 Windows、Linux 或 MacOS 上使用。可以使用 SDK 和您喜欢的编辑器、微软视觉工作室或可视化工作室代码进行开发。
YARP 1.1 支持 ASP.NET 核心 3.1、 5.0 & 6.0。可以从 https://dotnet.microsoft.com/download/dotnet/ 下载 .NET 开发工具包。
对 .NET 5 的视觉工作室支持包含在 Visual Studio 2019 v16.8 或更高版本中。
对 .NET 6 的可视化工作室支持包含在 Visual Studio 2022 中。
文档:https://microsoft.github.io/reverse-proxy/articles/getting-started.html
Git: https://github.com/microsoft/reverse-proxy
入门示例
首先使用命令行创建一个“MyProxy.YarpDemo”ASP.NET Core 应用程序
添加项目引用
Install-Package Yarp.ReverseProxy
添加 YARP 中间件
var builder = WebApplication.CreateBuilder(args);builder.Services.AddReverseProxy().LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));var app = builder.Build();app.MapReverseProxy();app.Run();
配置
YARP 的配置在 appsettings.json 文件中定义。有关详细信息,请参阅配置文件。
还可以以编程方式提供配置。有关详细信息,请参阅配置提供程序。
您可以通过查看路由配置和集群配置来了解有关可用配置选项的更多信息。
{"Logging": {"LogLevel": {"Default": "Information","Microsoft": "Warning","Microsoft.Hosting.Lifetime": "Information"}},"AllowedHosts": "*",//YARP配置源"ReverseProxy": {"Routes": {"route1": {"ClusterId": "cluster1","Match": {"Path": "{**catch-all}"}}},"Clusters": {"cluster1": {//PowerOfTwoChoices - 选择两个随机的目标,然后从中选择一个更少请求的目标//FirstAlphabetical - 字母序, Random - 随机, RoundRobin - 轮询//LeastRequests - 所有目标中选择分配请求最少的目标"LoadBalancingPolicy": "PowerOfTwoChoices","Destinations": {"destination1": {"Address": "http://localhost:5202"}}}}}}
:::warning LoadBalancingPolicy配置项说明
- PowerOfTwoChoices - 选择两个随机的目标,然后从中选择一个更少请求的目标
- FirstAlphabetical - 字母序
- Random - 随机
- RoundRobin - 轮询
LeastRequests - 所有目标中选择分配请求最少的目标 :::
配置项说明
{"ReverseProxy": {// 在 Routes 节点配置需要反向代理的路由表"Routes": {// 第一个路由配置(最简配置)"minimumroute" : { // 路由名称,可自定义// 该路由所关联的集群配置,也就是目标服务器配置"ClusterId": "minimumcluster","Match": { // 匹配规则"Path": "{**catch-all}"}},// 第二个路由配置(全量)"allrouteprops" : {"ClusterId": "allclusterprops""Order" : 100, // 路由顺序,数字越小优先级越高// 认证策略,可选 "Default", "Anonymous""Authorization Policy" : "Anonymous",// Cors 策略,可选 "Default", "Disable""CorsPolicy" : "Default","Match": { //匹配 /something/*"Path": "/something/{**remainder}", // The path to match using ASP.NET syntax.// 限定 Host,不设置就是不限制"Hosts" : [ "www.aaaaa.com", "www.bbbbb.com"],// Heep Methods 限定,不指定就是不限制"Methods" : [ "GET", "PUT" ],"Headers": [ // 请求头限定,不指定就是不限制{"Name": "MyCustomHeader", // 请求头名称"Values": [ "value1", "value2", "another value" ], // 规则值// 匹配模式,可选:"ExactHeader", "HeaderPrefix", "Exists" , "Contains", "NotContains""Mode": "ExactHeader","IsCaseSensitive": true // 是否区分大小写}],"QueryParameters": [ // 查询字符串限定,不设置就是不限制{"Name": "MyQueryParameter", // 参数名"Values": [ "value1", "value2", "another value" ], // 规则值"Mode": "Exact", // 匹配模式,可选 "Exact", "Prefix", "Exists" , "Contains", "NotContains""IsCaseSensitive": true}]},"MetaData" : { // 元数据(KV对象),可以在自定义扩展中使用"MyName" : "MyValue"},"Transforms" : [ // List of transforms. See ./Transforms.html for more details{"RequestHeader": "MyHeader","Set": "MyValue",}]}},// 转发服务器配置"Clusters": {"minimumcluster": {"Destinations": {"example.com": { // 目的地 1,名字自定义"Address": "http://www.example.com/" // 要转发的目标地址}}},"allclusterprops": { // 一个比较全面的目的地配置"Destinations": {"first_destination": {"Address": "https://contoso.com" // 目标地址},"another_destination": {"Address": "https://10.20.30.40","Health" : "https://10.20.30.40:12345/test" // Health Check 地址,会覆盖 HealthCheck.Active 下的 Path}},"LoadBalancingPolicy" : "PowerOfTwoChoices", // 负载均衡策略: PowerOfTwoChoices - 选择两个随机的目标,然后从中选择一个更少请求的目标, "FirstAlphabetical" - 字母序, "Random" - 随机, "RoundRobin" - 轮询, "LeastRequests" - 所有目标中选择分配请求最少的目标"SessionAffinity": {"Enabled": true, // Defaults to 'false'"Policy": "Cookie", // Default, alternatively "CustomHeader""FailurePolicy": "Redistribute", // default, Alternatively "Return503""Settings" : {"CustomHeaderName": "MySessionHeaderName" // Defaults to 'X-Yarp-Proxy-Affinity`}},"HealthCheck": { // 健康检查配置"Active": { // Makes API calls to validate the health."Enabled": "true","Interval": "00:00:10", // 检查间隔"Timeout": "00:00:10", // 超时时间"Policy": "ConsecutiveFailures","Path": "/api/health" // 健康检查地址},"Passive": { // Disables destinations based on HTTP response codes"Enabled": true, // Defaults to false"Policy" : "TransportFailureRateHealthPolicy", // Required"ReactivationPeriod" : "00:00:10" // 10s}},"HttpClient" : { // Configuration of HttpClient instance used to contact destinations"SSLProtocols" : "Tls13","DangerousAcceptAnyServerCertificate" : false,"MaxConnectionsPerServer" : 1024,"EnableMultipleHttp2Connections" : true,"RequestHeaderEncoding" : "Latin1" // How to interpret non ASCII characters in header values},"HttpRequest" : { // Options for sending request to destination"ActivityTimeout" : "00:02:00","Version" : "2","VersionPolicy" : "RequestVersionOrLower","AllowResponseBuffering" : "false"},"MetaData" : { // Custom Key value pairs"TransportFailureRateHealthPolicy.RateLimit": "0.5", // Used by Passive health policy"MyKey" : "MyValue"}}}}}
运行项目
