当前位置: 首页 > news >正文

得物彩虹桥架构演进之路-负载均衡篇

文 / 新一

一、前言

一年一更的彩虹桥系列又来了,在前面两期我们分享了在稳定性和性能2个层面的一些演进&优化思路。近期我们针对彩虹桥 Proxy 负载均衡层面的架构做了一次升级,目前新架构已经部署完成,生产环境正在逐步升级中,借此机会更新一下彩虹桥架构演进之路系列的第三篇。

阅读本文预计需要20~30分钟,建议不熟悉彩虹桥的同学在阅读本文前,可以先看一下前两篇彩虹桥架构演进的文章:

得物数据库中间件平台“彩虹桥”演进之路

彩虹桥架构演进之路-性能篇|得物技术

二、背景

彩虹桥目前依赖 SLB 做负载均衡和节点发现,随着业务发展流量越来越高,SLB 带宽瓶颈逐渐暴露,虽然在半年前做过一次双 SLB 改造临时解决了带宽瓶颈,但运维成本也随之变高。除了带宽瓶颈外,SLB 无法支持同区优先访问,导致难以适配双活架构。所以准备去除彩虹桥对 SLB 的强依赖,自建彩虹桥元数据中心,提供负载均衡和节点发现等能力,同时支持同区访问等能力来更好的适配双活架构。下面会详细介绍一下彩虹桥元数据中心以及 SDK 相关能力的相关细节。

三、核心名称解释

图片

四、现有架构回顾

在开始介绍彩虹桥元数据中心之前,我们先来回顾一下彩虹桥目前架构,以及存在的一些痛点。

现有架构

图片

  • 业务服务集成 SDK 通过域名访问,请求经过 SLB 转发到具体的 Proxy 节点。

  • 每个集群挂载双 SLB,SDK 通过 DNS 解析轮训路由到2个 SLB,2个 SLB 挂载不同的后端节点。

  • 每个集群部署的 Proxy 节点均为一个可用区,双活架构为集群维度多可用区部署。

  • 业务侧大多数为多可用区混布,单同一个逻辑库只会连接一个彩虹桥集群,由于彩虹桥一个集群内的节点均为同一可用区,所以业务服务-彩虹桥这条链路必然会出现一半节点跨区访问。

  • 彩虹桥集群按照业务域划分,彩虹桥集群所属业务域的 RDS 大多数都会跟彩虹桥集群同区。比如彩虹桥交易集群为i区,归属交易集群的逻辑库挂载的 RDS 大多数也都是i区。

主要痛点

  • SLB 带宽已达瓶颈(5Gb/s,历史上出现过多次 SLB 带宽达到 100%的情况),目前彩虹桥单集群挂载了双 SLB 暂时解决带宽瓶颈但仍存在痛点:

    1. SLB 扩容流程较复杂(配置监听、配置虚拟服务器组、监听绑定虚拟服务组,配置调度算法、更新域名解析的等),基于目前发布系统能力无法实现全自动化。根据之前混沌工程演练结果,SLB 扩容流程需要30分钟左右。

    2. SLB 扩容后,需要改域名解析,DNS 解析生效需要一段时间(域名 TTL 1 分钟,本地缓存10分钟),新 SLB 需要10分钟左右才开始逐渐承载流量,无法实现 SLB 快速扩容。

  • 单可用区故障时,需要人工操作切流到其他可用区集群,SLA 难以保证(目前无法自动化判定单可用区故障,且集群级别流量调度需要人工预估集群负载,难以实现自动化切流)。

  • SLB 目前支持最低权重为1/100,粒度较粗,无法支撑发布过程中的更小流量灰度需求。

  • Proxy 单个集群所有节点均为同一个 AZ,需要与下游 RDS 保证同 AZ,跨集群流量调度灵活性差,很难实现多可用区流量均衡(目前由于大部分 RDS 为 I 区,Proxy 多可用区流量非常不均衡:i区 90%/k 区流量 10%)。

