SpringCloud 学习(三)Ribbon 和 Feign

news2024/12/23 17:47:21

4. Netflix.Ribbon

4.1 简介

(1) 概念

  • Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端负载均衡工具

(2) 负载均衡(LB:LoadBalance)和集群架构

在这里插入图片描述

  • 应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理,并返回相应数据。
  • 负载均衡设备:将用户访问的请求,根据负载均衡算法,分发到集群中的一台处理服务器。(一种把网络请求分散到一个服务器集群中的可用服务器上去的设备)。
  • 负载均衡的作用(解决的问题):
    • 解决并发压力,提高应用处理性能(增加吞吐量,加强网络处理能力);
    • 提供故障转移,实现高可用;
    • 通过添加或减少服务器数量,提供网站伸缩性(扩展性);
    • 安全防护;(负载均衡设备上做一些过滤,黑白名单等处理)

(3) 负载均衡分类

  • 集中式 LB
    • 在服务的消费方和提供方之间使用独立的 LB 设施,如 Nginx(反向代理服务器),由该设施把访问请求通过某种策略转发至服务的提供方。
  • 进程式 LB
    • 将 LB 逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后从这些地址中选用一个服务器。
    • Ribbon 属于进程式 LB,它是一个类库,集成于消费方进程,消费方通过它来获取提供方的地址。

4.2 集成 Ribbon

调整 springcloud-consumer-dept-80 服务

● 添加依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
● 为 RestTemplate 配置负载均衡
@Configuration  // spring applicationContext.xml
public class ConfigBean {

    // 注册 bean <bean></bean>
    @Bean
    // 配置负载均衡实现 RestTemplate
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
● 修改获取远程服务的地址
// DeptConsumerController
// Ribbon 实现负载均衡,此处的地址应是一个变量——服务名
// private static final String REST_URL_PREFIX = "http://localhost:8001";
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
● 添加 Eureka 配置
# eureka
eureka:
  client:
    # 不向 eureka 注册自己
    register-with-eureka: false
    # 列出可使用的服务地址供消费者服务选择
    service-url:
      defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
● 开启 Eureka 客户端服务
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

4.3 模拟多服务访问

● 创建数据库

在这里插入图片描述

cloud01.dept.db_source = cloud01
cloud02.dept.db_source = cloud02
cloud03.dept.db_source = cloud03
● 创建两个 maven 模块作为服务提供者

springcloud-provider-dept-8001
springcloud-provider-dept-8002
springcloud-provider-dept-8003

在这里插入图片描述

  • 修改配置文件

    springcloud-provider-dept-8001 => cloud01
    springcloud-provider-dept-8002 => cloud02
    springcloud-provider-dept-8003 => cloud03
    
● 访问效果

在这里插入图片描述

在这里插入图片描述

4.4 自定义 Ribbon 规则

(1) 创建 Ribbon 配置类

  • 自定义配置类的组件会覆盖 RibbonClientConfiguration 中的组件来完成配置。

  • 自定义配置类的注解必须是 @Configuration,其不在主应用程序下的 @ComponentScan 中,否则将由所有 @RibbonClients 共享,若使用 @ComponentScan / @SpingBootApplication,则需要采取避免措施,,如将其放在一个单独的,不重叠的包中,或指定在 @ComponentScan。

  • 自定义配置类放在启动类所在的目录外

    在这里插入图片描述

    /**
     * 每个服务访问 5 次,选择下一个服务
     * @author why
     * @since 2021/9/7 21:02
     */
    public class RoundFiveRule extends AbstractLoadBalancerRule {
    
        // 被调用次数
        private int toltal = 0;
    
        // 当前提供服务的索引
        private int currentIndex = 0;
    
        // @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
        public Server choose(ILoadBalancer lb, Object key) {
            if (lb == null) {
                return null;
            }
            Server server = null;
    
            while (server == null) {
                if (Thread.interrupted()) {
                    return null;
                }
    
                // 获取可用服务
                List<Server> upList = lb.getReachableServers();
                // 获取所有服务
                List<Server> allList = lb.getAllServers();
    
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }
    
                // // 生成区间随机数
                // int index = chooseRandomInt(serverCount);
                // // 随机获取可用服务
                // server = upList.get(index);
    
                //===============================================================================
                if (toltal < 5) {
                    server = upList.get(currentIndex);
                    toltal++;
                } else {
                    toltal = 1;
                    currentIndex++;
                    if (currentIndex >= upList.size()) {
                        currentIndex = 0;
                    }
                    server = upList.get(currentIndex);
                }
                System.out.print(" " + currentIndex + " ");
                //================================================================================
    
                if (server == null) {
                    Thread.yield();
                    continue;
                }
    
                if (server.isAlive()) {
                    return (server);
                }
                server = null;
                Thread.yield();
            }
    
            return server;
    
        }
    
        protected int chooseRandomInt(int serverCount) {
            return ThreadLocalRandom.current().nextInt(serverCount);
        }
    
        @Override
        public Server choose(Object key) {
            return choose(getLoadBalancer(), key);
        }
    
        @Override
        public void initWithNiwsConfig(IClientConfig clientConfig) {
            // TODO Auto-generated method stub
        }
    
    }
    

(2) 将自定义配置类注册到 Spring 中

@Configuration
public class MyRule {
   	// 将自定义配置类注册到 Spring 中
    @Bean
    public IRule myRule() {
        return new RoundFiveRule();
    }
}

(3) 配置启动类自动加载自定义配置类

@SpringBootApplication
@EnableEurekaClient
/*
 * 微服务启动时,加载 Ribbon 配置类
 * @param name 服务名
 * @param configuration 自定义配置类的反射
 */
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT", configuration = RoundFiveRule.class)
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class, args);
    }
}

在这里插入图片描述

虽然 index 为轮询方式,但由于 index 并未与服务进行一对一绑定,所以服务的访问准确来说并不是每 5 次就更换下一个服务。

5. Netflix.Feign

5.1 简介

  • Feign 是声明式的 web service 客户端,它简化了微服务之间的调用。
  • Ribbon 使用微服务名字调用微服务,Feign 使用接口和注解调用微服务。
  • 创建一个接口,使用 Feign 注解进行配置,即可完成对服务提供方的接口绑定。
  • Feign 集成了 Ribbon,通过添加一层的方式增加了代码的可读性,但是性能有所降低

5.2 Feign 实现

调整 springcloud-consumer-dept-80 微服务

● 创建 maven moudle

在这里插入图片描述

● 添加依赖

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-feign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>

● 删除 Ribbon 配置

● 编写 Feign 服务层

在公共服务 springcloud-api 中添加 Feign 服务层

在这里插入图片描述

/**
 * Feign 实现服务的调用
 *
 * @author why
 * @since 2021/9/9 9:24
 */
// 将接口注册到 Spring,否则会报红,但是却不影响调用,原因不明
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {

    @GetMapping("/dept/getDept/{id}")
    public Dept queryById(@PathVariable("id") Long id);

    @GetMapping("/dept/list")
    public List<Dept> queryAll();

    @PostMapping("/dept/add")
    public boolean addDept(Dept dept);
}

● 启动类开启 Feign 扫描

@SpringBootApplication
@EnableEurekaClient
/*
 * @EnableFeignClients(basePackages = {"com.why.springcloud"})  扫描 springcloud-api 
 * 务 com.why.springcloud 目录及以内目录下的 @FeignClient
 */
@EnableFeignClients(basePackages = {"com.why.springcloud"})
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class, args);
    }
}

● 远程调用

Feign 服务层也可以放在当前服务服务中,此时无需对注解 @EnableFeignClients 的属性赋值

@SpringBootApplication
@EnableEurekaClient
/*
 * @EnableFeignClients 扫描当前服务主类同级及以内目录下的 @FeignClient
 */
@EnableFeignClients
public class FeignDeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignDeptConsumer_80.class, args);
    }
}

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

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

相关文章

文档升级 | iTOP-RK3568开发板ADB工具的安装和使用

iTOP -RK3568开发板使用手册更新&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 《iTOP-3568开发板ADB使用手册》进行了文档升级&#xff0c;对ADB工具的安装和使用进行了更全面的步骤介绍。 第1章 安装adb工…

git revert 撤销之前的提交

git revert 用来撤销之前的提交&#xff0c;它会生成一个新的 commit id 。 输入 git revert --help 可以看到帮忙信息。 git revert commitID 不编辑新的 commit 说明 git log 找到需要撤销的 commitID &#xff0c; 然后执行 git revert commitID &#xff0c;会提示如下…

DataGrip初始化设置

DataGrip初始化设置 自定义设置 具体配置项 Customize —> Allsettins… 外观 退出IDE之前无需确认 启动IDE自动打开之前的项目 Appearance & Behavior —> System Settings —> Confirm before exiting the IDE Appearance & Behavior —> System Settin…

写一个Chrome浏览器插件(manifest v3)

目录 1、创建manifest.json 文件 2、开始写popup页面以及对应的逻辑。 2.1 popup 页面 2.2 后台运行 background.js 2.3 content.js 2.4 popup页面的js文件 3、chrome 浏览器加载本项目 4、参考文档 1、创建manifest.json 文件 首先需要在项目的根目录下创建manifes…

深入剖析Redis系列- Redis数据结构之哈希

1.11.5哈希类型(hash) Redis的hash 是一个string类型的key和value的映射表&#xff0c;这里的value是一系列的键值对&#xff0c;hash特别适合用于存储对象。 哈希类型的数据操作总的思想是通过key和field操作value&#xff0c;key是数据标识&#xff0c;field是域&#xff0c;…

基于SSM+Vue的舞蹈网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

大二上Redis学习笔记

redis非关系型数据库NOSQL&#xff0c;用c语言编写的,基于内存的数据库&#xff0c;每秒支持十几万的读写操作&#xff0c;性能远超数据库&#xff0c;还支持集群、分布式、主从同步等配置。 Redis基本功能 1 发布订阅系统 2 地图信息分析 3 计时器和计数器 redis运行的图形界…

