SpringCloud系列(六)| 聊聊负载均衡

news2024/9/28 11:20:57

一、负载均衡概述

上一篇文章中,我们在集成OpenFeign的过程中提示我们需要加入了一个依赖就是: spring-cloud-starter-loadbalancer。 顾名思义,这个包的作用就是用来做负载均衡的。

简单解释一下什么是负载均衡,就是当我们的服务有多个实例的时候,比如我们userservice, 一个端口号是8081,一个端口号是8082。当然这是因为我只有一天电脑只能一台机器上模拟。正常情况我们的两个用户服务肯定应该是部署在两台机器上,这样就可以防止其中一台机器出现故障而导致的服务不可用的问题,这叫做分布式部署。而部署了两个相同的服务,当我们有大量的请求过来的时候,就可以把请求平均分布到两台机器上分别处理,降低每个服务的负载,使他们的压力得到均衡。这就是服务均衡。

那我们实际来验证一下,我们加入了这个包是否实现了负载均衡的功能。怎么验证的,就是同时启动两个用户服务。然后调用的时候,看请求是否能够均衡的打到两个服务上。

二、负载均衡验证

我们先来改造一下我们的用户接口,由于两个服务的端口号是不一样的,我们就在程序当中打印一下端口号。

package com.lsqingfeng.springcloud.user.controller;

import com.lsqingfeng.springcloud.common.base.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @className: UserController
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-29 17:25
 */
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Value("${server.port}")
    private String port;

    @GetMapping("hello")
    public Result hello(String name){
        log.info("被请求到的服务端口号为: " + port);
        return Result.success(name);
    }

}

然后按照上篇文章的方式,启动两个用户服务。

另外一个:

然后自启动订单服务,订单服务的接口中已经通过openFeign成功调用了userservice中的接口。我们观察日志,看看调用的是哪个服务。

第一次调用:

服务一打印了日志:

再次调用:

服务二打印了日志。这就验证了请求是在两个机器上分别出现了。说明我们的负载均衡已经实现了。

而且Spring-Cloud-Loadbalancer默认的负载均衡策略就是轮训策略。也就是一人一下,轮着来。而负载均衡也有其他的策略。

三、spring-cloud-starter-loadbalancer

Spring Cloud LoadBalancer是一个客户端负载均衡器,类似于Ribbon,但是由于Ribbon已经进入维护模式,并且Ribbon 2并不与Ribbon 1相互兼容,所以Spring Cloud全家桶在Spring Cloud Commons项目中,添加了Spring cloud Loadbalancer作为新的负载均衡器,并且做了向前兼容。由于我们使用的SpringCloud版本比较新,引入的nacos依赖中已经不包含ribbon的相关依赖了。如果你使用的是相对比较老的版本,在使用Spring-cloud-loadbalancer的时候,需要将 ribbon的相关依赖排除掉,同时在配置文件中禁用ribbon。

关于spring-cloud-loadbalancer的具体内容,可以参看一下官方文档:

地址: Cloud Native Applications

通过文档中的描述,

Spring Cloud 中内部微服务调用默认是 http 请求,主要通过下面三种 API:

  • RestTemplate:同步 http API
  • WebClient:异步响应式 http API
  • 三方客户端封装,例如 openfeign

如果项目中加入了 spring-cloud-loadbalancer 的依赖并且配置启用了,那么会自动在相关的 Bean 中加入负载均衡器的特性。

  • 对于 RestTemplate,会自动对所有 @LoadBalanced 注解修饰的 RestTemplate Bean 增加 Interceptor 从而加上了负载均衡器的特性。
  • 对于 WebClient,会自动创建 ReactorLoadBalancerExchangeFilterFunction,我们可以通过加入ReactorLoadBalancerExchangeFilterFunction会加入负载均衡器的特性。
  • 对于三方客户端,一般不需要我们额外配置什么。

所以由于我们使用的是openFein,如果想要自己定义一套负载均衡的算法策略,我找了很多的资料都没有相关的介绍,应该是目前来讲,可能还不支持针对openFeign的定制化负载均衡策略。如果大家有相关资料也可以分享给我。目前来讲,这种轮训机制的策略也可以满足一般的负载均衡需求。

当然如果确实有自定义负载均衡策略的需要,那么我们也可以把openFeign的调用改为RestTemplate或者 WebClient。这样就可以实现了。

代码已经上传至gitCode:一缕82年的清风 / spring-cloud-learning · GitCode, 有需要的朋友可以下载下来查看。

四、负载均衡实现

上面的内容写于2022年,现在是2023年,我又重新开始写这个专题的时候,又重新研究了一下这个问题。发现OpenFeign和 loadbalancer集成的时候,可以可以来配置负载均衡策略的。 只不过负载均衡的策略目前只有两种,一种是随机、一种是轮询。这里来讲解一下具体的配置过程。

首先要注意,我们要在调用方进行配置!在调用方进行配置!在调用方进行配置!在调用方进行配置!

那我们进入调用方的工程,先添加一个负载均衡的配置类。 创建一个conf包,添加一个类如下:

