Ribbon是Netflix客户端的负载均衡器,可对HTTP和TCP客户端的行为进行控制。为Ribbon配置服务器提供者地址后,Ribbon就可以基于某种负载均衡算法自动帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,也可以为Ribbon实现自定义的负载均衡算法。关于详细的负载均衡算法,请看这篇文章:
https://blog.csdn.net/qq_43753724/article/details/119836860?spm=1001.2014.3001.5501
要将Ribbon包含在项目中,请添加如下依赖:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
dependency>
在Ribbon中有以下几个重要概念:
Ribbon提供了以下几种Rule:
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
dependency>
说明:
1.如果使用的是eureka client 和 consul client,无须引入依赖,因为在eureka,consul中默认集成了ribbon组件
2.如果使用的client中没有ribbon依赖需要显式引入上述依赖
这里注册两个订单服务(模仿订单服务集群),一个9990端口,一个9999端口
使用**@Value**注解将端口号注入到port变量里面,就可以在别的服务调用的时候在页面上打印出提供服务的服务器节点的端口,方便观察负载均衡的结果。
访问8500端口即可查看服务注册中心中所注册的订单服务ORDERS
这样我们就可以在需要使用的地方直接注入了。
BeansConfig.java
package com.baizhi.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration //代表这是一个SpringBoot配置类 spring.xml 工厂 创建对象 bean id class=""
public class BeansConfig {
//工厂中创建RestTemplate
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@Autowired //服务注册与发现的客户端对象
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("user")
public String invokeDemo(){
log.info("user demo...");
//2、使用Ribbon+RestTemplate实现负载均衡调用 1.DiscoveryClient 2.LoadBalanceClient 3.@LoadBalance
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("ORDERS");
serviceInstances.forEach(serviceInstance -> {
log.info("服务主机:{} 服务端口:{} 服务地址:{}",serviceInstance.getHost(),serviceInstance.getPort(),serviceInstance.getUri());
});
String result = new RestTemplate().getForObject(serviceInstances.get(0).getUri() + "/order", String.class);
return "OK"+result;
}
在用户服务中调用订单服务:http://localhost:8888/user
由于我们使用了(serviceInstances.get(0).getUri()
,所以一致使用的是订单服务列表中的第一台节点,即9990端口的节点。可以看到,这里并没有自动帮我们做负载均衡,需要我们自己去做负载均衡的算法。
@RestController
@Slf4j
public class UserController {
@Autowired //服务注册与发现的客户端对象
private DiscoveryClient discoveryClient;
@Autowired //负载均衡客户端对象
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("user")
public String invokeDemo(){
log.info("user demo...");
//3、使用LoadBalancerClient进行服务调用
ServiceInstance serviceInstance = loadBalancerClient.choose("ORDERS"); //默认轮询
log.info("服务地址:{} 服务主机:{} 服务端口:{}",serviceInstance.getUri(),serviceInstance.getHost(),serviceInstance.getPort());
String result = restTemplate.getForObject(serviceInstance.getUri() + "/order", String.class);
return "OK"+result;
}
}
这种方式的负载均衡算法默认使用的是轮询方式。即第一次调用9990端口的节点,第二次就调用9999端口的节点,以此类推。
//工厂中创建RestTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
@RestController
@Slf4j
public class UserController {
@Autowired //服务注册与发现的客户端对象
private DiscoveryClient discoveryClient;
@Autowired //负载均衡客户端对象
private LoadBalancerClient loadBalancerClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("user")
public String invokeDemo(){
log.info("user demo...");
//4、使用@LoadBalance注解 作用:可以让对象具有ribbon负载均衡特性
String result = restTemplate.getForObject("http://ORDERS/order", String.class);
return "OK"+result;
}
}
默认还是轮询的负载均衡算法,但是由于我们在配置文件中添加了
#修改用户服务调用订单服务默认负载均衡策略不再使用轮询 使用随机策略
ORDERS.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
所以,现在使用的负载均衡算法是随机法
格式:
id.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule