@[toc]
Spring cloud 使用 Ribbon 来实现客户端负载均衡
前言
在Spring cloud 中当统一类型多个服务开始注册到服务注册中心中,次数服务即是集群 消费端(客户端)消费的时候需要进行选择调用服务。
服务注册 点击
Spring cloud 中默认调用是依赖eureka 的 ribbon 来实现客户端负载均衡策略
我们先来注册两个服务
然后采用 ribbon 来实现负载均衡策略
ribbon依赖
ribbon 依赖eureka进行实现负载均衡,所以我们不需要导入包,默认在eureka 依赖中存在
实现负载均衡
仅仅需要在 上面增加 @LoadBalanced注解即可
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaclientApplication {
//开启负载均衡
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(EurekaclientApplication.class, args);
}
}
消费调用
@RestController
public class GetUserController {
@Autowired
RestTemplate restTemplate;
//服务发现对象
@Autowired
DiscoveryClient discoveryClient;
@RequestMapping("get")
public User getUser(int id){
//user微服务的名字 用来想此服务发送请求
String servceId = "user-server";
String url = "http://" + servceId + "/getUser?id=" + id;
System.out.println(url + " = " + url);
User forObject = restTemplate.getForObject(url, User.class);
}
测试
打印每次调用的 url 和 端口
@Autowired
LoadBalancerClient loadBalancerClient;
for (int i = 0; i < 100; i++) {
ServiceInstance choose = loadBalancerClient.choose("user-server");
System.out.println("第 " + (i+1) + "次 执行 " + choose.getPort() + choose.getUri());
}
return forObject;
}
结果如下
我们可以看到每次是轮训调用,一个接着一个循环调用请求(总共2个服务)。
默认策略
ribbon自动配置中没有指定配置策略默认实现轮训策略
设置随机策略
设置负载均衡为随机策略
serviceId.ribbon.NFLoadBalancerRuleClassName=自定义的负载均衡策略类
在配置文件里面配置
user-server: # 这个配置是请求的服务名
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
或者通过硬编码方式
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule() {
// 负载均衡规则,改为随机
return new RandomRule();
}
默认情况下 配置文件大于硬编码方式
测试结果
每次请求随机访问
自定义策略
ribbon 默认通过 IRule 接口来实现负载均衡策略,默认实现通过ZoneAvoidanceRule 轮训负载
- 结构图
另外自带的负载均衡策略
不依赖eureka实现Ribbon负载均衡
ribbon可以脱离eureka实现负载均衡如下
#取消Ribbon使用Eureka
ribbon.eureka.enabled=false
#配置Ribbon能访问 的微服务节点,多个节点用逗号隔开
user-server.ribbon.listOfServers=localhost:6869,localhost:6870
最后可能会遇到的问题
可能会报错
springcloud ribbon实现负载均衡的时候,提示Request URI does not contain a valid hostname: http://PRODUCT_SERVICE/
原因是因为服务名不能 有 下划线
代码地址 传送门