服务网格 ASM 负载均衡算法全面解析

简介: 在本文中,笔者将解析服务网格的多种负载均衡算法的实现原理和使用场景,为服务网格负载均衡算法的选择提供参考。

【阅读原文】戳:服务网格 ASM 负载均衡算法全面解析


引言:当今,分布式微服务是毫无争议地主流架构模式,微服务将复杂大型系统拆分成多个松耦合的微型系统,以此使得大型系统的迭代更为灵活,容错率也变得更高。对于其中的单一微服务,支持横向扩容,以根据业务情况灵活地调整系统中每个服务所使用的资源。要正确地调用多副本服务,有两个基础的问题需要解决:服务发现和负载均衡。K8s作为当前业界广泛采用的部署平台,通过服务(Service)非入侵式地解决了服务发现和负载均衡的问题,但是,面对日益复杂的业务场景,K8s服务仍然存在一些不尽人意之处,例如,其负载均衡算法仅支持随机,而对于一些特定场景,随机算法的表现较差,且没有调优余地。因此,越来越多地微服务运维团队选择了服务网格作为网络基础设施,其在K8s服务的基础上,提供了比K8s更强大的负载均衡能力。在本文中,笔者将解析服务网格的多种负载均衡算法的实现原理和使用场景,为服务网格负载均衡算法的选择提供参考。

 

 

服务网格负载均衡的优势

 

K8s Service通过iptables规则,实现了连接级别的负载均衡,这种负载均衡不需要入侵应用,而是直接从网络层面将流量做DNAT,实现了负载均衡。但K8s的负载均衡存在一些显著的缺陷,首先,由于其使用iptables规则实现负载均衡,这使得K8s的负载均衡算法的时间复杂度是O(n),因此在集群规模逐渐膨胀时,负载均衡的性能可能受到显著影响。其次,其只支持随机负载均衡算法,这种算法并不能严格地将请求均匀地分布到后端实例上。由于其基于iptables规则实现的缘故,因为其工作在3层(IP层),因此只能做到4层,即TCP连接级别的负载均衡,而当今大多数主流应用使用HTTP/GRPC协议进行通信,基于iptables规则实现的K8s服务负载均衡注定无法实现请求级别的路由。而服务网格控制平面从K8s集群ApiServer获得工作负载和服务信息,并将这些信息下发至SIdecar,借助其7层能力,支持对HTTP/GRPC请求实现请求级负载均衡,同时支持了适用于多种场景的负载均衡算法,用户可以根据业务特性,为特定服务选择适用的负载均衡算法,以更高效地利用系统资源。


 


 

 

负载均衡算法

 

服务网格ASM提供了多种负载均衡算法,其中包括与社区Istio兼容的RANDOM、ROUND_ROBIN,LEAST_REQUEST以及ASM特有的PEAK_EWMA。在本文接下来的内容中,笔者将逐一分析每种负载均衡算法的特点及其适用场景。

 

 

RANDOM和ROUND_ROBIN

 

服务网格ASM提供了经典的随机(RANDOM)和轮询(ROUND_ROBIN)算法,对于随机负载均衡,与K8s服务不同的是,由于ASM Sidecar工作在7层,因此对于HTTP、GRPC协议的通信可以提供请求级别的随机负载均衡。随机负载均衡由于随机计算本身的不稳定性,不能保证请求完全均匀地分布到后端。此时若工作负载的性能和请求产生的计算量都比较平均,则可以考虑使用轮询算法进行负载均衡,轮询算法可以完全平均地将请求分布到后端工作负载。这两种算法被广泛使用在各种分布式系统的负载均衡中,它们足够简单直观,且被几乎所有负载均衡软硬件支持,但是,在实践中却存在一些场景,使得这两种算法的表现不尽人意。

 

 

RANDOM和ROUND_ROBIN的不足之处

 

由于RANDOM和ROUND_ROBIN两种负载均衡算法均是完全不考虑后端服务状态,仅使用本地状态计算得出负载均衡结果的算法,因此,后端服务状态变化完全不会影响到负载均衡计算的结果,从而导致做出不够理想的负载均衡决策,例如以下这些场景:

 

1.后端处理能力不均衡

 