五、自建元数据中心&SDK 增强

图片

元数据中心独立部署

  • 新增 Metadata 数据库,多可用区部署(需要跟集群中的 Proxy 同区)。

  • 新增 MetaCenter 服务,多可用区部署。

  • Proxy 连接所有 Metadata 数据库,注册&心跳都会写入到所有数据库。

  • MetaCenter 服务定时查询所有 metadata 数据库,基于心跳版本号和多个数据库的并集筛选出健康的节点列表存储到内存中。

  • MetaCenter 服务提供 API,查询 MetaCenter 内存中的可用节点列表数据。

  • SDK 启动时会去通过7层 SLB 访问 MetaCenter 提供的 API 拉取节点列表并存储到内存,运行中每隔 5s 更新一次。

  • MetaCenter 每次计算时如果有节点下线,通过 ARK 实时下发拉取事件给 SDK,SDK 会立刻重新拉取一次节点列表。

  • SDK 通过下发的节点列表做负载均衡,优先路由到同可用区的 Proxy 节点,其次按照节点权重轮训。

  • SDK 轮训间隔时间和节点变更事件下发开关均为可配置,实时生效。

架构详解

Metadata 数据库

图片

节点表结构设计

  • beat_version:心跳版本号,只有上报心跳时会更新。

  • config_version:配置版本号,更新权重&状态时会更新。

  • enabled:是否启用

Proxy

节点启动时

  • 注册:启动时会去所有 metadata 数据库注册当前节点,如果 node_info 不存在对应节点记录,则新增,如果存在则修改权重为初始权重。

  • 启动完成后需要调用 bifrost-admin 提供的调用节点启用 API(发布脚本)

update node_info set weight = 1, config_version = #{config_version}where cluster_name = ? and address = ?

节点运行时

  • 心跳:定时更新所有 metadata 数据库节点记录的 beat_version 字段

update node_info set beat_version = beat_version + 1 where cluster_name = ? and address = ?

节点下线

  • 调用 bifrost-admin 提供的下线 OPEN API(发布脚本)

MetaCenter( Heimdall) 

  • 启动时

初始化心跳版本号:记录所有 metadata 数据库每个节点最新 beat_version 和初始化心跳丢失次数到内存

图片

图片

  • 运行时

定时查询节点信息(3s 一次),筛选可用节点并写入到内存中,提供 OpenAPI 给 SDK 调用,每个库均执行以下操作,最终会得到每个库的可用节点列表,最后把多个 list 求并集,得到最终的可用列表,写入到内存中。

查出所有列表数据后,对比内存中的 beat_version 与数据库中的 beat_version,如不相同则更新内存,如果相同说明对应节点心跳有丢失,如果丢失次数超过阈值,则剔除此节点。

节点列表中除了 ip、端口信息外,还有权重,启用状态属性, 这些属性都属于控制流变更,如果出现2边数据库不一致场景,以 config_version 最大的为准。

图片

1.2.3.20节点与K区网络断开

图片

1.2.3.20节点宕机

如果本次计算时有节点列表变化,会下发一个变更事件到 ARK(value 为时间戳-秒),SDK 在收到次配置变更后会立刻到 MetaCenter 拉取一次节点列表,以弥补定时轮训的延时。

  • 兜底配置

MetaCenter 提供的 OpenAPI 是通过计算后存入内存的数据,为了可以人工干预节点列表,需要支持开关一键切换至人工配置的节点列表数据。

图片

SDK( Rainbow) 

  • SDK 启动时会去通过7层 SLB 拉取节点列表并存储到内存,运行中每隔5s更新一次。

    如果拉取失败,启动时报错,运行中不做任何处理,等待下次拉取。

    如果拉取的可用节点列表为空,启动时报错,运行时兜底不做任何处理,等待下次拉取。

  • 拉取的可用节点列表与内存中做对比,如果有节点被移除,需要优雅关闭对应的存量连接(如果被移除节点超过1个,则不做驱逐)。

      当可用节点数量/所有节点数量 < X%时,忽略本次变更,不更新内存中的可用节点列表。

  • 拉取的节点数据会按照可用区进行分组,分为同可用区&跨可用区2个队列

    负载均衡时优先从同 AZ 节点队列中进行加权轮训。

      当同AZ节点权重总和/所有节点权重总和 < Y%时,同 AZ 节点优先策略失效,退化为所有节点加权轮训。

      当同AZ可用节点 < Z时,同 AZ 节点优先策略失效,退化为所有节点加权轮训 。

  • 需要新增查询节点列表的监控埋点&以上三种计算结果的埋点

图片

另外 SDK 支持一键动态切换至走老架构方式(4层 SLB)

管理后台

  • 新增页面【节点管理】,用于查询&管理节点

图片

  • 新增页面【兜底节点管理】,用于管理兜底节点列表。

图片

  • 提供节点上下线 API,给发布系统调用。

修改状态会去所有 metadata 数据库执行,只有一个库成功就返回成功,如所有库都修改失败,则返回失败。

update node_info set enabled = 0, config_version = #{config_version}where ip = ? and port = ?

容灾能力

表格中的是否有影响和故障恢复时间均指 SDK-Proxy 的访问链路,Proxy-DB 链路不在范围内。

图片

  • 可用区i全部宕机举例

参考以下时间线,可在30s左右完成恢复。

图片

  • i区 Metadata 数据库故障,无影响。

图片

一些思考

Q:为什么不用 sylas(得物注册中心产品)做注册中心,而是要自建元数据中心做服务发现?

彩虹桥和 sylas 均为 P0 级别服务,对稳定性要求极高,在架构设计之初需要充分考虑到互相依赖可能带来的级联故障,在与注册中心相关同学沟通后,决定自建彩虹桥元数据中心,实现自闭环。

Q:为什么不是传统的基于 Raft 协议的三节点来实现服务发现,而是用多套数据源做 merge?

Raft 是工程上使用较为广泛的强一致性、去中心化、高可用的共识算法,在分布式系统中,适用于高一致性、容错性要求高的场景。但 Raft 协议需要维护领导者选举和日志复制等机制,性能开销较大,其次 Raft 协议相对复杂,在开发、维护、排障等方面会非常困难,反之采用多数据源求并集的方式更简单,同时也具备单节点故障、整个可用区故障以及跨区网络中断等多种复杂故障下的容灾能力。

Q:如何在 SLB 切换到新架构的过程中保障稳定性?

可灰度:支持单个上游节点粒度的灰度

可回滚:支持一键动态切换至 SLB 架构

可观测:大量埋点数据可实时进行观测,有问题可快速回滚。

图片

图片

六、总结

自建元数据中心后,将给彩虹桥带来一系列收益:

  • 应用服务通过 SDK 直接连接 Proxy 节点,摆脱了对 SLB 的依赖,解决了带宽瓶颈和额外网络开销问题,并提高了流量灰度控制的精细度。

  • 简化了扩容流程,扩容时只需增加 Proxy 节点大大缩短整个扩容时间。

  • 多可用区容灾实现自动故障转移,无需人工干预。

  • SDK 具备了同 AZ 路由能力,更好适配双活架构。

往期回顾

1.得物精准测试平台设计与实现

2.解析Go切片:为何按值传递时会发生改变?|得物技术

3.基于IM场景下的Wasm初探:提升Web应用性能|得物技术

4.实时特征框架的生产实践|得物技术

5.商家下载中心设计演进之路|得物技术

关注得物技术,每周一、三更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

相关文章:

得物彩虹桥架构演进之路-负载均衡篇

文 / 新一 一、前言 一年一更的彩虹桥系列又来了&#xff0c;在前面两期我们分享了在稳定性和性能2个层面的一些演进&优化思路。近期我们针对彩虹桥 Proxy 负载均衡层面的架构做了一次升级&#xff0c;目前新架构已经部署完成&#xff0c;生产环境正在逐步升级中&#xf…...

