目录
- 问题产生背景
- 解决方案:实现LoadBalancer
- 1. 添加依赖
- 2. 配置文件
- 3. 使用LoadBalancer
- 4. 使用 RestTemplate 进行服务调用
- 5. 测试
问题产生背景
以下是一个购物车项目,通过调用外部接口获取商品信息,并添加到购物车中,这段代码中有一个问题:下面的代码中直接指定了调用的url,但如果存在多个resfood服务的url,就需要修改代码,如果存在多个,就无法保证调用的url来自不同的resfood服务,所以需要使用负载均衡。负载均衡可以实现将请求平均分配到各个服务上,避免出现一直调用同一个服务的情况。
@Value("${resfood.url}")
private String resfoodUrl;
/**
* 调用外部接口,获取商品信息,并添加到itemList中
* @param fid
* @param item
* @param itemList
*/
private void addItem(int fid, CartItem item, List<CartItem> itemList) {
String url = resfoodUrl+fid;
Map<String,Object> result = restTemplate.getForObject(url, Map.class);
System.out.println(result);
System.out.println(result.get("obj").getClass().getSimpleName());
// ObjectMapper是Jackson提供的一个类,用于将json数据转换为java对象
Resfood resfood = objectMapper.convertValue(result.get("obj"), Resfood.class);
// CartItem cartItem = new CartItem();
//原来的item
item.setFood(resfood);
//处理数量小于0的情况
if(item.getNum()<=0){
return;
}
// item.setNum(0);
// cartItem.setNum(item.getNum());
itemList.add(item);
}
解决方案:实现LoadBalancer
实现 Spring Cloud LoadBalancer 的前提条件:当前服务与当前服务调用的服务需要实现服务注册与发现。
1. 添加依赖
<!-- 负载均衡依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- nacos场景依赖:nacos客户端,用于将当前的微服务注册到nacos服务器中-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2. 配置文件
配置nacos
cloud:
nacos:
discovery:
# nacos的服务器地址,根据实际情况修改
server-addr: your_nacos_server_addr
username: nacos
password: nacos
3. 使用LoadBalancer
在配置类中创建一个带有负载均衡功能的 RestTemplate Bean。
@Configuration
public class RestTemplateConfig {
// 使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
4. 使用 RestTemplate 进行服务调用
在代码中,使用 LoadBalanced 的 RestTemplate 调用服务。
@Value("${resfood.url}")
private String resfoodUrl;
/**
* 调用外部接口,获取商品信息,并添加到itemList中
* @param fid
* @param item
* @param itemList
*/
private void addItem(int fid, CartItem item, List<CartItem> itemList) {
String url = resfoodUrl+fid;
Map<String,Object> result = restTemplate.getForObject(url, Map.class);
System.out.println(result);
System.out.println(result.get("obj").getClass().getSimpleName());
// ObjectMapper是Jackson提供的一个类,用于将json数据转换为java对象
Resfood resfood = objectMapper.convertValue(result.get("obj"), Resfood.class);
// CartItem cartItem = new CartItem();
//原来的item
item.setFood(resfood);
//处理数量小于0的情况
if(item.getNum()<=0){
return;
}
// item.setNum(0);
// cartItem.setNum(item.getNum());
itemList.add(item);
}
使用服务名称代替url,让Spring Cloud LoadBalancer自动选择合适的服务实例。
resfood:
url: http://res-food/resfood/getById/
5. 测试
多开几个依赖的服务,请求需要测试的接口,测试是否能通过服务名称调用服务,并且负载均衡。
请求发送到不同的服务上。