【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的环境下是可以的)
三件套:
- 导入依赖启动器
- 编写配置文件
- 启动配置
- 编写配置类(视情况而定)
- 导入依赖: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>
- 编写配置文件
- 启动配置
- 测试
LoadBalancer 负载均衡器
Ribbon和LoadBalancer相差不大,大多数内容一致;
LoadBalancer翻译过来的意思是 负载均衡器
正常使用
- 导入依赖
<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>
- 编写配置文件,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
- 配置类 ,使用注解
@LoadBalanced
@Configuration
public class ConfigBean { // 相当于 application.xml@Bean@LoadBalanced // 开启负载均衡功能public RestTemplate getRestTemplate() {return new RestTemplate();}
}
- 启动配置,检查问题,理论上是正常启用
扩展学习
- 更改服务消费方的访问地址,在最开始是使用RestTemplate的时候使用的
http://localhost:8001/,现在改成服务消费者的名字,之后再在Controller中将对应的url改成服务名http://SPRINGCLOUD-PROVIDER-DEPT;

- 再次开启所有的服务,查看三个集群是否都可以访问 服务供应者;

- 可以之后,访问消费者,使用消费者的Request请求路径访问,测试成功。

实现负载均衡
创建三个服务提供者,使用一样的数据库,数据库Database不一样;
每个服务(8001/8002/8003)都关联多个注册中心(7001/7002/7003);
这样子就会使LoadBalance 进行负载均衡,默认使用轮询调用的方式;
场景:
| serve | port | database | Eureka注册中心 |
|---|---|---|---|
| 8001 | 8001 | DB01 | 7001/7002/7003 |
| 8002 | 8002 | DB02 | 7001/7002/7003 |
| 8003 | 8003 | DB03 | 7001/7002/7003 |
这样子在注册中心调用分配的时候会调用8001,之后再调8002,8003;消费者方发出请求后也会从7001/7002/7003中选择一个合适的节点,进行调用;
默认理解的是:
服务消费者 >> 随机的Eureka注册中心 >> 随机的server服务器 >> 返回调用内容数据;
特别的占内存,测试时启动的微服务 使用 3~5个就可以了
自定义负载均衡的算法(LoadBalancer)
详细流程
- 确保依赖已完全导入
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 实现自定义负载均衡器
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);}
}
- 注册 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 时才使用随机算法,其他服务仍用默认轮询算法。
- 使用
@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的客户端;只需要创建一个接口,就可以添加注解;
面向接口编程是很多开发时候的规范,调用微服务访问有两种方法:
- 微服务名字(Ribbon/LoadBalance)
- 接口和注解(Feign)
Feign的特点
- 声明式 REST 客户端:用接口 + 注解代替手动写 RestTemplate 或 WebClient
- 自动集成负载均衡:通过 @LoadBalanced 机制,结合服务注册中心(如 Eureka/Nacos)实现服务调用。
- 底层依赖:Spring Cloud OpenFeign(基于 Netflix Feign 封装,但已移除 Ribbon)。
Feigen的使用
前提准备
- 新建一个service在api中

- 新建一个Feign的服务,copy 80消费端的内容
- 删除原来Ribbon/LoadBalance的内容
- 在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);
}
- 在该service中调用到Mapping是服务提供者那边的,需要再加一个注解
@Feign,在这个地方的value是在Eureka中设置的服务名
使用流程
组件导入流程:
- 导入依赖
- 编写配置文件
- 启动配置类
- 编写配置类
导入依赖
- 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思想对其进行了封装。
启动配置,进行测试
- 在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);}
}
- 服务注册启动成功,Eureka页面正常显示,调用内容正常显示;
- 服务提供者启动正常,直接调用提供者Service的DB查询正常;
- 服务消费者(Feign组件)启动正常,调用URL显示内容查询正常;

