问题 : 我们在订单服务里需要查询商品,如何发起远程调用商品服务查询出来?
方案1 : 使用 RestTemplate 实现远程调用
/**
* 订单查询产品
* @param pid 产品ID
* @param uid 用户ID
* @return
*/
@Override
public Order createOrder(Long pid, Long uid)
{
Order order = new Order();
/**
* 方案1 : 使用 RestTemplate 实现远程调用
*/
String url = "http://localhost:8081/products" + pid;
Product product = restTemplate.getForObject(url, Product.class);
// 商品
order.setPid(pid);
order.setProductName(product.getName());
order.setProductPrice(product.getPrice());
// 用户 模拟已经从数据库查到了用户
order.setUid(1L);
order.setUsername("xxx");
order.setNumber(1);
super.save(order);
return order;
}
缺点 : 不优雅,URL硬编码,虽然可以完成服务调用,但是如果IP地址或端口变化就需要手动改动,无法实现负载均衡
方案 2 : 使用 DiscoveryClient 注册中心API
/**
* 方案2 : 使用 discoveryClient 注册中心api
*/
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
ServiceInstance instance = instances.get(0);
int port = instance.getPort();
String host = instance.getHost();
String url = "http://" + host + ":" + port + "/products/" + pid;
方案3 : 负载均衡
启动多一个ProductServer,访问的时候就会随机选择两个服务其中一个,实现负载均衡
/**
* 方案3 : 负载均衡
*/
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
// 随机选择一个服务
int index = new Random().nextInt(instances.size());
ServiceInstance instance = instances.get(index);
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/products/" + pid;
Product product = restTemplate.getForObject(url, Product.class);
方案4 : 基于Ribbon实现负载均衡
在 RestTemplate 的生成方法上添加 @LoadBalanced注解
/**
* 方案4 : 使用Ribbon方式--带负载均衡
*/
String url = "http://product-service/products/" + pid;
Product product = restTemplate.getForObject(url, Product.class);
order.setProductName(product.getName());
order.setProductPrice(product.getPrice());
方案5 : 使用Feign实现负载均衡
添加依赖
<!--fegin组件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在启动类上添加@EnableFeignClients注解
添加IProductEfginService接口
@FeignClient(name = "product-service")
public interface IProductFeginService {
@GetMapping("/products/{pid}")
Product get(@PathVariable("pid") Long pid);
}
/**
* 方案5 : 使用 Feign 接口--负载均衡
*/
Product product = productFeignService.get(pid);