问题引入

我们一个服务可能会进行多机部署,也就说多台服务器组成的集群共同对外提供一致的服务,那么我们的微服务的代码就需要拷贝多份,部署到不同的机器上。

我们使用 IDEA 来开启多个相同的服务
这里以 product-service 为例:

找到 services 按键,点开来:

在这里插入图片描述

找到我们需要多机部署的服务,右键然后点击 Copy Configuration ,复制这个服务的所有配置。

在这里插入图片描述

之后就是给我们新的服务命名,然后点击 Modify options 修改配置信息。

在这里插入图片描述

点击 Add VM options
在这里插入图片描述

在 VM options 添加端口信息:

-Dserver.port=端口号

注意由于我们是在本机部署多个服务,所以端口号需要修改,避免端口的冲突

在这里插入图片描述

最后点击 Apply ,然后 OK,就可以创建成功了。


然后我们启动所有的服务,在 Eureka 界面可以看到我们的 product-service 有多个注册信息

在这里插入图片描述

这里使用 order-service 来注册发现 product-service:

@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;public OrderInfo getOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectById(orderId);
//        String url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId();//从 eureka 中获取服务信息List<ServiceInstance> instances = discoveryClient.getInstances("product-service");String uri = instances.get(0).getUri().toString();String url = uri + "/product/" + orderInfo.getProductId();log.info("访问的资源路径:" + url);ProductDetailInfo productDetailInfo = restTemplate.getForObject(url, ProductDetailInfo.class);orderInfo.setProductDetailInfo(productDetailInfo);return orderInfo;}
}

但是我们发现多个请求,即使 product-service 有三个一样的服务,但是使用的都是 9092,如果我们的请求类一旦上升,就可能会导致 9092这个服务器崩溃,我们应该要做到均衡地将这些请求发送给 product-service 的三个不同的服务器中,这就是我们本章要提到的负载均衡

在这里插入图片描述

负载均衡

概念

负载均衡(Load Balance,简称LB),是高并发, 高可用系统必不可少的关键组件.
当服务流量增大时,通常会采用增加机器的方式进行扩容,负载均衡就是用来在多个机器或者其他资源中,按照一定的规则合理分配负载.

分类

负载均衡分为服务端负载均衡和客户端负载均衡

服务端负载均衡,主要使用的是负载均衡器 Nginx,请求先到达负载均衡器,然后通过负载均衡算法在多个服务器之间选择一个进行访问

在这里插入图片描述


客户端负载均衡:
将负载均衡的功能以库的方式集成到客户端中,而不是由一台负载均衡设备集中提供

在这里插入图片描述

模拟实现

这里我们使用原子类,避免发生线程不安全,通过原子类的数值和我们获取到的服务注册列表的长度进行取余获取下标,以轮询的方式来访问 product-service 服务端。

@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;private static final AtomicInteger count = new AtomicInteger(1);private List<ServiceInstance> instances;@PostConstructpublic void init() {instances = instances = discoveryClient.getInstances("product-service");}public OrderInfo getOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectById(orderId);
//        String url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId();int index = count.getAndIncrement() % instances.size();String uri = instances.get(index).getUri().toString();String url = uri + "/product/" + orderInfo.getProductId();log.info("访问的资源路径:" + url);ProductDetailInfo productDetailInfo = restTemplate.getForObject(url, ProductDetailInfo.class);orderInfo.setProductDetailInfo(productDetailInfo);return orderInfo;}
}

但是这个实现方式也有缺陷,就是如果后续有新的服务注册或者旧的服务崩溃的话,我们的 order-service 就不会获得到最新的注册列表,导致后续出现 bug

即使你采用下面的方式,每次 order-service 处理请求都要进行重新获取服务列表,也还是会出现 bug ,那就是如果旧的服务崩溃,可能无法即使获取,导致出现ConnectException

java.net.ConnectException: Connection refused: connect
@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;private static final AtomicInteger count = new AtomicInteger(1);//    private List<ServiceInstance> instances;
//
//    @PostConstruct
//    public void init() {
//        instances = instances = discoveryClient.getInstances("product-service");
//    }public OrderInfo getOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectById(orderId);
//        String url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId();List<ServiceInstance> instances = discoveryClient.getInstances("product-service");int index = count.getAndIncrement() % instances.size();String uri = instances.get(index).getUri().toString();String url = uri + "/product/" + orderInfo.getProductId();log.info("访问的资源路径:" + url);ProductDetailInfo productDetailInfo = restTemplate.getForObject(url, ProductDetailInfo.class);orderInfo.setProductDetailInfo(productDetailInfo);return orderInfo;}
}

LoadBalance

SpringCloud从2020.0.1版本开始,移除了Ribbon组件,使用Spring Cloud LoadBalancer组件来代替Ribbon实现客户端负载均衡