package com.lsqingfeng.springcloud.conf;

import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/**
* @className: LoadBalancedConfig
* @description: 
* @author liushuai
* @date 2023/3/8 3:45 PM
*/
@Configuration
public class LoadBalancedConfig {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        // 随机方式,轮询方式: RoundRobinLoadBalancer
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

这里最后返回的RandomLoadBalancer 就是代表的随机轮询策略机制。

然后在feignClient上添加一个注解。

@LoadBalancerClient(name="userservice", configuration = LoadBalancedConfig.class)

这里的configuration就指向我们刚刚写的那个配置类。完整代码如下:

package com.lsqingfeng.springcloud.order.client;

import com.lsqingfeng.springcloud.common.base.Result;
import com.lsqingfeng.springcloud.conf.LoadBalancedConfig;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @interface: UserFeignClient
 * @description:
 * @author: sh.Liu
 * @date: 2022-03-29 19:10
 */
@Component
@FeignClient(name="userservice")
@LoadBalancerClient(name="userservice", configuration = LoadBalancedConfig.class)
public interface UserFeignClient {
    /**
     * userController中的hello
     * @param name
     * @return
     */
    @GetMapping("/user/hello")
    Result hello(@RequestParam("name") String name);
}

接下来就可以了。我们启动三个userService实例。 一个OrderService实例。 通过调用接口,查看被调用的服务情况。(关于idea启动过个服务报错,前面讲过)

我们调用了三次order/getOrder接口。查看UserService服务中的的日志

发现8084被调用了两次,8082被调用了一次。 看样子应该是随机的。

接下来换成轮询的试试。修改OrderService中的配置类。改为:RoundRobinLoadBalancer

@Configuration
public class LoadBalancedConfig {
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        // 随机方式,轮询方式: RoundRobinLoadBalancer
        return new RoundRobinLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }
}

重新启动OrderService.

再来调用三次服务:

发现每个服务都被调用了一次,验证了我们的猜测。说明我们还是可以对负载均衡的策略进行配置的。

如果觉得这两种方式满足不了,那么我们就只能自己去写实现了。可以参考RoundRobinLoadBalancer的方式尝试着去做下。其实如果没有啥特殊需求,这两种策略其实也足够使用了。

好了,关于这一部分的内容,我们就先到这里吧。代码已经上传到了gitCode。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python面经【11】- Python可迭代对象一网打尽专题

Python面经【11】- Python可迭代对象一网打尽专题 可迭代对象Python的迭代器、生成器1) 迭代器2) 生成器 可迭代对象、迭代器的区别12. 生成器、迭代器的区别什么是装饰器&#xff1f;函数装饰器有什么作用一句话解释什么样的语言能够使用装饰器Python中的作用域&#xff1f;什…