Jmeter中的断言(四)

13--XPath断言 功能特点 数据验证&#xff1a;验证 XML 响应数据是否包含或不包含特定的字段或值。支持 XPath 表达式&#xff1a;使用 XPath 表达式定位和验证 XML 数据中的字段。灵活配置&#xff1a;可以设置多个断言条件&#xff0c;满足复杂的测试需求。 配置步骤 添加…...

vue2 src_Todolist编辑($nextTick)

main.js //引入Vue import Vue from "vue"; //引入App import App from ./App;//关闭Vue的生产提示 Vue.config.productionTip false;new Vue({el: #app,render: h > h(App),beforeCreate() {//事件总线Vue.prototype.$bus this;} });App.vue <template>…...

driver.js实现页面操作指引

概述 在访问某些网站的时候&#xff0c;第一次进去你会发现有个操作指引&#xff0c;本文引用driver.js&#xff0c;教你在你的页面也加入这般高大上的操作指引。 实现效果 实现 driver.js简介 driver.js是一个功能强大且高度可定制的基于原生JavaScript开发的新用户引导库…...

ffmpeg区域颜色覆盖

ffmpeg去除水印(遮盖指定区域)的几种办法_ffmpeg去水印-CSDN博客 ffmpeg -i a.mp4 -vf "drawboxx1560:y30:w310:h100:tfill" b.mp4 drawbox在视频帧上绘制一个矩形&#xff1a; x和y&#xff1a;矩形左上角的坐标。默认值是0。 w和h&#xff1a;矩形的宽度和高度。…...

【Python TensorFlow】进阶指南(续篇三)

在前几篇文章中&#xff0c;我们探讨了TensorFlow的高级功能&#xff0c;包括模型优化、分布式训练、模型解释等多个方面。本文将进一步深入探讨一些更具体和实用的主题&#xff0c;如模型持续优化的具体方法、异步训练的实际应用、在线学习的实现细节、模型服务化的最佳实践、…...

QT 实现仿制 网络调试器(未实现连接唯一性) QT5.12.3环境 C++实现

网络调试助手&#xff1a; 提前准备&#xff1a;在编写代码前&#xff0c;要在.pro工程文件中&#xff0c;添加network模块。 服务端&#xff1a; 代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QtWidgets> #inclu…...

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-31

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…...

面试题---深入源码理解MQ长轮询优化机制

引言 在分布式系统中&#xff0c;消息队列&#xff08;MQ&#xff09;作为一种重要的中间件&#xff0c;广泛应用于解耦、异步处理、流量削峰等场景。其中&#xff0c;延时消息和定时消息作为MQ的高级功能&#xff0c;能够进一步满足复杂的业务需求。为了实现这些功能&#xf…...

stable diffusion生成模型

1、stable diffusion Stable Diffusion 是一种扩散模型,基于对图像的逐步去噪过程训练和生成。它的核心包括以下几个步骤: 扩散过程(Diffusion Process)在训练时,向真实图像逐步添加噪声,最终将其变为纯随机噪声。这是一个正向过程,目的是学习如何将复杂的图像分解成随…...

分治法的魅力:高效解决复杂问题的利器

文章目录 分治法 (Divide and Conquer) 综合解析一、基本原理二、应用场景及详细分析1. 排序算法快速排序 (Quicksort)归并排序 (Mergesort) 2. 大整数运算大整数乘法 3. 几何问题最近点对问题 4. 字符串匹配KMP算法的优化版 三、优点四、局限性五、分治法与动态规划的对比六、…...

Spring IOC实战指南:从零到一的构建过程

Spring 优点&#xff1a; 方便解耦&#xff0c;简化开发。将所有对象创建和依赖关系维护交给 Spring 管理(IOC 的作用)AOP 切面编程的支持。方便的实现对程序进行权限的拦截、运行监控等功能(可扩展性)声明式事务的支持。只需通过配置就可以完成对事务的管理&#xff0c;无需手…...

