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

Ribbon客户端负载均衡策略测试及其改进

文章目录

  • 一、目的概述
  • 二、验证步骤
    • 1、源码下载
    • 2、导入IDE
    • 3、运行前修改配置
    • 4、策略说明
    • 5、修改策略
  • 三、最终结论
  • 四、改进措施
    • 1. 思路分析
    • 2. 核心代码
    • 3. 测试页面

一、目的概述

为了验证Ribbon客户端负载均衡策略在负载节点失效的情况下,是否具有故障转移的功能,进行了以下代码验证!

二、验证步骤

1、源码下载

git clone https://gitee.com/00fly/microservice-all-in-one.git

https://gitee.com/00fly/microservice-all-in-one/tree/master/ribbon-demo-simple

2、导入IDE

在这里插入图片描述

3、运行前修改配置

根据调用关系,我们需要启动2个user服务,为了方便调试我们这边分别启动8081、8082端口的user服务,并在movie模块中,设置负载节点地址为:127.0.0.1:8081,127.0.0.1:8082

微服务movie
微服务user
微服务user

eclipse为例简要说明
查看环境配置
在这里插入图片描述
打开Dashboard,选择Duplicate config
在这里插入图片描述
选择open Config
在这里插入图片描述
选择Profile设置为dev

在这里插入图片描述
全部启动
在这里插入图片描述
docker部署相对简单,编排文件为
https://gitee.com/00fly/microservice-all-in-one/blob/master/ribbon-demo-simple/docker/docker-compose.yml

version: '3.8'
services:#负载均衡节点ribbon-user-simple-0:image: registry.cn-shanghai.aliyuncs.com/00fly/ribbon-user-simple:0.0.1container_name: ribbon-user-simple-0deploy:resources:limits:cpus: '1'memory: 200Mreservations:memory: 180Mrestart: on-failurelogging:driver: json-fileoptions:max-size: 5mmax-file: '1'#负载均衡节点ribbon-user-simple-1:image: registry.cn-shanghai.aliyuncs.com/00fly/ribbon-user-simple:0.0.1container_name: ribbon-user-simple-1deploy:resources:limits:cpus: '1'memory: 200Mreservations:memory: 180Mrestart: on-failurelogging:driver: json-fileoptions:max-size: 5mmax-file: '1'#调用方ribbon-movie-simple:image: registry.cn-shanghai.aliyuncs.com/00fly/ribbon-movie-simple:0.0.1container_name: ribbon-movie-simpledeploy:resources:limits:cpus: '1'memory: 200Mreservations:memory: 180Mports:- 8090:8082environment:USER_SERVERS: ribbon-user-simple-0:8081,ribbon-user-simple-1:8081restart: on-failurelogging:driver: json-fileoptions:max-size: 5mmax-file: '1'

4、策略说明

  • RandomRule 实现从服务实例清单中随机选择一个服务实例的功能。
  • RoundRobinRule 实现了按照线性轮询的方式依次选择每个服务实例的功能。
  • RetryRule 实现了一个具备重试机制的实例选择功能。
  • WeightedResponseTimeRule是对 RoundRobinRule 的拓展,增加了根据实例的运行情况来计算权重,并根据权重来挑选实例。
  • ClientConfigEnableRoundRobinRule 通过继承该策略,在子类中做一些高级策略时有可能会存在一些无法实施的情况,那么就可以用父类的实现作为备选(线性轮询机制)。
  • BestAvailableRule 通过遍历负载均衡器中维护的所有服务实例,会过滤掉故障的实例,并找出并发请求数最小的一个,所以该策略的特性是可选出最空闲的实例。
  • PredicateBasedRule 先通过子类实现中的 Predicate 逻辑来过滤一部分服务实例,然后再以线性轮询的方式从过滤后的实例清单中选出一个。
  • AvailabilityFilteringRule 通过线性抽样的方式直接尝试寻找可用且较空闲的实例来使用。
  • ZoneAvoidanceRule 根据负载情况选择可用区

5、修改策略

修改这边的负载均衡策略在这里插入图片描述
打开页面
在这里插入图片描述
停止8081或8082端口服务,重新调试,返回结果如下:
在这里插入图片描述

三、最终结论

RandomRule、RoundRobinRule 策略不具备故障转移能力
RetryRule、WeightedResponseTimeRule等虽然具有故障转移,但是故障转移的时间太长,并且故障恢复后,重新选中该恢复的节点所需时间也较长。