节流防抖:提升前端性能的秘密武器(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

我常用的几个经典Python模块

Python常用的模块非常多&#xff0c;主要分为内置模块和第三方模块两大类&#xff0c;且不同模块应用场景不同又可以分为文本类、数据结构类、数学运算类、文件系统类、爬虫类、网络通讯类等多个类型。 大家常用的内置模块比如&#xff1a;math、re、datetime、urllib、os、ra…

自动化测试流程详解

最近很多小伙伴问我自动化测试到底该怎么做&#xff1f;流程是什么样的&#xff1f;在每个阶段都需要注意什么&#xff1f;本文也就主要从自动化测试的基本流程入手&#xff0c;对面试自动化测试工程师的同学会有不少帮助。对于在职的朋友&#xff0c;也可以参考此流程&#xf…

AI扩图哪家强?我们实地测试了5款扩图工具

AI扩图的命运齿轮开始转动了。 近日&#xff0c;“AI扩图”在各个社交平台上频频出圈&#xff0c;#AI扩图#话题&#xff0c;在抖音平台累计播放数超7.8亿次。 何为AI扩图&#xff1f; AI 扩图功能给我们带来了一个观察世界的新角度。在 AI 的加持下&#xff0c;我们可以看到…

门窗企业网站建设作用是什么

门窗作为市场重要的组合部分&#xff0c;其应用广泛使得众多商家入局经营&#xff0c;无论大型建筑还是家庭应用&#xff0c;都有较高需求度&#xff0c;尤其对品牌商来说&#xff0c;无论直售还是加盟都可以获得不菲效益。 但对门窗企业来说&#xff0c;也需要解决几个痛点&a…

【计算思维】第14届蓝桥杯省赛计算思维U8组真题试卷

选择题 第 1 题 单选题 要把下面 4 张图片重新排列成蜗牛的画像&#xff0c;该如何排列这些图片?( ) A. B. C. D. 第 2 题 单选题 下图的几张牌&#xff0c;每次可以交换任意 2 张。 如将它们按照下面的顺序排列&#xff0c;最少需要交换( )次。 A.4 B.5 C.6 D.7 …

YOLOv8改进 | 2023Neck篇 | BiFPN双向特征金字塔网络(附yaml文件+代码)

一、本文介绍 本文给大家带来的改进机制是BiFPN双向特征金字塔网络&#xff0c;其是一种特征融合层的结构&#xff0c;也就是我们本文改进YOLOv8模型中的Neck部分&#xff0c;它的主要思想是通过多层级的特征金字塔和双向信息传递来提高精度。本文给大家带来的结构可以让大家自…

2023年贺岁电影:一眼多,二眼好多

如果从11月末开始统计&#xff0c;今年贺岁档共有72部贺岁片&#xff0c;平均一天就有2部电影上映&#xff0c;看完总计需要花费7400分钟。 这个数量几乎快赶上2021年到2022年贺岁片的总和。 今年电影市场快速回暖以来&#xff0c;多部爆款作品接力上映&#xff0c;持续刺激市…

项目篇 | 图书管理系统 | 图像加载与绘制

项目篇 | 图书管理系统 | 图像加载与绘制 基本介绍 首先解释清楚什么叫图像加载与绘制,意思就是说项目中需要用到一些图片资源(各种图标),我们要在图书管理系统中展示这些图片,就需要先导入图片到项目中,再加载图片资源(通过资源路径)、绘制图片(即展示)。 注:如果…

如何将Word中的表格图片转换为可编辑格式?

我们都知道&#xff0c;Word中的表格是一个非常有用的工具&#xff0c;可以让我们在文档中轻松添加和编辑各种数据。但有时候我们可能会遇到一个问题&#xff1a;当表格作为图片插入时&#xff0c;我们就不能直接编辑它了。这可怎么办呢&#xff1f; 别担心&#xff0c;我们有…

Python语言学习笔记之八(文件IO)

本课程对于有其它语言基础的开发人员可以参考和学习&#xff0c;同时也是记录下来&#xff0c;为个人学习使用&#xff0c;文档中有此不当之处&#xff0c;请谅解。 1、什么是文件I/O 在Python中&#xff0c;文件IO&#xff08;输人/输出)是指与文件进行交互的过程。这包括读…

翻译: 生成式人工智能项目的生命周期 Lifecycle of a generative AI project

我将分享一下构建生成式AI软件应用程序的过程。首先&#xff0c;我们会确定项目范围&#xff0c;决定软件要实现的功能。例如&#xff0c;你可能决定建立一个餐厅声誉监控系统。接下来是实际的实施阶段。由于生成式AI使构建应用程序变得容易&#xff0c;你通常可以很快构建出一…

【Fastapi框架】Fastapi的使用和进阶

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、项目启动1.安装2.示例3.启动4.路由 二、进阶1.请求数据2.静态文件加载3.路由管理4.跨域配置5.自定义中间件6.使用jwt中间件 前言 一、…

轻松学习视频剪辑:视频转码批量转为序列图片技巧,从新手到高手

随着视频剪辑的普及&#xff0c;越来越多的爱好者开始尝试自己动手进行视频剪辑。对于新手来说&#xff0c;掌握一些实用的技巧是很有必要的。在视频剪辑中&#xff0c;有时候要将视频片段转换为序列图片&#xff0c;以便进行更灵活的编辑和处理。本文详解云炫AI智剪的一种简单…

Python爬虫实战(基础篇)—9获取某个城市天气(附完整代码)

文章目录 专栏导读背景1、网址(请求URL)2、查看请求方法、参数3、请求初步测试代码请求成功 4、数据清洗(lxmlxpath)【城市实时天气】【日期】lxmlxpath 代码【室外温度】【体感温度】lxmlxpath 代码【天晴情况】【全天气温】lxmlxpath 代码【气压值】【降水量】【风力情况】【…

Ransac 算法的探索和应用

Ransac 算法python 应用和实现 Ransac 算法是一种常用的图像匹配算法&#xff0c;在参数估计领域也经常被使用到。针对估计各种曲线的鲁棒模型参数&#xff0c;效果显著。这里对ransac算法进行某些探索。 python program: import numpy as np import matplotlib.pyplot as p…

UniGui使用CSS移动端按钮标题垂直

unigui移动端中按钮拉窄以后&#xff0c;标题无法垂直居中&#xff0c;是因为标题有一个padding属性&#xff0c;在四周撑开一段距离。会变成这样&#xff1a; 解决方法&#xff0c;用css修改padding&#xff0c;具体做法如下 首先给button的cls创建一个cls,例如 然后添加css&…

python numpy 两种方法将相同shape的一维数组合并为二维数组

1 np.column_stack 最简单的一种方法 将多个一维数据按【列】合并为二维数组 import numpy as np# a b 都是一维数组 a np.array((1,2,3)) b np.array((2,3,4))# 变成二维 merge np.column_stack((a,b)) # array([[1, 2],[2, 3],[3, 4]])2 np.hstack 尽管该函数也是对【列…

桂电|《操作系统》实验一:UNIX/LINUX及其使用环境(实验报告)

桂林电子科技大学2023-2024学年 第 一 学期 操作系统A 实验报告 实验名称 实验一 UNIX/LINUX及其使用环境 实验指导老师&#xff1a; 成绩 院 系 计算机与信息安全学院 专业 计算机科学与技术(卓越工程) 学 号 姓名 课内序…