目录

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. Winows11-hosts文件无法修改保存

    Win11系统hosts文件无法修改保存 新近使用win11新电脑修改hosts,添加IP和主机名映射,保存时提示host无法修改. 解决办法: 1.将hosts文件的权限"只读" ...

  2. Linux--top命令解释

    top命令解释 1.1 系统运行时间和平均负载: top命令的顶部显示与uptime命令相似的输出 这些字段显示: 当前时间 系统已运行的时间 当前登录用户的数量 相应最近5.10和15分钟内的平均负 ...

  3. 开源.NetCore通用工具库Xmtool使用连载 - 散列算法篇

    [Github源码] <上一篇>详细介绍了Xmtool工具库中的加解密类库,今天我们继续为大家介绍其中的散列算法类库. 散列算法在某些特殊场景也可以当做加密方法使用:其特点是不可逆,同一内 ...

  4. JS Leetcode 530. 二叉搜索树的最小绝对差 题解分析,再次了解中序遍历

    壹 ❀ 引 本题来自LeetCode 783. 二叉搜索树节点最小距离,题目描述如下: 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 . 示例 1: 输入:root ...

  5. Python list 中删除元素的方法

    在python列表中删除元素主要分为以下3种场景: 根据目标元素所在的索引位置进行删除,可以使用del关键字或pop()方法:根据元素本身的值进行删除,可使用列表(list类型)提供的remove() ...

  6. 玩转 CMS2

    玩转 CMS2 上篇研究了样式.请求.evn.mock,感觉对效率的提升没有太明显作用. 比如某个工作需要2天,现在1天可以干完,这就是很大的提升. 提高效率的方法有代码复用.模块化.低代码工具. 目 ...

  7. 【Unity3D】UGUI之Button

    1 Button属性面板 ​ 在 Hierarchy 窗口右键,选择 UI 列表里的 Button 控件,即可创建 Button 控件,选中创建的 Button 控件,按键盘[T]键,可以调整 But ...

  8. 识别主机名和IP地址

    文章来源:https://oracle-base.com/articles/misc/identifying-host-names-and-addresses Identifying Host Nam ...

  9. 记一次 .NET某列控连锁系统 崩溃分析

    一:背景 1. 讲故事 过年喝了不少酒,脑子不灵光了,停了将近一个月没写博客,今天就当新年开工写一篇吧. 去年年初有位朋友找到我,说他们的系统会偶发性崩溃,在网上也发了不少帖子求助,没找到自己满意的答 ...

  10. del,str,repr,call,bool,add,len等魔术方法以及与类相关的魔术属性---day23

    1.__del__ # ### __del__魔术方法(析构方法) ''' 触发时机:当对象被内存回收的时候自动触发(1.页面执行完毕回收所有变量2.所有对象被del的时候) 功能:对象使用完毕后资源 ...