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

【SpringCloud】Ribbon(LoadBalancer ) 和 Feign

文章目录

  • 负载均衡
  • Ribbon简介
  • Ribbon的使用(jdk1.8的环境下是可以的)
  • LoadBalancer 负载均衡器
    • 正常使用
    • 扩展学习
  • 实现负载均衡
  • 自定义负载均衡的算法(LoadBalancer)
    • 详细流程
    • Ribbon的方式(Spring新版不支持)
  • Feign简介
    • Feign能做些什么
    • Feign的特点
  • Feigen的使用
    • 前提准备
    • 使用流程
      • 导入依赖
      • 编写逻辑代码,使用注入的方式将Service导入进去
      • 编写配置文件
      • 启动配置,进行测试

负载均衡

峰值调用,通过网速汇总,调整网络的速率吞吐,其中LVS是典型的应用

画板

Ribbon简介

SpringCloud Ribbon 是基于NetFlix Ribbon实现的一套客户端负载均衡的工具

Ribbon将负载均衡的位置放在了消费方,和Eureka挂钩,找到合适的节点进行使用;

经调查发现,SpringCloud使用的2024.0.0,对应SpringBoot3.4.5,官方已经完全移除了Ribbon,现在转用loadbalancer,

Ribbon的使用(jdk1.8的环境下是可以的)

三件套:

  • 导入依赖启动器
  • 编写配置文件
  • 启动配置
  • 编写配置类(视情况而定)
  1. 导入依赖:Ribbon、Eureka-Client
<!-- 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-server -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka-server</artifactId><version>1.4.6.RELEASE</version>
</dependency>
  1. 编写配置文件
  2. 启动配置
  3. 测试

LoadBalancer 负载均衡器

Ribbon和LoadBalancer相差不大,大多数内容一致;

LoadBalancer翻译过来的意思是 负载均衡器

正常使用

  1. 导入依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-commons</artifactId>
</dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId><version>4.2.0</version>
</dependency>
  1. 编写配置文件,localhost换成域名
server:port: 8080eureka:client:register-with-eureka: false # 是否注册自己,消费者不需要向注册中心注册自己service-url:defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  1. 配置类 ,使用注解@LoadBalanced
@Configuration
public class ConfigBean { // 相当于 application.xml@Bean@LoadBalanced // 开启负载均衡功能public RestTemplate getRestTemplate() {return new RestTemplate();}
}
  1. 启动配置,检查问题,理论上是正常启用

扩展学习

  1. 更改服务消费方的访问地址,在最开始是使用RestTemplate的时候使用的http://localhost:8001/,现在改成服务消费者的名字,之后再在Controller中将对应的url改成服务名http://SPRINGCLOUD-PROVIDER-DEPT

  1. 再次开启所有的服务,查看三个集群是否都可以访问 服务供应者;
  2. 可以之后,访问消费者,使用消费者的Request请求路径访问,测试成功。

实现负载均衡

创建三个服务提供者,使用一样的数据库,数据库Database不一样;

每个服务(8001/8002/8003)都关联多个注册中心(7001/7002/7003);

这样子就会使LoadBalance 进行负载均衡,默认使用轮询调用的方式;

场景:

serveportdatabaseEureka注册中心
80018001DB017001/7002/7003
80028002DB027001/7002/7003
80038003DB037001/7002/7003

这样子在注册中心调用分配的时候会调用8001,之后再调8002,8003;消费者方发出请求后也会从7001/7002/7003中选择一个合适的节点,进行调用;

默认理解的是:

服务消费者 >> 随机的Eureka注册中心 >> 随机的server服务器 >> 返回调用内容数据;

特别的占内存,测试时启动的微服务 使用 3~5个就可以了

自定义负载均衡的算法(LoadBalancer)