【腾讯云TDSQL-C Serverless 产品体验】使用 Python向TDSQL-C添加读取数据实现词云图

关于TDSQL-C Serverless介绍 TDSQL-C 是腾讯云自主研发的新一代云原生关系型数据库。 它融合了传统数据库、云计算和新硬件技术的优势,100%兼容 MySQL,为用户提供具有极致弹性、高性能、高可用性、高可靠性和安全性的数据库服务。 TDSQL-C 实现了超过百万每秒的高吞吐量,支持…

SpringCloud 学习(四)Hystrix

6. Netflix.Hystrix 6.1 简介 ● 扇出 多服务之间调用&#xff0c;若微服务 A 调用微服务 B 和微服务 C&#xff0c;微服务 B 和 微服务 C 又调用其他微服务&#xff0c;这就是扇出 ● 服务雪崩 若扇出的链路上某个微服务的调用响应时间过长或者不可用&#xff0c;么此扇出…

ESP32在CAN(TWAI)波特率不同时收发数据,导致总线错误无法恢复

问题描述&#xff1a; 总线上有两个设备&#xff0c;主机&#xff1a;100ms周期发送数据。从机&#xff1a;以不同波特率发送数据&#xff0c;再把从机波特率调节至主机波特率一致无法通信。 环境&#xff1a;VSCODE IDF-v5.0 问题分析&#xff1a; 我们先看下ESP32技术参…

Spring 学习(四)注解实现自动装配及注解开发

1. 注解实现自动装配 JDK 1.5 开始支持注解&#xff0c;Spring 2.5 开始支持注解。 使用须知 导入约束 配置注解的支持&#xff08; <context:annotation-config/> &#xff09; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns&qu…

2023微信头像生成小程序,国庆头像生成,基于skyline+vue3+t

微信头像生成小程序&#xff0c;基于skylinevue3t该项目已适配微信小程序隐私政策&#xff0c;截图、获取头像等诸多新的接口 如何使用&#xff1a; 将代码导入到HBuilderX开发工具&#xff0c; 可无需修改任何代码&#xff0c;运行并编译到微信开发者工具 skyline需要使用微…

layui中使用JavaScript监听下拉框(select)的变化,根据选中的值来决定是否显示或隐藏input元素

HTML代码 <div class"layui-form-item" id"rubric"><label class"layui-form-label">前端说明</label><div class"layui-input-inline"><input type"text" id"user_rubric" name"…

页面添加遮罩层

1.css代码 // 子绝父相.self-check-tag {display: inline-block;min-width: 132px;height: 32px;position: relative;.overlay {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background-color: gray;opacity: 0.1;}2.效果

QT windows dpi变化导致的界面异常处理

问题&#xff1a;已经在UI界面中利用布局设计好界面&#xff0c;但是运行程序后显示的界面出现错乱&#xff0c;而且在做出一些修改后重新构建&#xff0c;运行时界面无变化。 目录 一、解决UI设计界面与运行时显示界面不一致的问题 1、导致该现象的原因有&#xff1a;显示屏…

[Linux] 3.Linux下编码和执行文件

Ctrl Alt T快捷键调出命令终端 输入xrandr指令把现有的电脑分辨率列出来 &#xff0c;xrandr -s 分辨率可以调节至想要的分辨率 调节字体大小&#xff1a;Ctrl Shift “”或Ctrl Shift “-” 使字体变大变小 拖动窗口右下角可调节窗口大小 Ctrl “L”清屏 编写C代码文件:…

【数据结构】散列表(哈希表)的学习知识总结

目录 1、散列表 2、散列函数 2.1 定义 2.2 散列函数的构造 2.2.1 除留余数法 2.2.2 直接定址法 2.2.3 数字分析法 2.2.4 平方取中法 3、冲突&#xff08;碰撞&#xff09; 4、处理冲突的方法 4.1 拉链法&#xff08;链接法&#xff09; 4.2 开放定址法 5、C语言…

电缆直埋、电缆沟、电缆井大样图

一、图纸下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1_SUnhFHMUY8Q_kkhgzscDQ?pwd8888 提取码&#xff1a;8888 二、部分图纸预览

GoogLeNet网络

目录 1. 创新点 1.1 引入Inception结构 1.2 11卷积降维 1.3 两个辅助分类器 1.4 丢弃全连接层&#xff0c;使用平均池化层 2. 网络结构 3. 知识点 3.1 torch.cat 3.2 关于self.training 3.3 关于load_state_dict中的strict 4. 代码 4.1 model.py 4.2 train.py …

MQ - 30 基础功能:死信队列的设计

文章目录 导图概述什么是死信队列死信队列实现的技术方案死信队列的存储目标死信队列的方案设计生产死信队列消费死信队列Broker 的死信队列主流消息队列的死信功能RocketMQRabbitMQ总结导图 概述 在日常业务的消费数据过程中,如果遇到数据无法被正确处理,就需要先手动把消息…