参考:https://blog.csdn.net/qwe86314/article/details/98027648
2个provider,1个consumer
nginx为服务端负载均衡
客户端负载均衡。
二、自动负载均衡
使用 @Loadbalancer 实现负载均衡
在SpringCloud中实现负债均衡非常的简单,只需要在RestTemplate上加入一个@LoadBalanced注解就可以了如下
@Bean
@LoadBalanced
RestTemplate loadBalancer() {
return new RestTemplate();
}
RestTemplate就有了负载均衡的能力了,我们继续在consumer 中的UserHelloController中加入hello2接口如下:
@Autowired
@Qualifier("loadBalancer")
RestTemplate loadBalancer;
@GetMapping("/hello2")
public String hello2(String name) {
String s = loadBalancer.getForObject("http://provider/hello?name={1}", String.class, name);
return s;
}
由于现在项目中存在两个 RestTemplate 的实例,因此这里我加了 @Qualifier(“loadBalancer”) 注解,表示通过名称来查找 RestTemplate 的实例
此时注入进来的 RestTemplate 实例自动就具备了负载均衡功能,但需要注意的是这里的请求地址,原本的 Host+":"+Port 被微服务名称所替代
这里使用了 provider 来代替 Host+":"+Port ,在真正的请求发起时,会通过拦截器将请求拦截下来,然后将 provider 换成一个具体的服务地址。
请求失败重试
具备了负载均衡功能的 RestTemplate 也可以开启请求重试功能。
在微服务调用的过程中,由于网络抖动等原因造成了访问失败,这个时候如果直接就认定访问失败显然是不划算的,可以多尝试几次,多次尝试之后,如果还是请求失败,再判定访问失败。
如果开发者加入了该依赖,但是又不想开启请求失败重试功能,可以在application.properties中添加如下配置:
spring.cloud.loadbalancer.retry.enabled=false
至于请求失败重试的次数以及切换实例的次数
# 最大的重试次数,不包括第一次请求
ribbon.MaxAutoRetries=3
# 最大重试server的个数,不包括第一个 server
ribbon.MaxAutoRetriesNextServer=1
也可以指定是否开启任何异常都重试:
ribbon.OkToRetryOnAllOperations=true
一、手动负载均衡
consumer 获取 provider 地址时,我们一直采用了 DiscoveryClient 来手动获取。
provider 代码:
@RestController
public class HelloController {
@Value("${server.port}")
Integer port;
@GetMapping("/hello")
public String hello(String name) {
return "hello" + name + ":" + port;
}
}
provider的application.yml配置如下:
spring:
application:
name: provider
server:
port: 4001
eureka:
client:
service-url:
defaultZone: http://localhost:1111/eureka
运行provider
nohub java -jar provider-0.0.1-SNAPSHOT.jar --server.port= 4001 &
nohub java -jar provider-0.0.1-SNAPSHOT.jar --server.port= 4002 &
consumer 用来去调用provider 的服务,DiscoveryClient 从 eureka 上获取所有的provider实例,这些获取到的实例保存到一个list集合中,所以这个轮询就是从list中取出ServiceInstance 实例,组装成相关的实例去运行.
动态改变host+port去进行负载均衡。
@RestController
public class UserHelloController {
@Autowired
DiscoveryClient discoveryClient;
@Autowired
RestTemplate restTemplate;
int count = 0;
@GetMapping("/hello")
public String hello(String name) {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(count % list.size());
count ++;
String host = instance.getHost();
int port = instance.getPort();
String s = restTemplate.getForObject("http://" + host + ":" + port + "/hello?name={1}", String.class, name);
return s;
}