Welcome to YARP - 3 负载均衡 (Load Balancing)
目录
Welcome to YARP - 1.认识YARP并搭建反向代理服务
- 2.1 - 配置文件(Configuration Files)
- 2.2 - 配置提供者(Configuration Providers)
- 2.3 - 配置过滤器(Configuration Filters)
介绍
负载均衡(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应用程序在负载均衡环境中有多个后端服务器,负载均衡器用于将客户端请求分发到这些服务器上。**在某些情况下,对于特定应用程序,需要确保来自同一客户端的请求在处理过程中被路由到同一台后端服务器,以便维护用户会话状态。 **
例如:
对于需要用户身份验证的应用程序,粘性会话可以确保用户登录后的会话状态在同一服务器上保持一致。这对于管理用户身份验证和权限非常重要。
瞬态缓存(例如内存中),其中第一个请求将数据从较慢的持久存储中提取到快速的本地缓存中,而其他请求仅使用缓存的数据,从而提高吞吐量。
配置
服务和中间件注册
会话关联服务由 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
}
}
}
请求管道
粘性会话机制由服务(如上所述)和以下两个中间件实现:
SessionAffinityMiddleware- 协调请求的关联解决过程。首先,它调用ClusterConfig.SessionAffinity.policy属性,为给定群集指定的策略。然后,它检查策略返回的关联解析状态,并在出现故障时调用ClusterConfig.SessionAffinity.FailurePolicy上的故障处理策略。
它必须在负载平衡器之前添加到管道中。
public static IReverseProxyApplicationBuilder UseSessionAffinity(this IReverseProxyApplicationBuilder builder)
{
builder.UseMiddleware<SessionAffinityMiddleware>();//SessionAffinityMiddleware
return builder;
}
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的性能,这是一个园友贴出来的性能对比图。
看到了这两个(nginx 和 haproxy)我们想到了 k8s 的 Ingress。k8s 的 Ingress Controller常用的两款软件就是 Nginx 和 Haproxy。 而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)的更多相关文章
- Oracle RAC 客户端连接负载均衡(Load Balance)
实现负载均衡(Load Balance)是Oracle RAC最重要的特性之一,主要是把负载平均分配到集群中的各个节点,以提高系统的整体吞吐能力.通常情况下有两种方式来实现负载均衡,一个是基于客户端连 ...
- Oracle RAC 服务器端连接负载均衡(Load Balance)
Oracle RAC服务器端的负载均衡是根据RAC中各节点的连接负荷数情况,将新的连接请求分配到负荷最小的节点上去.当数据库处于运行时,RAC中各节点的PMON进程每3秒会将各自节点的连接负荷数更新到 ...
- "高可用方案工具包" high availability toolkit 1.2 公布了。version 1.2 新增了 负载均衡 load balance 的技术实现
"高可用方案工具包" high availability toolkit 1.2 公布了. version 1.2 新增了 负载均衡 load balance 的技术实现. 项目 ...
- 【高可用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 [ ...
- 【高可用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 参考 ...
- 【高可用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 ...
- 章文嵩博士和他背后的负载均衡(LOAD BANLANCER)帝国
案首语: 阿里集团技术大牛,@正明,淘宝基础核心软件研发负责人.LVS创始人.阿里云首席科学家章文嵩博士从阿里离职,去追求技术人生另一段历程,让阿里像我一样的很多热爱技术的工程师都有一丝牵动和感触. ...
- 干货 | 亿级Web系统负载均衡几种实现方式
一个执着于技术的公众号 负载均衡(Load Balance)是集群技术(Cluster)的一种应用技术.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用是Web ...
- 亿级Web系统负载均衡几种实现方式
负载均衡(Load Balance)是集群技术(Cluster)的一种应用技术.负载均衡可以将工作任务分摊到多个处理单元,从而提高并发处理能力.目前最常见的负载均衡应用是Web负载均衡.根据实现的原理 ...
- 服务发现与负载均衡 dubbo zk原理
服务发现与负载均衡 拓展阅读 : dubbo 原理概念图 2016-03-03 杜亦舒 性能与架构 性能与架构 性能与架构 微信号 yogoup 功能介绍 网站性能提升与架构设计 内容整理自文章“实施 ...
随机推荐
- jwt 生成的token exp 的单位是秒
public class Test { public static void main(String[] args) throws UnsupportedEncodingException { Dat ...
- 利用ogg实现oracle到kafka的增量数据实时同步
前言 ogg即Oracle GoldenGate是Oracle的同步工具,本文讲如何配置ogg以实现Oracle数据库增量数据实时同步到kafka中,其中同步消息格式为json. 下面是我的源端和目标 ...
- 分布式图算法Pregel
最近看了Google的Pregel论文,图算法有一些经典且不可被替代的应用场景,如社交网络,相互引用等.但是在单个结点上的运算量往往过少,注重的是消息传播和逻辑处理,而不是单纯的大规模计算.虽然已经过 ...
- postgresql备份和恢复操作
1.介绍 最近项目上用了postgresql数据库,部署的时候需要备份数据库并在现场进行恢复操作,特此记录.我是在windows上安装的pgadmin4,此处用cmd下操作的: 备份命令:pg_dum ...
- Idea:Fetch failed: fatal: Could not read from remote repository
今天在idea工具中fetch github仓库报错:Fetch failed: fatal: Could not read from remote repository 查了以下需要调整下setti ...
- std::weak_ptr 与 std::shared_ptr 配合使用
std::shared_ptr<int> a = std::make_shared<int>(2); std::weak_ptr<int> b = a; a = n ...
- win32-GetActiveWindow和GetForegroundWindow
最近被这两个api搞得有点晕,故查阅了相关的资料. 这篇文章解释的很好:https://devblogs.microsoft.com/oldnewthing/20081006-00/?p=20643 ...
- win32 - IFileDialog接口的使用
官方示例: CommonFileDialogModes.cpp 如果我们想要自己创建一个通用的文件对话框,则可以使用IFileOpenDialog接口,代码参考: HRESULT BasicFileO ...
- etcd实现分布式锁分析
3篇关于分布式锁的文章,可以结合看: consul实现分布式锁:https://www.cnblogs.com/jiujuan/p/10527786.html redis实现分布式锁:https:// ...
- ThreadLocal的应用场景和注意事项有哪些?
https://cloud.tencent.com/developer/article/1618405