使用 负载均衡器 Ribbon 实现负载均衡

Posted Yan Yang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 负载均衡器 Ribbon 实现负载均衡相关的知识,希望对你有一定的参考价值。

内容

配置 Nacos 注册中心请看我的上篇博客:配置 Nacos 注册中心

一、远程调用负载均衡 Ribbon

1. 什么是负载均衡 (掌握)

  通俗的讲, 负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

2. 自定义负载均衡 (掌握)

  1. 通过idea再启动一个 shop-product 微服务,设置其端口为8082

  2. 通过nacos查看微服务的启动情况

  3. 修改 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;
        }
    }
    
  4. 启动两个服务提供者和一个服务消费者,多访问几次消费者测试效果


3. 基于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;
        }
    }
    
  3. 为了更直观看到请求是进行负载均衡了,我们修改一下ProductController代码

    @RestController
    @Slf4j
    public class ProductController {
        @Autowired
        private ProductService productService;
        @Value("${server.port}")
        private String port;
        //商品信息查询
        @RequestMapping("/product")
        public Product findByPid(@RequestParam("pid") Long pid) {
            log.info("接下来要进行{}号商品信息的查询", pid);
            Product product = productService.findByPid(pid);
            product.setPname(product.getPname()+",data from "+port);
            log.info("商品信息查询成功,内容为{}", JSON.toJSONString(product));
            return product;
        }
    }
    
  4. 调用订单保存的方法,查看日志.

  默认情况下,采取的是ZoneAvoidanceRule的策略,复合判断server所在区域的性能和server的可用性选择server


4. Ribbon支持的负载均衡策略

  Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接口为com.netflix.loadbalancer.IRule , 具体的负载策略如下图所示:

策略名策略描述实现说明
BestAvailableRule选择一个最小的并发请求的server逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRule先过滤掉故障实例,再选择并发较小的实例;使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRule根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权
RetryRule对选定的负载均衡策略机上重试机制。在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRule轮询方式轮询选择server轮询index,选择index对应位置的server
RandomRule随机选择一个server在index上随机,选择index对应位置的server
ZoneAvoidanceRule(默认)复合判断server所在区域的性能和server的可用性选择server使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

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

product-service: # 调用的提供者的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

总结

以上就是远程调用负载均衡 Ribbon 的总结了安全框架入门的总结了,代码仅供参考,欢迎讨论交流。
下篇博客:配置远程调用 Feign

以上是关于使用 负载均衡器 Ribbon 实现负载均衡的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用Ribbon 负载均衡自定义 Ribbon 配置禁用 Eureka 实现 Ribbon 调用)

SpringCloud系列五:Ribbon 负载均衡(Ribbon 基本使用Ribbon 负载均衡自定义 Ribbon 配置禁用 Eureka 实现 Ribbon 调用)

springCloud:Ribbon实现客户端侧负载均衡-自定义Ribbon配置

Ribbon-负载均衡策略

4-Ribbon负载均衡

SpringCloud无介绍快使用,Ribbon负载均衡工具与OpenFeign的使用(十五)