在后端处理能力不均衡时,完全均衡地分布请求反而会影响服务质量,由于后端负载能力不平均,处理能力弱的后端会更早过载,而负载均衡算法仍然以平均分配的方式将请求分配至后端,这些被分配至已过载的后端的请求会加剧已过载后端的压力,进一步恶化服务的延迟,影响服务的整体表现,例如下图例子中,Server-1的处理能力更强,还能够接受新的请求,而Server-2已经满载,但随机或者轮询负载均衡算法仍然将新请求打到Server-2,而不是尚有余力的Server-1,这将导致这个请求的返回实践因Server-2的满载而显著延长。


 


 

2.请求计算量不平均

 

即使后端的处理能力类似,同类请求对后端造成的压力也可能存在显著的差异,一个典型的例子是LLM应用,同样是几个单词的prompt,“write me a novel”和“what is the time”两个prompt在后端计算量上的差异可谓天壤之别,因此返回时间可能也存在显著差异,例如下图的例子中,Server-1和Server-2正在处理的请求虽然都是2个,但是,Server-2处理了一个大计算量的请求,导致其已经满载,然而随机或者轮询负载均衡算法仍然将新请求打到Server-2,而不是尚有余力的Server-1,这将导致这个请求的返回实践因Server-2的满载而显著延长。

 

即使是在请求计算量大致均等的场景下,错误的请求也可能导致类似的问题,例如客户端发送了错误的请求,服务端可能在校验失败后不做任何处理就立即返回,就会间接导致请求计算量不平均的问题。

 


 


 

如何避免RANDOM和ROUND_ROBIN的不足

 

RANDOM和ROUND_ROBIN存在的缺陷本质上还是因为负载均衡无法感知后端的状态所致,理论上来说,最优的负载均衡决策应该结合后端实时状态和请求的潜在计算量做出,然而,这两者在真正的负载均衡实现中都存在很大的挑战,那么是否存在对后端状态间接感知的方式呢?笔者将在下面的篇幅中介绍ASM支持的另外两种负载均衡算法。

 

 

LEAST_REQUEST

 

LEAST_REQUEST算法在用户未显式指定时被作为ASM默认提供的负载均衡算法,该负载均衡器会记录当前每个后端上未完成的请求数量,处理能力更强的后端往往会因请求更快完成而更快地消耗这个计数,负载均衡器借助这个现象来间接感知后端的压力状态,并总是将请求路由到未完成请求数最少的后端。

 

下面,我们来通过例子直观地感受一下LEAST_REQUEST的优势,首先以前面提到过的后端处理能力不均衡场景为例,在T1时刻,负载均衡向Server-1和Server-2分别分配了3个请求,由于Server-1的并发处理能力更大,到T2时刻时,Server-1已经完成了对全部3个请求的处理,而Server-2仍然有一个请求未完成处理,由于LEAST_REQUEST总是会向进行中请求最少的后端分配请求,因此,新到达的请求被分配至负载更低的Server-1。


 


 

我们再来看看请求计算量不均的场景,这个场景下同样的请求对后端的计算复杂度差异显著,下图例子中,在T1时刻,Server-1有2个进行中的请求,Server-2只有一个,但Server-2处理的是一个大计算量请求(例如一个复杂的Prompt)。到T2时刻,Server-1的2个请求都已经返回,而Server-2尚未完成一个复杂请求的计算和返回。此时,如果负载均衡器收到了新的请求,由于Server-1的进行中请求数量少于Server-2,新请求会被分配至Server-1。


 

 


结合上述两个例子,我们可以直观地看到LEAST_REQUEST负载均衡算法在应对更加复杂场景时相对于RANDOM和ROUND_ROBIN算法表现出了更强的自适应能力,通过进行中请求数的变化实时地感知后端地状态以做出更优的负载均衡决策,降低请求平均延迟,提升整个系统的利用率。这样的特性非常适合对于同类请求计算量差异的AI场景。

 

LEAST_REQUEST能在绝大多数情况下提供较好的负载均衡表现,但是LESAT_REQUEST是任何情况下的最优解吗?我们不妨思考这样一种情况,当后端因为异常出现报错时,由于错误请求没有被实际处理,往往会立即返回,LEAST_REQUEST负载均衡器中记录的报错节点的进行中的请求数量会快速降低,该后端在该评价体系下被误认为是“高性能”的,因此更多的请求被分配到发生错误的后端,进而造成系统的整体错误率提升。显然,这个缺陷是由于LEAST_REQUEST评估体系无法感知错误率的存在导致的,那么是否有更好的选择呢,接下来,笔者将介绍ASM提供的PEAK_EWMA负载均衡器。

 

 

