目录

Welcome to YARP - 1.认识YARP并搭建反向代理服务

Welcome to YARP - 2.配置功能

Welcome to YARP - 3.负载均衡

Welcome to YARP - 4.限流

Welcome to YARP - 5.身份验证和授权

Welcome to YARP - 6.压缩、缓存

Welcome to YARP - 7.目标健康检查

Welcome to YARP - 8.分布式跟踪

介绍

负载均衡(Load Balancing)是一种用于分发网络流量或工作负载的技术,旨在确保多个服务器或资源之间的负载均衡分布,以提高性能、可用性和可伸缩性。负载均衡通常用于网络服务器、Web服务器、应用程序服务器和其他计算资源,以分散请求并优化资源利用。

YARP中,每当有多个正常运行的目标(服务)可用时,YARP 会决定将哪一个用于给定请求。YARP 附带内置负载均衡算法,当然你也可以自定义负载均衡算法(本文也会涉及)。

接下来带大家一步一步的去配置和使用YARP的负载均衡功能。

负载均衡配置

服务和中间件注册

负载均衡策略通过该方法 AddLoadBalancingPolicies()DI 容器中注册,该方法由 AddReverseProxy() 自动调用。

中间件添加 UseLoadBalancing() ,默认情况下包含在 MapReverseProxy 的无参数方法中。

集群配置

用于确定目标的算法可以通过设置 . LoadBalancingPolicy

如果未指定策略,则将使用 :PowerOfTwoChoices (随机找两个,然后把请求分配给最少的):

配置示例

"ReverseProxy": {
"Routes": {
"route1": {
"ClusterId": "cluster1",
"Match": {
"Path": "{**catch-all}"
}
}
},
"Clusters": {
"cluster1": {
"LoadBalancingPolicy": "RoundRobin",
"Destinations": {
"cluster1/destination1": {
"Address": "https://www.baidu.com/"
},
"cluster1/destination2": {
"Address": "https://cn.bing.com/"
}
}
}
}
}

代码示例

var clusters = new[]
{
new ClusterConfig()
{
ClusterId = "cluster1",
LoadBalancingPolicy = LoadBalancingPolicies.RoundRobin,
Destinations = new Dictionary<string, Destination>(StringComparer.OrdinalIgnoreCase)
{
{ "destination1", new DestinationConfig() { Address = "https://localhost:10000" } },
{ "destination2", new DestinationConfig() { Address = "https://localhost:10010" } }
}
}
};

效果展示:

可以看到相同的地址会按顺序循环选择目标服务。这就是 RoundRobin策列的效果。

内置策略

YARP 附带以下内置策略:

  • FirstAlphabetical

    选择按字母顺序排列的第一个可用目标,而不考虑负载。这对于双目标故障转移系统非常有用。

  • PowerOfTwoChoices (默认策略)

    选择两个随机目标,然后选择请求分配最少的目标。这避免了LeastRequest的开销,也避免了Random选择繁忙目标的最坏情况。

  • RoundRobin

    通过按顺序循环选择目的地。

  • LeastRequests

    选择请求分配最少的目标。这需要检查所有目标。

自定义策略

ILoadBalancingPolicy 负责从可用的健康目标列表中选择目标。

可以在 DI 中提供自定义实现。

// 实现 ILoadBalancingPolicy 接口
public sealed class LastLoadBalancingPolicy : ILoadBalancingPolicy
{
public string Name => "Last"; public DestinationState? PickDestination(HttpContext context, ClusterState cluster, IReadOnlyList<DestinationState> availableDestinations)
{
return availableDestinations[^1];
}
} // 注册服务到 DI
services.AddSingleton<ILoadBalancingPolicy, LastLoadBalancingPolicy>(); // 设置 cluster 的 LoadBalancingPolicy 属性为我们上述定义好的名称(Last)
// 可在代码里设置 也可以在 配置文件里设置,取决于你使用什么配置提供者
cluster.LoadBalancingPolicy = "Last";

此策略会一直选择可用目标的最后一个,这里就不做演示了,这里只是告诉大家如何去自定义策略。

粘性会话

