SpringCloud LoadBalancer是SpringCloud官方自己提供的客户端负载均衡器,用来替代Ribbon的。因为netfilx停更了,所以SpringCloud官方就自己开发了一块客户端负载均衡器这边用来替代Ribbon。但是目前是没有办法去替代Ribbon的。因为它目前的负载均衡算法还很少。
SpringCloud在早期是把Ribbon当做它的负载均衡器,在SpringCloud2021版的时候就移除了Ribbon,改用Loadbalancer为默认的负载均衡器
<!--nacos的管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud loadbalancer 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>
使用LoadBalancer实现负载均衡
配置文件
注意是每个服务都需要配置此文件.
spring:
# 添加服务名称
application:
name: orderservice
cloud:
# 负载均衡配置
loadbalancer:
ribbon:
#禁用ribbon
enabled: false # 爆红黄线的话不设置也可以
#配置nacos的服务地址
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
配置负载均衡
使用@LoadBalanced注解将RestTemplate配置为具有负载均衡功能:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
负载均衡-随机策略
注意,此方法不需要添加@Configuration注解
public class CustomLoadBalancerConfiguration {
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
然后在配置类或者主启动类中使用@LoadBalancerClient注释
@SpringBootApplication
//name写微服务的服务名称,configuration写配置文件的类
@LoadBalancerClient(name = "userservice", configuration = CustomLoadBalancerConfiguration.class)
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
/**
* 创建RestTemplate对象并注入spring容器
*
* @return
*/
@Bean
@LoadBalanced//注册中心中拉取服务的实例列表,并且使用loadbalancer实现负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
注意此随机策略如果是环境隔离模式下则不生效,我想使用spring.cloud.loadbalancer.type=random发现yaml报错,欢迎大佬补充。
测试Nacos设置负载均衡(轮询),让其优先寻找自己同集群下的服务
实现方法是使用的环境隔离。
此处用一个案例演示,查询订单列表并返回用户的信息,订单服务和用户服务是两个服务:
订单查询的请求地址是:http://localhost:8080/order/{id}
端口号8080订单服务的nacos的yaml配置如下:
spring:
# 添加服务名称
application:
name: orderservice
cloud:
# 负载均衡配置
loadbalancer:
ribbon:
#禁用ribbon
enabled: false
#配置nacos的服务地址
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
cluster-name: HZ # 集群名称:杭州
group: test-group # 服务的分组名称
订单服务的业务代码:
@Service
public class OrderService {
@Resource
private OrderMapper orderMapper;
@Resource
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
//请求地址
String url = "http://userservice/user/" + order.getUserId();
/**
* 2.利用RestTemplate发送http请求,查询用户
* 参数:
* 1.发送请求的url地址
* 2.返回值类型,默认是json格式
*/
User user = restTemplate.getForObject(url, User.class);
order.setUser(user);
// 4.返回
return order;
}
用户查询的请求地址是:
http://localhost:8081/user/{id}
http://localhost:8082/user/{id}
http://localhost:8083/user/{id}
端口号8081和8082的用户服务nacos的yaml配置如下
spring:
# 添加服务名称
application:
name: orderservice
cloud:
# 负载均衡配置
loadbalancer:
ribbon:
#禁用ribbon
enabled: false
#配置nacos的服务地址
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
cluster-name: HZ # 集群名称:杭州
group: test-group # 服务的分组名称
8083的用户服务nacos的yaml配置如下:
spring:
# 添加服务名称
application:
name: orderservice
cloud:
# 负载均衡配置
loadbalancer:
ribbon:
#禁用ribbon
enabled: false
#配置nacos的服务地址
nacos:
discovery:
server-addr: localhost:8848 # nacos服务地址
cluster-name: SH # 集群名称:杭州
group: test-group01 # 服务的分组名称
注意,8083和8081、8082的集群名称和服务的命名空间不同。
这是因为当Spring Cloud应用程序调用服务时,它会首先查找具有相同Group(分组)和Cluster名称的服务,并尝试通过负载均衡算法选择其中一个。如果没有找到具有相同Group和Cluster名称的服务,则会使用默认的负载均衡算法来选择服务。
注意:但是这样设置后随机策略就不会生效了(他还是采用的轮询方案,至于随机负载均衡方案我暂时还没搞懂)。
用户的查询业务代码:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User queryById(Long id) {
return userMapper.findById(id);//此方法内的SQL是"select * from tb_user where id = #{id}"
}
}
然后开始测试:
先启动订单服务和两个集群名称为HZ(杭州)集群分组为test-group的用户服务:
![](https://img-blog.csdnimg.cn/img_convert/33e0c2491bd3c430a9c9ec48be002aec.png)
然后启动集群名称为SH(上海)集群分组为test-group01的用户服务:
![](https://img-blog.csdnimg.cn/img_convert/ccc8d13dcd691fa371eb94ebcbcc56d8.png)
服务全部启动成功,去nacos管理页面查看:
![](https://img-blog.csdnimg.cn/img_convert/ad028ac00548dccbd22e1e35709adab8.png)
然后查看三个userservice的集群:
![](https://img-blog.csdnimg.cn/img_convert/f5d3eeac73faf0097aefb764caf26233.png)
![](https://img-blog.csdnimg.cn/img_convert/fc7946ff57ed22af78bb12607fefce73.png)
ok,环境准备成功无异常,开始发送请求测试,它会首先查找具有相同Group(分组)和Cluster名称的服务,并尝试通过负载均衡算法选择其中一个,由于我们订单服务和8081、8082的两个用户服务的Group(分组)和Cluster名称的服务相同,所以我们发送的请求8083用户服务并不会接收到。
我们连续发送6个请求查看控制台日志:
![](https://img-blog.csdnimg.cn/img_convert/d037f98c5041c6e6dfdc240ff7649f9c.png)
可以看到订单服务被请求了六次,再来查看用户服务。
8081端口用户服务结果:
![](https://img-blog.csdnimg.cn/img_convert/80d86ef2b6a4eebfbd0b95be8833f88b.png)
8082端口用户服务结果:
![](https://img-blog.csdnimg.cn/img_convert/6918ac38f9ac889cfe71e35705c428e6.png)
8083端口用户服务结果:
![](https://img-blog.csdnimg.cn/img_convert/67c011bfd61613aa1d7122e08def3b04.png)
可以看到nacos负载均衡让其优先寻找自己同集群下的服务实现成功(但是随机负载均衡策略暂时还没研究明白,欢迎大佬补充)。