PEAK_EWMA

 

 

ASM在1.21版本提供了PEAK_EWMA负载均衡器,该负载均衡器会ASM结合端点在过去一段时间内的响应时间、错误率,静态权重等因子计算出端点的负载均衡权重计算节点的分值,在一段时间内响应时间越短、错误率越低,静态权重越高,则该节点的分值越高,更容易被负载均衡选中。相比于LEAST_REQUEST,PEAK_EWMA的感知范围更全面,延迟升高、错误率上升都会造成该后端的权重降低,更少的请求被路由到这个后端,从而尽可能地提升服务整体地延迟和成功率表现。

 

这里我们提供了一个PEAK_EWMA负载均衡器的端到端实例,该示例使用simple-server应用作为服务端,该应用可通过启动参数指定,模拟不同状态码返回、随机延迟范围等多种服务端响应行为。在本例中,我们将部署两个Deployment,其中名为simple-server-503的deployment使用--mode=503启动参数设置为固定返回503,模拟一个收到请求立即返回503状态码的后端;名为simple-server-normal的deployment则使用--mode=normal--delayMin=50--delayMax=200模拟一个正常返回200的后端,其处理延迟在50-200之间波动。


 

 

 


前提条件

 

已创建ASM 1.21或以上版本的实例

已创建K8s 1.21或以上版本的集群,并已将K8s集群添加至ASM实例

 

 

部署示例

 

在K8s集群中通过以下yaml部署simple-server应用和服务,以及用于发起测试流量的sleep应用:


apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: simple-server
  name: simple-server-normal
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: simple-server
  template:
    metadata:
      labels:
        app: simple-server
    spec:
      containers:
      - args:
        - --mode
        - normal
        image: registry-cn-hangzhou.ack.aliyuncs.com/test-public/simple-server:v1.0.0.2-gae1f6f9-aliyun
        imagePullPolicy: IfNotPresent
        name: simple-server
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: simple-server
  name: simple-server-503
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: simple-server
  template:
    metadata:
      labels:
        app: simple-server
    spec:
      containers:
      - args:
        - --mode
        - "503"
        image: registry-cn-hangzhou.ack.aliyuncs.com/test-public/simple-server:v1.0.0.2-gae1f6f9-aliyun
        imagePullPolicy: IfNotPresent
        name: simple-server
        env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: metadata.name
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: simple-server
  name: simple-server
  namespace: default
spec:
  ports:
  - name: http
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app: simple-server
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      terminationGracePeriodSeconds: 0
      serviceAccountName: sleep
      containers:
      - name: sleep
        image: registry-cn-hongkong.ack.aliyuncs.com/test/curl:asm-sleep
        command: ["/bin/sleep", "infinity"]
        imagePullPolicy: IfNotPresent

 


为了避免ASM默认存在的重试机制(默认重试2次)对验证结果造成影响,我们通过为simple-server应用VirtualService来显式地关闭重试。使用ASM实例的kubeconfig,应用以下VirtualService:

 

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: simple-server
  namespace: default
spec:
  hosts:
    - simple-server.default.svc.cluster.local
  http:
    - name: default
      retries:
        attempts: 0 # 关闭重试
      route:
        - destination:
            host: simple-server.default.svc.cluster.local

 


使用K8s集群kubeconfig,执行以下命令来发起测试:

 

$ kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 10); do curl -s -o /dev/null -w "%{http_code}\n" simple-server:8080/hello; done'
200
200
200
503
503
503
503
503
200
503

 


可以看到,由于simple-server服务下有一个后端是固定返回503的,默认的LEAST_REQUEST并不能很好地在负载均衡阶段避开返回错误的节点。接下来我们来看看ASM的PEAK_EWMA负载均衡器的表现,在ASM实例中应用以下DestinationRule,为simple-server服务启用PEAK_EWMA负载均衡器:

 

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: simple-server
  namespace: default
spec:
  host: simple-server.default.svc.cluster.local
  trafficPolicy:
    loadBalancer:
      simple: PEAK_EWMA
---

 


使用同样的命令再次执行测试:

 

$ kubectl exec -it deploy/sleep -c sleep -- sh -c 'for i in $(seq 1 10); do curl -s -o /dev/null -w "%{http_code}\n" simple-server:8080/hello; done'
200
503
200
200
200
200
200
200
200
200

 


可以看到,在返回了一个503后,后续全部都是200,这是因为PEAK_EWMA负载均衡器在后端返回503后,导致错误率上升,从而降低了该断点的分值,因此在之后的一段时间内,该后端将在分值比较时低于正常的后端,因此不会被选择到。但是,过一段时间后,这种影响因为移动平均的缘故又被消除,从而使得负载均衡器可以重新选择到该后端。我们在前文提到过,PEAK_EWMA算法不仅可以感知后端的错误率,同时还可以感知后端延迟变化,尽可能将请求路由给延迟更低的端点,关于这一点ASM官方文档提供了一个例子,欢迎各位读者前往体验。

 

 

总结

 

负载均衡是一个现代分布式应用绕不开的一个重要话题,每一种负载均衡都有其适用的场景,根据业务场景正确地选择负载均衡算法能为应用带来更好的表现。阿里云服务网格ASM团队在结合了大量客户实际场景后,于1.21版本推出了PEAK_EWMA负载均衡算法,该负载均衡算法在传统的负载均衡算法上更进一步,提供了综合后端延迟、错误率、静态权重的负载均衡选择能力,让负载均衡能够动态适应应用状态的变化,做出更优的负载均衡决策,从而提升应用的全局表现。



我们是阿里巴巴云计算和大数据技术幕后的核心技术输出者。

欢迎关注 “阿里云基础设施”同名微博知乎

获取关于我们的更多信息~

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
4月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
5月前
|
机器学习/深度学习 人工智能 搜索推荐
从零构建短视频推荐系统:双塔算法架构解析与代码实现
短视频推荐看似“读心”,实则依赖双塔推荐系统:用户塔与物品塔分别将行为与内容编码为向量,通过相似度匹配实现精准推送。本文解析其架构原理、技术实现与工程挑战,揭秘抖音等平台如何用AI抓住你的注意力。
1396 7
从零构建短视频推荐系统:双塔算法架构解析与代码实现
|
5月前
|
机器学习/深度学习 存储 算法
动态规划算法深度解析:0-1背包问题
0-1背包问题是经典的组合优化问题,目标是在给定物品重量和价值及背包容量限制下,选取物品使得总价值最大化且每个物品仅能被选一次。该问题通常采用动态规划方法解决,通过构建二维状态表dp[i][j]记录前i个物品在容量j时的最大价值,利用状态转移方程避免重复计算子问题,从而高效求解最优解。
672 1
|
5月前
|
算法 搜索推荐 Java
贪心算法:部分背包问题深度解析
该Java代码基于贪心算法求解分数背包问题,通过按单位价值降序排序,优先装入高价值物品,并支持部分装入。核心包括冒泡排序优化、分阶段装入策略及精度控制,体现贪心选择性质,适用于可分割资源的最优化场景。
404 1
贪心算法:部分背包问题深度解析
|
5月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
5月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
机器学习/深度学习 算法 自动驾驶
1063 0
|
5月前
|
机器学习/深度学习 人工智能 资源调度
大语言模型的核心算法——简要解析
大语言模型的核心算法基于Transformer架构,以自注意力机制为核心,通过Q、K、V矩阵动态捕捉序列内部关系。多头注意力增强模型表达能力,位置编码(如RoPE)解决顺序信息问题。Flash Attention优化计算效率,GQA平衡性能与资源消耗。训练上,DPO替代RLHF提升效率,MoE架构实现参数扩展,Constitutional AI实现自监督对齐。整体技术推动模型在长序列、低资源下的性能突破。
669 8
|
5月前
|
算法 API 数据安全/隐私保护
深度解析京东图片搜索API:从图像识别到商品匹配的算法实践
京东图片搜索API基于图像识别技术,支持通过上传图片或图片URL搜索相似商品,提供智能匹配、结果筛选、分页查询等功能。适用于比价、竞品分析、推荐系统等场景。支持Python等开发语言,提供详细请求示例与文档。
|
7月前
|
机器学习/深度学习 人工智能 编解码
AI视觉新突破:多角度理解3D世界的算法原理全解析
多视角条件扩散算法通过多张图片输入生成高质量3D模型,克服了单图建模背面细节缺失的问题。该技术模拟人类多角度观察方式,结合跨视图注意力机制与一致性损失优化,大幅提升几何精度与纹理保真度,成为AI 3D生成的重要突破。
858 0

相关实验场景

更多

推荐镜像

更多
  • DNS