【服务与服务之间的调用】 负载均衡ribbon

实现自定义负载均衡

1.修改 OrderServiceImpl 的代码,实现负载均衡

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public Order createOrder(Long productId,Long userId) {
        log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);
        //从nacos中获取服务地址
        //自定义规则实现随机挑选服务
        List<ServiceInstance> instances = discoveryClient.
                getInstances("product-service");
        int index = new Random().nextInt(instances.size());
        ServiceInstance instance = instances.get(index);
        String url = instance.getHost()+":"+instance.getPort();
        log.info(">>从nacos中获取到的微服务地址为:" + url);
        //远程调用商品微服务,查询商品信息
        Product product = restTemplate.getForObject(
                "http://"+url+"/product/"+productId,Product.class);
        log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));
        //创建订单并保存
        Order order = new Order();
        order.setUid(userId);
        order.setUsername("叩丁狼教育");
        order.setPid(productId);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderDao.save(order);
        log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));
        return order;
    }
}

基于Ribbon实现负载均衡

Ribbon是Spring Cloud的一个组件, 它可以让我们使用一个注解就能轻松的搞定负载均衡

  1. 在RestTemplate 的生成方法上添加@LoadBalanced注解
@Bean
@LoadBalanced //贴上该注解
public RestTemplate restTemplate(){
	return new RestTemplate();
}

2.修改OrderServiceImpl服务调用的方法

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public Order createOrder(Long productId,Long userId) {
        log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);
        //远程调用商品微服务,查询商品信息
        Product product = restTemplate.getForObject(
                "http://product-service/product?productId="+productId,Product.class);
        log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));
        //创建订单并保存
        Order order = new Order();
        order.setUid(userId);
        order.setUsername("叩丁狼教育");
        order.setPid(productId);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderDao.save(order);
        log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));
        return order;
    }
}

我们可以通过修改配置来调整Ribbon的负载均衡策略,在order-server项目的application.yml中增加如下配置:

product-service: # 调用的提供者的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机选择一个server

com.netflix.loadbalancer.RoundRobinRule 轮询选择一个server 等等其他策略

远程调用Feign

​ Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务

一样简单, 只需要创建一个接口并添加一个注解即可。

​ Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负载均衡的效果。

1 .在shop-order-server项目的pom文件加入Fegin的依赖

<!--fegin组件-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.在启动类OrderServer.java上添加Fegin的扫描注解,注意扫描路径(默认扫描当前包及其子包)

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServer {
    public static void main(String[] args) {
        SpringApplication.run(OrderServer.class,args);
    }
}

3 .在shop-order-server项目中新增接口ProductFeignApi

//name的名称一定要和订单服务的服务名保持一致
@FeignClient(name = "product-service")
public interface ProductFeignApi {
    @RequestMapping("/product")
    public Product findByPid(@RequestParam("pid") Long pid);
}

4 .修改OrderServiceImpl.java的远程调用方法

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private ProductFeignApi productFeignApi;
    @Override
    public Order createOrder(Long productId,Long userId) {
        log.info("接收到{}号商品的下单请求,接下来调用商品微服务查询此商品信息", productId);
        //远程调用商品微服务,查询商品信息
        Product product = productFeignApi.findByPid(productId);
        log.info("查询到{}号商品的信息,内容是:{}", productId, JSON.toJSONString(product));
        //创建订单并保存
        Order order = new Order();
        order.setUid(userId);
        order.setUsername("叩丁狼教育");
        order.setPid(productId);
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderDao.save(order);
        log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));
        return order;
    }
}
  1. 重启服务,并验证.

Feign的重要属性

超时配置

feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000

重试次数配置

https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-file-sample-clientproperties

product-service: # 调用的提供者的名称
  ribbon:
    MaxAutoRetries: 0
    MaxAutoRetriesNextServer: 0

ribbon负载均衡原理

1.通过反射能够获取到你传递过来参数,url = http://product-service/get?id=xxx
2.按照规则去进行切割,切割product-service服务的名字.
3.在我本地中是有服务名对应着那些节点的信息,product-service 130.131:8081 130.131:8083
4.根据你配置负载均衡策略选择-个节 点信息把服务名给替换掉htt://192.168.130.131:8081/get?id=xx
5.使用RestTemplate去发送请求

feign调用原理

1.通过反射拿到我代理类实现的接口ProductFeignApi
2.通过反射拿到接口,上注解@FeignClient注解,并且把注解中值取出来, product-service
3.通过反射拿到接口中方法,并且拿到接口中方法上的注解@RequestMapping,并且把值给取出来, /get
4.把方法中参数注解中的值也会取出来id
5.拼接路径ht:/product-service/get?id=xx
6.根据服务名上本地去找product-service对应节点信息localhost:8081 localhost:8083
7.根据你配置ribbon的负载均衡策略选择一个节点localhost:8081
8.把服务名称替换成htt://ocalhost:8081/get?id=xx
9.使用RestTemplate发送请求

你可能感兴趣的:(负载均衡,微服务,java,spring,cloud)