说明
在之前的 eureka-demo
工程(SpringCloud_Eureka.md
有步骤) 中,我们启动了一个 user-service
,然后通过 DiscoveryClient
来获取服务实例信息,然后获取 ip
和端口来访问
但是实际环境中,我们往往会开启很多个 user-service
的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?
一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。
不过 Eureka
中已经帮我们集成了负载均衡组件:Ribbon
,简单修改代码即可使用。
demo
启动3个 user-service
实例,8081
、8082
、8083
,启动方式参考 SpringCloud_Eureka.md
中启动多个 eureka-service
Eureka
监控面板
接下来,消费者会拉取到两个user-service的实例,需要利用负载均衡算法,从中选择一个。
因为Eureka中已经集成了Ribbon,所以我们无需引入新的依赖。直接修改代码:
在 user-consumer
的启动类中,RestTemplate
的配置方法上添加@LoadBalanced
注解:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
修改 user-consumer
中的UserController
中的调用方法,不再手动获取 ip
和端口,而是直接通过服务名称调用
package com.it.learn.controller;
import com.it.learn.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("consumer")
public class UserController {
// 发送基于http协议的远程过程调用(2个服务器相互调用)
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/{id}")
public User findUserById(@PathVariable("id") Long id){
String url = "http://user-service/user/" + id;
// 查询
User user = restTemplate.getForObject(url, User.class);
return user;
}
}
访问页面 http://localhost:8080/consumer/5,查看结果
可以双击 shift
键找到 RibbonLoadBalancerClient
类,在此位置打断点,查看 user-consumer
是否是轮询的方式调用 user-service
请求链路分析
流程:
- 1)用户发送请求到consumer-service
- 2)consumer-service根据服务id(user-service)去eureka拉取服务列表
- 3)eureka返回服务列表信息到consumer-service,consumer缓存服务列表,这样下次请求就无需拉取了
- 4)利用Ribbon的负载均衡策略,从列表中选择一个服务
- 5)向选中的服务发送请求
demo
ribbon-demo