使用

添加注解 @LoadBalanced

在 RestTemplate 上添加 @LoadBalanced
将 RestTemplate 交给 LoadBalance 管理

@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}
}

修改远程调用的代码

修改 String url = “http://product-service/product/” + orderInfo.getProductId();
将 ip 和端口号修改为 服务名称【product-service】,这样 LoadBalance会自动为我们提供服务端

@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;public OrderInfo getOrderById(Integer orderId) {OrderInfo orderInfo = orderMapper.selectById(orderId);String url = "http://product-service/product/" + orderInfo.getProductId();log.info("访问的资源路径:" + url);ProductDetailInfo productDetailInfo = restTemplate.getForObject(url, ProductDetailInfo.class);orderInfo.setProductDetailInfo(productDetailInfo);return orderInfo;}
}

负载均衡策略

负载均衡策略是一种思想,无论是哪种负载均衡器,它们的负载均衡策略都是相似的 SpringCloud
LoadBalancer仅支持两种负载均衡策略:轮询策略和随机策略

1.轮询(RoundRobin):轮询策略是指服务器轮流处理用户的请求.这是一种实现最简单,也最常用的策略.生活中也有类似的场景,比如学校轮流值日,或者轮流打扫卫生.

2.随机选择(Random):随机选择策略是指随机选择一个后端服务器来处理新的请求

自定义负载均衡策略

SpringCloud LoadBalancer默认负载均衡策略是轮询策略,实现是RoundRobinLoadBalancer,如果服务的消费者如果想采用随机的负载均衡策略,也非常简单。

官方链接:SpringCloud LoadBalancer

public class CustomLoadBalancerConfiguration {@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name);}
}

CustomLoadBalancerConfiguration 这个类不用加类注解【@Configuration】
因为这个类是在组件的扫描范围内

@LoadBalancerClient(name = "product-service", configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}
}

我们在 RestTemplate 上添加 @LoadBalancerClient 注解,将服务名称和负载策略填写进去

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916999.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916999.shtml
英文地址,请注明出处:http://en.pswp.cn/news/916999.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

13. 若依框架中的 Sensitive 敏感字段过滤

若依框架中有Sensitive注解&#xff0c;但代码中并未使用&#xff0c;但该注解的实现还是比较值的学习的。该注解是一个运行时注解该注解只能应用在字段上JacksonAnnotationsInside 表示当使用Jackson序列化时&#xff0c;Jackson会自动识别该注解下的其他Jackson相关注解&…

git本地仓库,工作区和暂存区的知识

一 git工作原理 Git 的工作原理基于分布式版本控制&#xff0c;通过管理文件的不同版本状态&#xff0c;实现代码的追踪、协作和回溯。除了常见的工作区&#xff08;Working Directory&#xff09; 和暂存区&#xff08;Staging Area/Index&#xff09;&#xff0c;核心还包括本…

MPU6050模块

一&#xff1a;MPU6050简介输出一个随姿态变化而变化的电压&#xff0c;想要量化电压&#xff0c;就得使用ADC转化欧拉角偏航角&#xff08;Yaw&#xff09;&#xff1a;也叫航向角&#xff0c;通常是绕 z 轴旋转的角度&#xff0c;以 x 轴正向为起始边&#xff0c;旋转后 x 轴…

jvm的栈和堆

在 JVM 中&#xff0c;栈&#xff08;Stack&#xff09;和堆&#xff08;Heap&#xff09;是两种核心内存区域&#xff0c;用于存储不同类型的数据&#xff0c;它们的设计和存储规则有明确区分&#xff0c;主要体现在存储内容、生命周期和管理方式上&#xff1a;一、栈&#xf…

自动驾驶车辆的敏捷安全档案

简介近年来&#xff0c;在开发安全关键软件时&#xff0c;敏捷开发方法的使用日益增多。敏捷方法非常适合自动驾驶汽车软件的增量改进、运行设计域的逐步扩展以及新型智能路侧单元的开发。由于车辆和智能路侧单元的预期改进&#xff0c;未来几年将会有新的自动驾驶车辆试验。因…

【时时三省】(C语言基础)动态内存分配与它的指针变量

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省什么是内存的动态分配全局变量是分配在内存中的静态存储区的&#xff0c;非静态的局部变量&#xff08;包括形参&#xff09;是分配在内存中的动态存储区的&#xff0c;这个存储区是一个称为栈…

SpringMVC的核心架构与请求处理流程

Spring MVC 核心架构核心组件组件作用类比DispatcherServlet前端控制器&#xff0c;统一接收请求并协调各组件处理一个餐厅的前台HandlerMapping根据请求URL映射到对应的处理器&#xff08;Controller&#xff09;路由表HandlerAdapter执行处理器方法&#xff0c;处理参数绑定、…