各种策略的表现。大家可以自行研究测试。

四、改进措施

1. 思路分析

  • 采用多线程,多个节点同时检测,返回最快响应的节点
  • 采用多线程,定义超时时间,返回超时时间之内有响应的节点, 后续根据规则选择1个节点

2. 核心代码

NodeController.java


import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;import com.itmuch.cloud.study.user.entity.User;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;@Slf4j
@Api(tags = "负载均衡节点")
@RestController
@RequestMapping("/node")
public class NodeController
{@Autowiredprivate WebClient webClient;@Value("${microservice-ribbon-user.ribbon.listOfServers}")private List<String> listOfServers;private ExecutorService executorService = Executors.newFixedThreadPool(10);@ApiOperation("查询用户")@GetMapping("/user/{id}")public List<User> findById(@PathVariable Long id)throws InterruptedException{// WebClient支持异步List<User> users = new CopyOnWriteArrayList<User>();listOfServers.stream().forEach(hostWithPort -> webClient.get().uri(String.format("http://%s/%s", hostWithPort, id))// URI.acceptCharset(StandardCharsets.UTF_8).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class).subscribe(resp -> users.add(resp)));int index = 0;while (users.isEmpty() && (index++) < 100){TimeUnit.MILLISECONDS.sleep(10);log.info("index:{}, waitting......", index);}if (users.isEmpty()){throw new RuntimeException("查询超时,无返回值");}return users;}@ApiOperation("查询用户 by execute")@GetMapping("/v0/user/{id}")public List<User> findByExecute(@PathVariable Long id)throws InterruptedException{// List<User> users = new ArrayList<User>();// TODO ArrayList users一定概率有null值// 原因:通过new ArrayList<>()初始化的大小是0,首次插入触发扩容,并发可能导致出现null值List<User> users = new CopyOnWriteArrayList<User>();listOfServers.stream().forEach(hostWithPort -> executorService.execute(() -> webClient.get().uri(String.format("http://%s/%s", hostWithPort, id))// URI.acceptCharset(StandardCharsets.UTF_8).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class).subscribe(resp -> users.add(resp))));int index = 0;while (users.isEmpty() && (index++) < 100){TimeUnit.MILLISECONDS.sleep(10);log.info("index:{}, waitting......", index);}if (users.isEmpty()){throw new RuntimeException("查询超时,无返回值");}return users;}@ApiOperation("查询用户 by submit")@GetMapping("/v1/user/{id}")public List<User> findBySubmit(@PathVariable Long id)throws InterruptedException{List<User> users = new CopyOnWriteArrayList<User>();listOfServers.stream().forEach(hostWithPort -> executorService.submit(() -> webClient.get().uri(String.format("http://%s/%s", hostWithPort, id))// URI.acceptCharset(StandardCharsets.UTF_8).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class).subscribe(resp -> users.add(resp)), users));int index = 0;while (users.isEmpty() && (index++) < 100){TimeUnit.MILLISECONDS.sleep(10);log.info("index:{}, waitting......", index);}if (users.isEmpty()){throw new RuntimeException("查询超时,无返回值");}return users;}@ApiOperation("查询用户 by invokeAny")@GetMapping("/v2/user/{id}")public User findByInvokeAny(@PathVariable Long id)throws InterruptedException, ExecutionException, TimeoutException{return executorService.invokeAny(listOfServers.stream().map(hostWithPort -> new Callable<User>(){@Overridepublic User call(){Mono<User> mono = webClient.get().uri(String.format("http://%s/%s", hostWithPort, id))// URI.acceptCharset(StandardCharsets.UTF_8).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class);return mono.block();}}).collect(Collectors.toList()), 1000, TimeUnit.MILLISECONDS);}@ApiOperation("查询用户 by invokeAll")@GetMapping("/v3/user/{id}")public List<User> findByInvokeAll(@PathVariable Long id)throws InterruptedException{List<Future<User>> futures = executorService.invokeAll(listOfServers.stream().map(hostWithPort -> new Callable<User>(){@Overridepublic User call(){Mono<User> mono = webClient.get().uri(String.format("http://%s/%s", hostWithPort, id))// URI.acceptCharset(StandardCharsets.UTF_8).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class);return mono.block();}}).collect(Collectors.toList()), 1000, TimeUnit.MILLISECONDS);List<User> users = new ArrayList<User>();for (Future<User> future : futures){try{users.add(future.get());}catch (Exception e){log.error(e.getMessage(), e);}}return users;}
}

3. 测试页面

在这里插入图片描述


有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

相关文章:

Ribbon客户端负载均衡策略测试及其改进

文章目录 一、目的概述二、验证步骤1、源码下载2、导入IDE3、运行前修改配置4、策略说明5、修改策略 三、最终结论四、改进措施1. 思路分析2. 核心代码3. 测试页面 一、目的概述 为了验证Ribbon客户端负载均衡策略在负载节点失效的情况下&#xff0c;是否具有故障转移的功能&a…...

linux网络编程5——Posix API和网络协议栈,使用TCP实现P2P通信

文章目录 Posix API和网络协议栈&#xff0c;使用TCP实现P2P通信1. socket()2. bind()3. listen()4. connect()5. accept()6. read()/write(), recv()/send()7. 内核tcp数据传输7.1 TCP流量控制7.2 TCP拥塞控制——慢启动/拥塞避免/快速恢复/快速重传 8. shutdown()9. close()9…...

低代码平台中的功能驱动开发:模块化与领域设计

在现代软件开发中&#xff0c;尤其是在低代码平台的背景下&#xff0c;清晰地定义功能和模块是成功的关键。功能驱动开发强调功能的优先性&#xff0c;模块化设计则确保系统的可维护性和可扩展性。本文将探讨如何在低代码平台中有效地将功能与模块结合起来&#xff0c;形成一个…...

HTTP和HTTPS基本概念,主要区别,应用场景

HTTP和 HTTPS是用于在网络中传输数据的协议&#xff0c;虽然它们的功能类似&#xff0c;但在安全性上存在显著差异。 1. HTTP 的基本概念 定义&#xff1a;HTTP 是一种无状态的、面向请求-响应的协议&#xff0c;用于客户端&#xff08;如浏览器&#xff09;和服务器之间传输…...

node.js使用Sequelize ORM操作数据库

一、什么是ORM ORM是在数据库和编程语言之间建立一种映射关系&#xff0c;这样可以让我们有非常简单的代码&#xff0c;来实现各种数据库的操作。 例如&#xff1a;使用mysql去查找表&#xff08;表名称为Articles&#xff09; SELECT * FROM Articles;但是我们使用ORM的话&…...

STM32-Modbus协议(一文通)

Modbus协议原理 RT-Thread官网开源modbus RT-Thread官方提供 FreeModbus开源。 野火有移植的例程。 QT经常用 libModbus库。 Modbus是什么&#xff1f; Modbus协议&#xff0c;从字面理解它包括Mod和Bus两部分&#xff0c;首先它是一种bus&#xff0c;即总线协议&#xff0c;和…...

100. 不同方向的投影视图

本节课给大家讲解&#xff0c;通过UI按钮界面交互改变threejs相机的观察视角。 x轴方向观察 // 通过UI按钮改变相机观察角度 document.getElementById(x).addEventListener(click, function () {camera.position.set(500, 0, 0); //x轴方向观察camera.lookAt(0, 0, 0); //重新…...

Appium中的api(三)

目录 Appium中的api(三) 1.输入和清空内容 1--输入内容 2--清空内容 2.获取文本内容 3.获取文本位置 4.获取文本的大小&#xff08;即获取控件的宽和高&#xff09; 5.滑动api 6.拖拽api 7.如何获取手机分辨率 8.如何截图 9.模拟按键事件api 10.操作通知栏 案例:App自动化模拟 …...

踩坑:关于使用ceph pg repair引发的业务阻塞

概述 在某次故障回溯中&#xff0c;发现引发集群故障&#xff0c;slow io&#xff0c;pg stuck的罪魁祸首竟是做了一次ceph pg repair $pgid。然而ceph pg repair作为使用频率极高的&#xff0c;用来修复pg不一致的常用手段&#xff0c;平时可能很少注意其使用规范和可能带来的…...

瞬间升级!电子文档华丽变身在线题库,效率翻倍✨

&#x1f44b;嘿小伙伴们&#xff0c;有个超赞的秘籍要告诉你们——土著刷题能将你的电子文档一键变身在线题库&#xff01;&#x1f609; 你还没发现这个宝藏功能吗&#xff1f;快来瞧瞧&#xff01; &#x1f31f;是不是常被一堆电子版的学习资料搞得头昏脑涨&#xff0c;学习…...

如何动态改变本地的ip

在当今数字化时代&#xff0c;网络连接已成为我们日常生活和工作中不可或缺的一部分。无论是出于隐私保护、突破地域限制&#xff0c;还是为了测试和优化网络应用&#xff0c;动态改变本地IP地址的需求日益增多。本文将详细介绍如何安全、有效地实现这一目标&#xff0c;旨在帮…...

Spring Boot框架在中小企业设备管理中的创新应用

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…...

Ceph入门到精通-Osd db扩容

ceph-bluestore-tool 是一个在 BlueStore 实例上执行低级管理操作的实用程序。 以下命令可用于 ceph-bluestore-tool 语法 ceph-bluestore-tool COMMAND [ --dev DEVICE … ] [ -i OSD_ID ] [ --path OSD_PATH ] [ --out-dir DIR ] [ --log-file | -l filename ] [ --deep ]c…...

windows msvc2017 x64编译AWS SDK CPP库

在本文中&#xff0c;我们将介绍如何编译AWS SDK C库&#xff0c;以便在您的项目中使用。AWS SDK C库提供了与Amazon Web Services交互的接口&#xff0c;允许您在C应用程序中使用AWS服务。 一、准备工作 在开始编译AWS SDK C库之前&#xff0c;请确保您的系统已经安装了以下…...

铜业机器人剥片 - SNK施努卡

SNK施努卡有色行业电解车间铜业机器人剥片 铜业机器人剥片技术是针对传统人工剥片效率低下、工作环境恶劣及生产质量不稳定的痛点而发展起来的自动化解决方案。 面临人工剥片的诸多挑战&#xff0c;包括低效率、工作环境差、人员流动大以及产品质量控制不精确等问题。 人工剥片…...

非接触式竖向位移、水平位移视频实时在线监测的设备分类及选型

前言 视觉是人工智能正在快速发展的一个分支&#xff0c;简单说来&#xff0c;机器视觉就是用机器代替人眼来做测量和判断。在结构健康自动化监测方面&#xff0c;机器视觉采用光学图像结合智能算法和物联网技术&#xff0c;利用先进的智能靶标识别及亚像素处理等技术&#xff…...

Svelte 5 正式发布:新一代前端框架!

10 月 22 日&#xff0c;Svelte 5 正式发布&#xff01;该版本带来的更新主要包括&#xff1a; 重写框架&#xff1a;Svelte 5 是从头开始重写的&#xff0c;使得应用更快、更小、更可靠&#xff0c;并且代码更一致和符合习惯。 向后兼容&#xff1a;Svelte 5 几乎完全向后兼容…...

85.【C语言】数据结构之顺序表的中间插入和删除及遍历查找

目录 3.操作顺序表 1.分析中间插入函数 函数的参数 代码示例 图片分析 main.c部分改为 在SeqList.h添加SLInsert函数的声明 运行结果 2.分析中间删除函数 函数的参数 代码示例 图片分析 main.c部分改为 在SeqList.h添加SLErase函数的声明 运行结果 承接84.【C语…...

触觉智能Purple Pi OH鸿蒙开发板成功适配OpenHarmony5.0 Release,开启新征程!

10月22日&#xff0c;触觉智能Purple Pi OH鸿蒙开发板迎来了重大系统版本升级&#xff0c;成功适配OpenHarmony5.0 Release&#xff0c;为嵌入式开发者和科技爱好者们带来了全新的机遇与挑战&#xff01; 触觉智能 Purple Pi OH 开发板一直以来都以其高品质和超高性价比而著称。…...

分布式解决方案---分布式ID

目录 是什么 特点 全局唯一 高并发 高可用 怎么做 实现方案 是什么 分布式ID是指在分布式系统中生成的唯一标识符。由于分布式系统的特点&#xff0c;多个节点可能会同时生成ID&#xff0c;因此需要确保每个ID在整个系统中是唯一的。 重点就是唯一性&#xff01;&#x…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试

作者&#xff1a;Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位&#xff1a;中南大学地球科学与信息物理学院论文标题&#xff1a;BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接&#xff1a;https://arxiv.…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

ArcGIS Pro+ArcGIS给你的地图加上北回归线!

今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等&#xff0c;设置经线、纬线都以10间隔显示。 2、需要插入背会归线&#xf…...

麒麟系统使用-进行.NET开发

文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的&#xff0c;如果需要进行.NET开发&#xff0c;则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET&#xff0c;所以要进…...

LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考

目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候&#xff0c;显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …...