SpringCloud-负载均衡-Ribbon

news2024/12/23 9:32:07

在这里插入图片描述

文章目录

  • 1. 作用:负载均衡
  • 2. 应用实战
    • 2.1 provider-a代码
    • 2.2 provider-b代码
    • 2.3 consumer代码
    • 2.4 api工具向consumer发送请求查看对provider的调用情况
  • 3. ribbon总结
    • 3.1 Ribbon 源码核心
    • 3.2 如何实现负载均衡的呢?

1. 作用:负载均衡

2. 应用实战

请求发给consumer,consumer调用provider-a和provider-b,达到负载均衡的效果
下面三个服务都作为eureka-client向eureka-server注册

2.1 provider-a代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProviderController {


    @GetMapping("hello")
    public String hello(){
        return "我是提供者aaaa的接口";
    }

}

2.2 provider-b代码

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProviderController {


    @GetMapping("hello")
    public String hello(){
        return "我是提供者bbbb的接口";
    }

}

2.3 consumer代码

controller:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    /**
     * 思考 ribbon是怎么将 http://provider/hello 路径请求成功的
     * http://127.0.0.1:8080/hello
     * 1.拦截这个请求
     * 2.截取主机名称
     * 3.借助eureka来做服务发现 list<>
     * 4.通过负载均衡算法 拿到一个服务ip port
     * 5.reConstructURL
     * 6.发起请求
     *
     * @param serviceName
     * @return
     */
    @GetMapping("testRibbon")
    public String testRibbon(String serviceName){
        // 正常来讲 需要 拿到ip和port 以及 路径 才可以用
        // http://provider/hello
        String result = restTemplate.getForObject("http://" + serviceName + "/hello", String.class);
        // 只要你给restTemplate 加了ribbon的注解 项目中这个对象发起的请求 都会走ribbon的代理
        // 如果你想使用原生的restTemplate 就需要重新创建一个对象
        // RestTemplate myRest = new RestTemplate();
        // String forObject = myRest.getForObject("http://localhost:8888/aaa", String.class);
        return result;
    }


    // 轮训的算法 怎么去实现
    // 两台机器   A B
    // A
    // B
    // A
    // B
    // 代码实现轮训的算法  List<机器>
    // 请求次数
    //  int index =   1 % size    list.get(index);
    // % 取模 取余好处是一个周期函数 让得到的结果 总是小于 除数的
    //  1 / 2    1 % 2
    // 1%2=1
    // 2%2=0
    // 3%2=1
    // 4%2=0
    // 全局顶一个int i = 0
    // i++  线程不安全的
    // i % size
    // 怎么能做一个线程安全的轮训算法   加锁 效率极低  CAS 自旋锁 没有线程的等待和唤醒的开销
    // CAS 优点 性能好 java层面无锁的状态  但是在jvm层面 有锁的cmpxchg
    // CAS 缺点 会导致短暂时间内 CPU 飙升  还有ABA 问题


    /**
     * 核心是负载均衡,算法包括轮询、随机、权重、iphash
     * @param serviceName
     * @return
     */
    @GetMapping("testRibbonRule")
    public String testRibbonRule(String serviceName){
        ServiceInstance choose = loadBalancerClient.choose(serviceName);
        return choose.toString();
    }

}

启动类:在启动类对restTemplate的bean加上注解@LoadBalanced,这样整个服务内使用restTemplate调用时就能达到负载均衡的效果;
myRule()会定义负载均衡算法,不定义就是轮询,这里是随机算法

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }

    /**
     * 这个RestTemplate 已经变了
     * LoadBalanced 他就会被ribbon来操作
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate111(){
        return new RestTemplate();
    }

    /**
     * 往容器中放一个rule对象
     * 你访问任何一个提供者 都是这个算法
     * @return
     */
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }

}

配置文件:application.yml

server:
    port: 8082
spring:
    application:
        name: consumer
eureka:
    client:
        service-url:
            defaultZone: http://localhost:8761/eureka
    instance:
        hostname: localhost
        prefer-ip-address: true
        instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
# 访问不同的服务可以使用不同的算法规则,在启动类配置了,这里就不用配置了
#provider:  # 先写服务提供者的应用名称
#    ribbon:
#        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule    #几种算法的全限定类名
ribbon:
    eager-load:
        enabled: false # ribbon它只有自己的话 能不能做服务发现 借助eureka  # ribbon需要去eureka中获取服务列表 如果false就懒加载
    eureka:
        enabled: true
    http:  # 我们使用ribbon 用的restTemplate发请求 底部是java.net.HttpUrlConnection 发的请求  很方便 但是它不支持连接池
        client:  # 发请求的工具有很多 httpClient  它支持连接池 效率更好  如果你想改请求的工具 记得加这个依赖即可
            enabled: false
    okhttp: # 这个也是请求工具 移动端用的比较多 轻量级的请求
        enabled: false

