目录
- 问题产生背景
- 解决方案:实现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();//原来的itemitem.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_addrusername: nacospassword: nacos
3. 使用LoadBalancer
在配置类中创建一个带有负载均衡功能的 RestTemplate Bean。
@Configuration
public class RestTemplateConfig {// 使用@LoadBalanced注解赋予RestTemplate负载均衡的能力@LoadBalanced@Beanpublic 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();//原来的itemitem.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. 测试
多开几个依赖的服务,请求需要测试的接口,测试是否能通过服务名称调用服务,并且负载均衡。
请求发送到不同的服务上。