css 不错的按钮动画

效果图wxml <view class"{{status?active:}}"><view class"up-top btn"><text>向上</text></view><view class"up-left btn"><text>向左</text></view><view class"up-center b…

若依框架RuoYi-Vue-Plus-5.X的启动,本地安装docker,再部署 Redis、PG数据库(智慧水务)SmartWaterServer

一、部署redis数据库拉取镜像 docker pull redis启动Redis容器docker run -d --name redis-server -p 6379:6379 -v redis-data:/data redis redis-server --requirepass 123redis版本二、部署PostgreSQL 数据库拉取镜像docker pull postgres:15 创建数据存储目录、建议将数据挂…

Idea 清除无用的引用类

在IntelliJ IDEA中&#xff0c;你可以通过以下方式将选中的代码设置为大写&#xff1a;1. 使用快捷键(推荐)Windows/Linux&#xff1a;Ctrl Shift UMac&#xff1a;Cmd Shift U操作步骤&#xff1a;选中文本按下快捷键&#xff0c;即可在大小写之间切换。2. 通过菜单操作选…

同个主机拉取不同权限仓库的方法

背景&#xff1a;因为某些神奇的原因&#xff0c;无法同时授权仓库权限给自己。 1.本地电脑只有权限访问web仓库地址&#xff0c;无权限访问backend仓库&#xff1b; 2.堡垒机服务器只有权限访问backend仓库&#xff0c;无权限访问web仓库地址。 web仓库地址 &#xff1a;codeu…

快速搭建Node.js服务指南

Node.js是构建高效、可扩展网络应用的理想选择。以下是几种快速搭建Node.js服务的方法。 方法一&#xff1a;使用Express&#xff08;最流行框架&#xff09; 1. 初始化项目 mkdir my-node-service cd my-node-service npm init -y2. 安装Express npm install express3. 基础服…

通义千问Qwen3-30B-A3B-Thinking-2507技术解析:推理模型的工程实践突破

Qwen3-30B-A3B模型架构图2025年7月30日&#xff0c;阿里云通义千问团队发布了Qwen3-30B-A3B-Thinking-2507推理模型&#xff0c;这是继Qwen3-30B-A3B-Instruct-2507后的又一力作。作为专注于推理任务的专用模型&#xff0c;它在数学能力测试AIME25上取得85.0分&#xff0c;超越…

【源力觉醒 创作者计划】文心一言与deepseek集成springboot开发哪个更方便

一.实验背景 当前文心一言和deepseek都开源了&#xff0c;二者都可以作为大模型应用开发的模型基础了&#xff0c;我们都可以编写springboot项目来集成deepseek和文心一言了 二.实验目标 本文基于实际操作&#xff0c;通过实际操作来对比文心一言和deepseek在集成到springbo…

核磁共振数据T2几何均值计算

1、T₂ 几何均值公式如下&#xff1a;2、核磁T2几何均值计算代码 CSV 文件文件格式&#xff1a; 每一行是一个样点&#xff08;样品深度&#xff09;&#xff0c;列为&#xff1a;第一列是“深度”或其他&#xff1b;第二列及以后&#xff08;如 TASPEC0 ~ TASPEC199&#xff0…

微服务架构技巧篇——接口类设计技巧

目录 一、微服务架构的特点 二、微服务接口类设计技巧 2.1、BFF(Backend For Frontend) 2.1.1、 服务分布式带来的第一个挑战导致的几个典型问题 2.1.2、什么是 BFF 2.1.3、BFF 应用场景 2.1.4、BFF 落地经验 2.1.4.1、前端负责 BFF 开发优缺点 2.1.4.2、后端负责 BFF 开发优…

C++游戏开发(2)

直接上代码 1.首先是头文件编写 #include <iostream> #include <graphics.h> #include <string> 2,添加画布 长1280&#xff0c;宽720 initgraph(1280, 720); 3.添加主循环 bool running true; while(runing) { } 4.定义结构体变量msg ExMessge msg; 5.开…

Unity开发2D类银河恶魔城游戏学习笔记目录

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 玩家状态机 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现…

智慧社区项目开发(三)——基于 Spring Boot 实现动态路由加载:从数据库到前端菜单的完整方案

在后台管理系统中&#xff0c;不同用户角色往往拥有不同的操作权限&#xff0c;对应的菜单展示也需动态调整。动态路由加载正是解决这一问题的核心方案 —— 根据登录用户的权限&#xff0c;从数据库查询其可访问的菜单&#xff0c;封装成前端所需的路由结构并返回。本文将详细…

Python在自动化与运维领域的核心角色:工具化、平台化与智能化

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在 IT 系统日益复杂、运维任务持续增长的今天&#xff0c;自动化已成为企业基础设施管理的关键方向。Python 以其简洁的语法、强大…