详细流程

  1. 确保依赖已完全导入
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
  1. 实现自定义负载均衡器 ReactorServiceInstanceLoadBalancer
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.*;
import org.springframework.cloud.loadbalancer.core.*;
import reactor.core.publisher.Mono;import java.util.List;
import java.util.Random;public class CustomRandomLoadBalancer implements ReactorServiceInstanceLoadBalancer {private final String serviceId;private final ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;public CustomRandomLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,String serviceId) {this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;this.serviceId = serviceId;}@Overridepublic Mono<Response<ServiceInstance>> choose(Request request) {ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);return supplier.get(request).next().map(serviceInstances -> processInstanceResponse(serviceInstances));}private Response<ServiceInstance> processInstanceResponse(List<ServiceInstance> instances) {if (instances.isEmpty()) {return new EmptyResponse();}// 自定义逻辑:随机选择int index = new Random().nextInt(instances.size());ServiceInstance instance = instances.get(index);System.out.println("【CustomRandomLoadBalancer】选择了实例: " + instance.getHost() + ":" + instance.getPort());return new DefaultResponse(instance);}
}
  1. 注册 Spring Bean(按服务名绑定)
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@LoadBalancerClient(value = "springcloud-provider-dept", // ← 指定服务名configuration = CustomLoadBalancerConfig.class
)
public class LoadBalancerConfiguration {// 可留空
}class CustomLoadBalancerConfig {@BeanReactorServiceInstanceLoadBalancer customLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new CustomRandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class),serviceId);}
}

这样只有调用 springcloud-provider-dept 时才使用随机算法,其他服务仍用默认轮询算法。

  1. 使用 @LoadBalanced 调用
@Bean
@LoadBalanced
public RestTemplate restTemplate() {return new RestTemplate();
}// 调用
restTemplate.getForObject("http://springcloud-provider-dept/dept/list", String.class);

Ribbon的方式(Spring新版不支持)

// Ribbon 方式(已过时)
public class CustomRandomRule extends AbstractLoadBalancerRule {@Overridepublic Server choose(Object key) {ILoadBalancer lb = getLoadBalancer();List<Server> servers = lb.getAllServers();// 随机选择...return servers.get(new Random().nextInt(servers.size()));}
}// 配置类
@RibbonClient(name = "springcloud-provider-dept", configuration = RibbonConfig.class)
public class ConsumerApp { }class RibbonConfig {@Beanpublic IRule ribbonRule() {return new CustomRandomRule();}
}

不要混合使用 Ribbon 和 LoadBalancer

Feign简介

在 Spring Cloud 2024.0.0(基于 Spring Boot 3.4.5) 的现代微服务架构中,Feign 依然是实现 声明式 HTTP 客户端 的核心组件,但其底层已从 Ribbon 切换为 Spring Cloud LoadBalancer,并全面适配 Jakarta EE(jakarta.* 包)。

Feign能做些什么

Feign的目的是在编写Java Http客户端更加容易;

Feign是声明式的web Service客户端,再次简化了微服务之间的调用,类似于Controller调用Service,SpringCloud会同时集成Eureka和LoadBalance,再使用Feign作为负载均衡的HTTP的客户端;只需要创建一个接口,就可以添加注解;

面向接口编程是很多开发时候的规范,调用微服务访问有两种方法:

  1. 微服务名字(Ribbon/LoadBalance)
  2. 接口和注解(Feign)

Feign的特点

  • 声明式 REST 客户端:用接口 + 注解代替手动写 RestTemplate 或 WebClient
  • 自动集成负载均衡:通过 @LoadBalanced 机制,结合服务注册中心(如 Eureka/Nacos)实现服务调用。
  • 底层依赖:Spring Cloud OpenFeign(基于 Netflix Feign 封装,但已移除 Ribbon)。

Feigen的使用

前提准备

  1. 新建一个service在api中

  1. 新建一个Feign的服务,copy 80消费端的内容
  2. 删除原来Ribbon/LoadBalance的内容
  3. 在springcloud-api的com.cloud.springcloud.service创建一个service作为远程调用的service
package com.cloud.springcloud.service;import com.cloud.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;import java.util.List;/**** 公用接口 Service* FeignClient: 服务调用方* name: 服务提供者的服务名*/
@Service
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {@RequestMapping("/dept/get/{id}")public Dept get(@PathVariable("id") Long id);@RequestMapping("/dept/list")public List<Dept> list();@RequestMapping("/dept/add")public boolean add(Dept dept);@RequestMapping("/dept/delete/{id}")public boolean delete(@PathVariable("id") Long id);@RequestMapping("/dept/update")public boolean update(Dept dept);
}
  1. 在该service中调用到Mapping是服务提供者那边的,需要再加一个注解@Feign,在这个地方的value是在Eureka中设置的服务名

使用流程

组件导入流程:

  1. 导入依赖
  2. 编写配置文件
  3. 启动配置类
  4. 编写配置类

导入依赖

  • Feign的依赖
  • Eureka的依赖
  • LoadBalancer的依赖(Feign中包含这个,可以不导)
<!-- OpenFeign 核心依赖 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency><!-- 服务注册发现(以 Eureka 为例) -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency><!-- LoadBalancer(Feign 默认依赖,但显式声明更安全) -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

编写逻辑代码,使用注入的方式将Service导入进去

代码如下,注意要给api路径下的DeptClientService加入Component(@Service注解),确保能被扫描到

@RestController
public class DeptConsumerController {// idea 不建议使用Autowired//    @Autowiredprivate final DeptClientService deptClientService;public DeptConsumerController(DeptClientService deptClientService) {this.deptClientService = deptClientService;}// 消费者的请求地址@RequestMapping("/consumer/dept/findAll")public List<Dept> findAll(){return deptClientService.list();}@RequestMapping("/consumer/dept/add")public Object addDept(Dept dept) {return deptClientService.add(dept);}@RequestMapping("/consumer/dept/get/{id}")public Object findById(@PathVariable("id") Long id) {return deptClientService.get(id);}@RequestMapping("/consumer/dept/update")public Object updateDept(Dept dept) {return deptClientService.update(dept);}@RequestMapping("/consumer/dept/delete/{id}")public Object deleteDept(@PathVariable("id") Long id) {return deptClientService.delete(id);}}

编写配置文件

沿用的配置都是之前Eureka所配置完的,不需要改动,注意不要和Ribbon、LoadBalance的内容冲突

PS:Feign就是再对于LoadBalance的再次封装,Feign的底层依旧是沿用的Ribbon/LoadBalance的处理逻辑,使用java思想对其进行了封装。

启动配置,进行测试

  1. 在SpringBoot服务消费者 的启动类上启用 EnableFeignClients
@SpringBootApplication
@EnableFeignClients(basePackages = {"com.cloud.springcloud.service"})
public class SpringCloudDeptConsumerFeign_80 {public static void main(String[] args) {SpringApplication.run(SpringCloudDeptConsumerFeign_80.class, args);}
}
  1. 服务注册启动成功,Eureka页面正常显示,调用内容正常显示;
  2. 服务提供者启动正常,直接调用提供者Service的DB查询正常;
  3. 服务消费者(Feign组件)启动正常,调用URL显示内容查询正常;
http://www.dtcms.com/a/528625.html

相关文章:

  • Dockerfile 中 ENTRYPOINT 和 CMD 有什么区别 ?
  • 网站数据库模版深圳网站建设黄浦网络 骗钱
  • vs code 下docker使用方法,以php 项目为示例
  • 番禺网站建设哪里好深圳十大传媒公司
  • 前端常见的设计模式
  • 亚马逊云渠道商:如何通过配置自动替换构建故障自愈的云架构?
  • 豆包 Python 和 Java 的 AI 集成及模型转换
  • 深入解析C++命令模式:设计原理与实际应用
  • 商城网站建设目标上海前十名文化传媒公司
  • ExpressionVisitor 的使用场景及方法
  • 《3D端游开放世界动态天气系统与场景交互优化实践日志》
  • Date类自主实现后的反思
  • 网络渗流:爆炸渗流
  • 购物网站建设款流程国外优秀设计网站大全
  • 【C++】STL容器-stack和queue的使用与模拟实现
  • numpy学习笔记(持续更新)
  • linux schedule函数学习
  • 教育培训网站有哪些辽宁网站建设企业定制公司
  • Python机器学习---6.集成学习与随机森林
  • 厦门网站建设公司新能源汽车价格表图片及价格表
  • 二分查找栈堆动态规划
  • 【脚本】提取phpstudy网站对应的PHP版本
  • 沈阳做平板网站移动互联网开发是干什么的
  • StreamX部署详细步骤
  • java 正则表达式 所有的优先级
  • 做pc端网站平台网站做游戏活动
  • 【开发者导航】全自动 AI 视频创作与发布工具:LuoGen-agent
  • 网站 空间地址是什么苏州网站制作公司
  • Qt-多线程编程:互斥量 信号量
  • TERMSRV!WinStationLpcThread函数和TERMSRV!WinStationLpcHandleConnectionRequest函数分析