3.langchain中的prompt模板 (few shot examples in chat models)

本教程将介绍如何使用LangChain库和智谱清言的 GLM-4-Plus 模型来理解和推理一个自定义的运算符&#xff08;例如使用鹦鹉表情符号&#x1f99c;&#xff09;。我们将通过一系列示例来训练模型&#xff0c;使其能够理解和推断该运算符的含义。 环境准备 首先&#xff0c;确保…...

量子感知机

神经网络类似于人类大脑&#xff0c;是模拟生物神经网络进行信息处理的一种数学模型。它能解决分类、回归等问题&#xff0c;是机器学习的重要组成部分。量子神经网络是将量子理论与神经网络相结合而产生的一种新型计算模式。1995年美国路易斯安那州立大学KAK教授首次提出了量子…...

VM虚拟机装MAC后无法联网,如何解决?

✨在vm虚拟机上&#xff0c;给虚拟机MacOS设置网络适配器。选择NAT模式用于共享主机的IP地址 ✨在MacOS设置中设置网络 以太网 使用DHCP ✨回到本地电脑上&#xff0c;打开 服务&#xff0c;找到VMware DHCP和VMware NAT&#xff0c;把这两个服务打开&#xff0c;专一般问题就…...

IDEA 基本设置

设置主题 设置字体 设置编码格式 改变字体大小 开启 按住 ctrl 滚轮 改变字体大小。 开启自动编译...

Chrome 浏览器 131 版本新特性

Chrome 浏览器 131 版本新特性 一、Chrome 浏览器 131 版本更新 1. 在 iOS 上使用 Google Lens 搜索 自 Chrome 126 版本以来&#xff0c;用户可以通过 Google Lens 搜索屏幕上看到的任何图片或文字。 要使用此功能&#xff0c;请访问网站&#xff0c;并点击聚焦时出现在地…...

使用php和Xunsearch提升音乐网站的歌曲搜索效果

文章精选推荐 1 JetBrains Ai assistant 编程工具让你的工作效率翻倍 2 Extra Icons&#xff1a;JetBrains IDE的图标增强神器 3 IDEA插件推荐-SequenceDiagram&#xff0c;自动生成时序图 4 BashSupport Pro 这个ides插件主要是用来干嘛的 &#xff1f; 5 IDEA必装的插件&…...

计算机毕设-基于springboot的高校网上缴费综合务系统视频的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…...

STL关联式容器之map

map的特性是&#xff0c;所有元素都会根据元素的键值自动被排序。map的所有元素都是pair&#xff0c;同时拥有实值(value)和键值(key)。pair的第一元素被视为键值&#xff0c;第二元素被视为实值。map不允许两个元素拥有相同的键值。下面是<stl_pair.h>中pair的定义 tem…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

前端调试HTTP状态码

1xx&#xff08;信息类状态码&#xff09; 这类状态码表示临时响应&#xff0c;需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分&#xff0c;客户端应继续发送剩余部分。 2xx&#xff08;成功类状态码&#xff09; 表示请求已成功被服务器接收、理解并处…...

2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版

1.题目描述 2.思路 当前的元素可以重复使用。 &#xff08;1&#xff09;确定回溯算法函数的参数和返回值&#xff08;一般是void类型&#xff09; &#xff08;2&#xff09;因为是用递归实现的&#xff0c;所以我们要确定终止条件 &#xff08;3&#xff09;单层搜索逻辑 二…...

表单设计器拖拽对象时添加属性

背景&#xff1a;因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...

基于 HTTP 的单向流式通信协议SSE详解

SSE&#xff08;Server-Sent Events&#xff09;详解 &#x1f9e0; 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09; 是 HTML5 标准中定义的一种通信机制&#xff0c;它允许服务器主动将事件推送给客户端&#xff08;浏览器&#xff09;。与传统的 H…...