一、使用Ribbon实现客户端负载均衡
经过前文的讲解, 已经实现了微服务的 注册与发现。启 动各个微服务时 ,
Eureka Client会把自己的网络信息注册到 Eureka Server 上。世界似乎更美好了一些。
然而,这样的架构依然有一些问题,比 如负载均衡。一般来说,在生产环境中,各个微服务都会部署多个实例。那么服务消费者要如何将请求分摊到多个服务提供者实例上呢?
1.1 Ribbon 简介
ribbon 是 Netflix 发布的负载均衡器,它 有助于控制 HTTP 和 TCP 客户端的行为。为ribbon 配置服务提供者地址列表后 , Ribbon 就可基于某种负载均衡算法, 自动地帮助服务消费者去请求。 Ribbon 默认为我们提供了很多的负载均衡算法, 例如轮询、随机等。当然, 我们也可为 Ribbon 实现自定义的负载均衡算法。
在 Spring Cloud 中, 当 ribbon 与 Eureka 配合使用时, Ribbon 可自动从 Eureka Server 获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。
1.2 为服务消费者整合Ribbon
本节来为前文编写的电影微服务整合 Ribbon。
- 复制项目 consmuer 项目
- 为项目引入 Ribbon的依赖, Ribbon的依赖是:
由于前文中巳为电影微服务添加了spring-cloud-starter-eureka , 该依赖已经包含了spring-cloud-starter-ribbon , 所以尤须再次引入。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- 为 RestTemplate添加创LoadBalanced 注解。
回顾以前的代码,使用如下方法实例化 RestTemplate:
@SpringBootApplication
@EnableEurekaClient
public class SpringCustomerApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(SpringCustomerApplication.class, args);
}
}
为服务消费者整合 Ribbon两者对比可以发现,只 须 添加LoadBalanced 注解,就 可为 RestTemplate整合Ribban, 使其具备负载均衡的能力。
- 将 Controller 代码修改如下:
@RestController
public class MovieController {
private static final Logger logger = LoggerFactory.getLogger(MovieController.class);
@Autowired
private RestTemplate restTemplate;
@Value("${user.userServiceUrl}")
private String userServiceUrl;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/user/{id}")
public User findById(@PathVariable Long id) {
return this.restTemplate.getForObject("http://cloud/" + id, User.class);
//return this.restTemplate.getForObject("http://localhost:8000/" + id, User.class);
//return this.restTemplate.getForObject(this.userServiceUrl + id, User.class);
}
@GetMapping("/log_user_instance")
public void logUserInstance() {
ServiceInstance serviceInstance = this.loadBalancerClient.choose("cloud");
MovieController.logger.info("{}:{};{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
}
}
由代码可知, 我们将请求的地址改成了http://cloud/ 。
cloud 是用户微服务的虚拟主机名 ( virtual host name) , 当ribbon 和 Eureka 配合使用时, 会自动将虚拟主机名映射成微服务的网络地址。
在新增的logUserInstance( ) 方法中可使用LoadBalancerClient 的 API 更加直观地获取当前选择的用户微服务节点。
测试
1. 启动 discovery-eureka。
2. 启动 2 个或更多provinder实例。
3. 启动一个consumer。
4. 用consumer访问provinder,查看访问provinder的方式。
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=1qfejm37rewql