粘性会话 也被称为"会话持久性"或"会话粘性",是一种在Web应用程序负载均衡中的会话管理技术。它用于确保来自同一客户端的多个请求在负载均衡环境下被路由到同一个后端服务器,以保持用户会话的连续性。

通常,Web应用程序在负载均衡环境中有多个后端服务器,负载均衡器用于将客户端请求分发到这些服务器上。**在某些情况下,对于特定应用程序,需要确保来自同一客户端的请求在处理过程中被路由到同一台后端服务器,以便维护用户会话状态。 **

例如:

  1. 对于需要用户身份验证的应用程序,粘性会话可以确保用户登录后的会话状态在同一服务器上保持一致。这对于管理用户身份验证和权限非常重要。

  2. 瞬态缓存(例如内存中),其中第一个请求将数据从较慢的持久存储中提取到快速的本地缓存中,而其他请求仅使用缓存的数据,从而提高吞吐量。

配置

服务和中间件注册

会话关联服务由 AddReverseProxy() 自动在 DI 容器中注册(AddSessionAffinityPolicies)。默认情况下,中间件 UseSessionAffinity() 包含在无参数的 MapReverseProxy 方法中。如果要自定义代理管道,请在添加 UseLoadBalancing() .

app.MapReverseProxy(proxyPipeline =>
{
proxyPipeline.UseSessionAffinity();
proxyPipeline.UseLoadBalancing();
});

注意:某些会话关联实现依赖于数据保护,这将需要对多个代理实例等方案进行额外配置。有关详细信息,请参阅密钥保护,本文不再涉及。

集群配置
"ReverseProxy": {
"Clusters": {
"<cluster-name>": {
"SessionAffinity": {
"Enabled": "(true|false)", // defaults to 'false'
"Policy": "(HashCookie|ArrCookie|Cookie|CustomHeader)", // defaults to 'HashCookie'
"FailurePolicy": "(Redistribute|Return503Error)", // defaults to 'Redistribute'
"AffinityKeyName": "Key1",
"Cookie": {
"Domain": "localhost",
"Expiration": "03:00:00",
"HttpOnly": true,
"IsEssential": true,
"MaxAge": "1.00:00:00",
"Path": "mypath",
"SameSite": "Strict",
"SecurePolicy": "Always"
}
}
}
}
Cookie 配置

用于配置与 HashCookie、ArrCookie 和 Cookie 策略一起使用的 cookie 的属性可以使用 SessionAffinityCookieConfig 进行配置。属性可以是如上所示的 JSON 配置,也可以是如下所示的代码:

new ClusterConfig
{
ClusterId = "cluster1",
SessionAffinity = new SessionAffinityConfig
{
Enabled = true,
FailurePolicy = "Return503Error",
Policy = "HashCookie",
AffinityKeyName = "Key1",
Cookie = new SessionAffinityCookieConfig
{
Domain = "mydomain",
Expiration = TimeSpan.FromHours(3),
HttpOnly = true,
IsEssential = true,
MaxAge = TimeSpan.FromDays(1),
Path = "mypath",
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict,
SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.SameAsRequest
}
}
}
请求管道

粘性会话机制由服务(如上所述)和以下两个中间件实现:

  1. SessionAffinityMiddleware - 协调请求的关联解决过程。首先,它调用ClusterConfig.SessionAffinity.policy 属性,为给定群集指定的策略。然后,它检查策略返回的关联解析状态,并在出现故障时调用ClusterConfig.SessionAffinity.FailurePolicy上的故障处理策略。

它必须在负载平衡器之前添加到管道中。

public static IReverseProxyApplicationBuilder UseSessionAffinity(this IReverseProxyApplicationBuilder builder)
{
builder.UseMiddleware<SessionAffinityMiddleware>();//SessionAffinityMiddleware
return builder;
}
  1. AffinitizeTransform - 如果为请求建立了新的关联,则在响应上设置键。否则,如果请求遵循现有相关性,则不执行任何操作。这将自动添加为响应转换。
public static IReverseProxyBuilder AddSessionAffinityPolicies(this IReverseProxyBuilder builder)
{
builder.Services.TryAddEnumerable(new[] {
ServiceDescriptor.Singleton<IAffinityFailurePolicy, RedistributeAffinityFailurePolicy>(),
ServiceDescriptor.Singleton<IAffinityFailurePolicy, Return503ErrorAffinityFailurePolicy>()
});
builder.Services.TryAddEnumerable(new[] {
ServiceDescriptor.Singleton<ISessionAffinityPolicy, CookieSessionAffinityPolicy>(),
ServiceDescriptor.Singleton<ISessionAffinityPolicy, HashCookieSessionAffinityPolicy>(),
ServiceDescriptor.Singleton<ISessionAffinityPolicy, ArrCookieSessionAffinityPolicy>(),
ServiceDescriptor.Singleton<ISessionAffinityPolicy, CustomHeaderSessionAffinityPolicy>()
});
builder.AddTransforms<AffinitizeTransformProvider>();//AffinitizeTransform return builder;
}

相关代码已经贴上去,详细的处理过程可以自己去了解一下。

请注意,粘性会话也可能会引入一些挑战,例如单点故障问题和服务器不均衡。因此,在选择使用粘性会话时,需要仔细考虑应用程序的需求和负载均衡策略。不是所有应用程序都需要粘性会话,而有时可以使用其他方法来管理会话状态。选择是否使用粘性会话通常取决于特定的业务需求。

扩展知识

与本章节的内容关系不大

在其他文章的评论里我们了解到YARP的性能,这是一个园友贴出来的性能对比图。

看到了这两个(nginxhaproxy)我们想到了 k8s Ingress。k8s 的 Ingress Controller常用的两款软件就是 NginxHaproxy。 而YARP有一个k8s的扩展包就是对k8s的支持, 用于监视 kubernetes 入口对象并将 yarp配置为指向服务 ips 。对于.NET 并且上了 k8s 的团队 而言,YARP也是一个不错的选择。如何使用请参考: 如何在 Docker Desktop (KinD) 的 Kubernetes 中使用 YARP 作为入口控制器 Windows

我曾经待过的一个公司就规划了基于YARP并结合我们自己的配置中心或另启一个 Gateway 项目专门做网关,而且还要和 K8S 的 Ingress Controller 打通,所有的配置都可以在 配置中心 或者 Gateway 项目中进行操作,不仅运维方便,而且不熟悉k8s的开发也可以操作。

总结

本章我们使用YARP对服务进行了负载均衡配置,而且有不同的策略供我们选择,可以达到故障转移优化资源等效果。本章源码已上传GitHub在 YARP.LoadBalancing 文件夹下

下篇文章我们继续讲如何使用YARP限流 功能

Welcome to YARP - 3 负载均衡 (Load Balancing)的更多相关文章

  1. Oracle RAC 客户端连接负载均衡(Load Balance)

    实现负载均衡(Load Balance)是Oracle RAC最重要的特性之一,主要是把负载平均分配到集群中的各个节点,以提高系统的整体吞吐能力.通常情况下有两种方式来实现负载均衡,一个是基于客户端连 ...

  2. Oracle RAC 服务器端连接负载均衡(Load Balance)

    Oracle RAC服务器端的负载均衡是根据RAC中各节点的连接负荷数情况,将新的连接请求分配到负荷最小的节点上去.当数据库处于运行时,RAC中各节点的PMON进程每3秒会将各自节点的连接负荷数更新到 ...

  3. &quot;高可用方案工具包&quot; high availability toolkit 1.2 公布了。version 1.2 新增了 负载均衡 load balance 的技术实现

    "高可用方案工具包"  high availability toolkit 1.2 公布了. version 1.2 新增了 负载均衡 load balance 的技术实现. 项目 ...

  4. 【高可用HA】Nginx (1) —— Mac下配置Nginx Http负载均衡(Load Balancer)之101实例

    [高可用HA]Nginx (1) -- Mac下配置Nginx Http负载均衡(Load Balancer)之101实例 nginx版本: nginx-1.9.8 参考来源: nginx.org [ ...

  5. 【高可用HA】Apache (4) —— Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_jk

    Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_jk httpd版本: httpd-2.4.17 jk版本: tomcat-connectors-1.2.41 参考 ...

  6. 【高可用HA】Apache (3) —— Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_proxy

    Mac下配置Apache Httpd负载均衡(Load Balancer)之mod_proxy httpd版本: httpd-2.4.17 参考来源: Apache (1) -- Mac下安装Apac ...

  7. 章文嵩博士和他背后的负载均衡(LOAD BANLANCER)帝国

    案首语: 阿里集团技术大牛,@正明,淘宝基础核心软件研发负责人.LVS创始人.阿里云首席科学家章文嵩博士从阿里离职,去追求技术人生另一段历程,让阿里像我一样的很多热爱技术的工程师都有一丝牵动和感触. ...

  8. 干货 | 亿级Web系统负载均衡几种实现方式

    一个执着于技术的公众号 负载均衡(Load Balance)是集群技术(Cluster)的一种应用技术.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用是Web ...

  9. 亿级Web系统负载均衡几种实现方式

    负载均衡(Load Balance)是集群技术(Cluster)的一种应用技术.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用是Web负载均衡.根据实现的原理 ...

  10. 服务发现与负载均衡 dubbo zk原理

    服务发现与负载均衡 拓展阅读 : dubbo 原理概念图 2016-03-03 杜亦舒 性能与架构 性能与架构 性能与架构 微信号 yogoup 功能介绍 网站性能提升与架构设计 内容整理自文章“实施 ...

随机推荐

  1. 开源.NetCore通用工具库Xmtool使用连载 - 发送短信篇

    [Github源码] <上一篇> 介绍了Xmtool工具库中的发送邮件类库,今天我们继续为大家介绍其中的发送短信类库. 发送短信就像发送邮件一样,在软件系统中使用非常普遍,甚至比发送邮件还 ...

  2. springboot 实现拦截的 3 种方式介绍及异步执行的思考

    springboot 拦截方式 实际项目中,我们经常需要输出请求参数,响应结果,方法耗时,统一的权限校验等. 本文首先为大家介绍 HTTP 请求中三种常见的拦截实现,并且比较一下其中的差异. (1)基 ...

  3. 【Unity3D】同步Socket通讯

    1 前言 ​ 在多人对战网络游戏中,玩家之间一般不是直接通讯,而是与服务器通讯,服务器再把消息转发给其他玩家.网络通讯一般基于 Socket 实现,也有一些开源网络游戏框架,如:光子引擎 Photon ...

  4. Oracle 表压缩(Table Compression)技术介绍

    Oracle 表压缩(Table Compression)介绍 1.官方文档说法: As your database grows in size, consider using table compr ...

  5. 全栈式测试平台RunnerGo核心功能模块-接口管理

    ​全栈式测试平台RunnerGo相对于市面上其他性能测试产品来说更简单,它不用其他相关配件,天然支持分布式,有单独的机器做分布式的负载均衡,自有一套智能算法算压力机的配置从而平均分配,并从场景链路的流 ...

  6. Golang Web 框架 Gin 基础学习教程集合目录

    Gin Web 框架基础学习系列目录 01-quickstart 02-parameter 03-route 04-middleware 05-log 06-logrus 07-bind 08-val ...

  7. OpenCV开发笔记(五十七):红胖子8分钟带你深入了解直方图反向投影(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

  8. Gitlab中的打包作业完成后,更新http服务器里的版本号文件

    背景 在.gitlab-ci.yml里面,我们有4个场景 dotnet build.dotnet pack和dotnet push 单元测试 SSH到http服务器,更新对应的版本号文件里面的版本数字 ...

  9. TypeScript项目开发运行(即时编译、运行,所见所得)

    1.项目*.ts自动编译 $ tsc . --watch 2.项目本地web服务运行 $ npm install --save-dev webpack-dev-server npm install - ...

  10. javascript浮点数相减、相乘出现一长串小数

    149.7 * 100 = 14969.999999999998 3.57 - 2.33 = 1.2399999999999998 这是JavaScript浮点运算采用IEEE 754标准导致的Bug ...