2.4 api工具向consumer发送请求查看对provider的调用情况

http://localhost:8082/testRibbon?serviceName=provider
这是consumer接口的url,serviceName是provider的服务名,对应provider-a和provider-b
在这里插入图片描述

再次发送请求:
在这里插入图片描述

3. ribbon总结

Ribbon 总结(后面的代码中 不会出现 ribbon)
Ribbon 是客户端实现负载均衡的远程调用组件,用法简单

3.1 Ribbon 源码核心

ILoadBalancer 接口:起到承上启下的作用

  1. 承上:从 eureka 拉取服务列表
  2. 启下:使用 IRule 算法实现客户端调用的负载均衡
    设计思想:每一个服务提供者都有自己的 ILoadBalancer
    userService—》客户端有自己的 ILoadBalancer
    TeacherService—》客户端有自己的 ILoadBalancer
    在客户端里面就是 Map<String,ILoadBalancer> iLoadBalancers
    Map<String,ILoadBalancer> iLoadBalancers 消费者端
    服务提供者的名称 value (服务列表 算法规则 )

3.2 如何实现负载均衡的呢?

iloadBalancer loadbalance = iloadBalancers.get(“user-service”)
List servers = Loadbalance.getReachableServers();//缓存起来
Server server = loadbalance .chooseServer(key) //key 是区 id,–》IRule 算法
chooseServer 下面有一个 IRule 算法
IRule 下面有很多实现的负载均衡算法
你就可以使用 eureka+ribbon 做分布式项目

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

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

相关文章

演唱会总是抢不到票?教你用Python制作一个自动抢票脚本

人生苦短 我用python 这个大家应该都知道吧&#xff1f; 是中国综合类现场娱乐票务营销平台&#xff0c; 业务覆盖演唱会、 话剧、音乐剧、体育赛事等领域。 如何快速抢票&#xff1f; 那么&#xff0c; 今天带大家用Python来制作一个自动抢票的脚本小程序 本文源码python安…

使用Java对稀疏数组的压缩与还原

稀疏矩阵的压缩与还原 稀疏数组中元素个数很少或者有大量的重复值&#xff0c;如果直接保存保存&#xff0c;会浪费很多空间&#xff0c;这时&#xff0c;就可以考虑对数组进行压缩存储。 先定义一个稀疏数组 //创建一个二维数组 11 * 11 int[][] array1 new int[11][11]; /…

Window 编辑、删除、新增右键菜单

关于 Window 右键菜单 右键菜单可以在注册表编辑器中新增和修改 建议先下载 registry-finder&#xff0c;查找速度更快&#xff01; 使用管理员模式打开 registry-finder 后&#xff0c;点击 HKEY_CLASSES_ROOT &#xff0c;修改注册表右键菜单的子路径如下表所示 类型路径…

49.在ROS中实现local planner(2)- 实现Purepersuit(纯跟踪)算法

48.在ROS中实现local planner&#xff08;1&#xff09;- 实现一个可以用的模板实现了一个模板&#xff0c;接下来我们将实现一个简单的纯跟踪控制&#xff0c;也就是沿着固定的路径运动&#xff0c;全局规划已经规划出路径点&#xff0c;基于该路径输出相应的控制速度 1. Pur…

Linux系列学习(三) - 进程和库文件

目录 引言&#xff1a; 学习&#xff1a; 基本命令补充&#xff1a; wc命令&#xff1a; more命令&#xff1a; less命令&#xff1a; cat ps命令&#xff1a; kill命令&#xff1a; bg命令&#xff1a; fg命令&#xff1a; 查看系统运行级别&#xff1a; 库文件&a…

unity UGUI系统梳理 - 常用可视化控件

作为一名合格的UI仔>.<&#xff0c;我发现很多UI很久没有使用了&#xff0c;所以我决定做一个UGUI系列博客重新梳理一下 1、Image 在没有放入图片下&#xff0c;image控件长这样 注意 我一般没交互需求的情况下都会把RaycastTarget给点掉&#xff0c;这个不单单是从提…

CAPL脚本DBLookup函数动态访问CAN 报文的属性

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

学习周报3.5

文章目录前言文献阅读摘要介绍方法总结相关性总结前言 本周阅读文献《Multi-step ahead probabilistic forecasting of multiple hydrological》&#xff0c;文献主要提出一种基于三维卷积神经网络、卷积最小门记忆神经网络和变分贝叶斯神经网络的混合深度学习模型&#xff08…

【博学谷学习记录】超强总结,用心分享|狂野大数据课程【Spark SQL函数定义】的总结分析

5.1 如何使用窗口函数 回顾: 窗口函数格式:分析函数 over(partition by xxx order by xxx [asc|desc] [rows between xxx and xxx])学习的相关分析函数有那些? 第一类: row_number() rank() dense_rank() ntile()第二类: 和聚合函数组合使用 sum() avg() max() min() count…

西电软件体系结构核心考点汇总(期末真题+核心考点)

文章目录前言一、历年真题二、核心考点汇总2.1 什么是软件体系架构?(软件体系结构的定义)2.2 架构风格优缺点2.3 质量属性2.4 质量评估前言 主要针对西安电子科技大学《软件体系结构》的核心考点进行汇总。 【期末期间总结资料如下】 针对西电计科院软件工程专业大三《软件体…

【QT】使用QML构建一个简易的计算器界面(三)

前面两篇对计算器界面的布局和显示以及实现功能做了相关优化&#xff0c;但是对输入显示那一块还没有具体的处理步骤&#xff0c;包括对输入表达式的合法性检查&#xff0c;显示框的多行历史显示等功能还需要添加&#xff0c;接下来将从这几个方面对这些功能进行添加。 1、对输…

概率论 1.3 古典概型与几何概型

1.3.1 排列与组合排列从n个不同元素任取r(r<n)个元素排成一列(考虑元素出现的先后次序)&#xff0c;称此为一个排列&#xff0c;此种排列的总数为n(n-1)....(n-r1)n!/(n-r)&#xff01;&#xff0c;若rn,则称为全排列&#xff0c;2.重复排列从n个不同元素中每次取出一个,放回…

GPIO输入和输出以及八种工作模式

一.GPIO的简介 GPIO &#xff08;general purpose input output&#xff09;是通用输入输出端口的简称&#xff0c;简单来说就是软件可控制的引脚&#xff0c;STM32芯片的GPIO引脚与外部传感器连接起来&#xff0c;从而实现与外部通讯、控制以及数据采集的功能。 1.引脚全是GP…

[2.1.1]进程管理——进程的概念、组成、特征

文章目录第二章 进程管理进程的概念、组成、特征&#xff08;一&#xff09;进程的概念&#xff08;二&#xff09;进程的组成——PCB&#xff08;三&#xff09;进程的组成——程序段、数据段补充&#xff1a;程序是如何运行的&#xff1f;&#xff08;四&#xff09;进程的特…

vue3 插槽使用详解

目录1 前言2 插槽的使用2.1 基本使用2.2 具名插槽2.3 动态插槽名2.4 插槽传值3 总结1 前言 Vue 实现了一套内容分发的 API&#xff0c;将 <slot> 元素作为承载分发内容的出口&#xff0c;使用插槽使得vue组件的设计更加灵活。 在vue版本更迭中&#xff0c;尽管插槽的使…

常用的设计模式之一(创建型模式)

设计模式可分为三大类&#xff1a; 创建型模式 (Creational Patterns)结构性模式 (Structural Patterns)行为型模式 (Behavioral Patterns) 模式描述包括创建型模式工厂模式&#xff08;Factory Pattern&#xff09; 抽象工厂模式&#xff08;Abstract Factory Pattern&#…

并发编程——可见性与有序性

如果有兴趣了解更多相关内容&#xff0c;欢迎来我的个人网站看看&#xff1a;耶瞳空间 JMM即Java Memory Model&#xff0c;它定义了主存、工作内存抽象概念&#xff0c;底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。JMM体现在以下几个方面&#xff1a; 原子性&…

Web API

DOM API 1、选中页面元素 let elem document.querySelector(CSS选择器); console.log(elem); console.dir(elem); 2、事件 鼠标点击事件 onclick 鼠标移动事件 onmousemove 等等 事件源 .box&#xff0c;事件类型 onlick&#xff0c;事件处理方式 alert(hello) let d…

[Mybatis1]介绍与快速入门

文章目录 Mybatis概述 持久层 框架 Mybatis与JDBC对比 JDBC代码的缺陷 Mybatis简化JDBC Mybatis快速入门案例 整体案例项目结构 1.创建user表&#xff0c;添加数据 2.创建Maven项目&#xff0c;导入坐标 3.编写Mybatis核心配置文件 4.编写数据库返回对象的实体类 5. 编写S…

QML Button详解

1.Button简介 Button表示用户可以按下或单击的按钮控件。按钮通常用于执行一个动作&#xff0c;或回答一个问题。典型的按钮有确定、应用、取消、关闭、是、否和帮助。 Button继承自AbstractButton&#xff0c;提供了以下几种信号。 void canceled() //当按…