【Spring-Cloud-Alibaba】负载均衡Ribbon

Ribbon简介

源码下载 https://yangjing191928.coding.net/public/spring-cloud-alibaba/spring-cloud-alibaba/git/files/Ribbon

Ribbon是Spring Cloud的一个组件, 它可以让我们使用一个注解就能轻松的搞定负载均衡,内置多种负载均衡策略,内部负载均衡顶级接口为com.netflix.loadbalancer.IRule:具体策略如下

1:BestAvailableRule 选择一个最小的并发请求的server逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server

2:AvailabilityFilteringRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(activeconnections 超过配置的阈值)使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态

3:WeightedResponseTimeRule 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas 时,使用roubine策略选择server。

4:RetryRule 对选定的负载均衡策略机上重试机制在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server

5:RoundRobinRule 轮询方式轮询选择server轮询index,选择index对应位置的server

6:RandomRule 随机选择一个server 在index上随机,选择index对应位置的server
7:ZoneAvoidanceRule 复合判断server所在区域的性能和server的可用性选择server 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接 数过多的Server。

修改配置

在需要使用负载均衡的服务,修改配置(appliaction.yml)来调整Ribbon的负载均衡策略;例如:商品服务

server:
  port: 8081
spring:
  application:
    name: product-service
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
#ribbon要执行的负载均衡
product-service: # 调用的提供者的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.share.shareconter.configure.Nacosweight

RestTemplate的生成方法上添加@LoadBalanced注解

在调用服务的地方添加注解@LoadBalanced。例如我们这里是订单服务调用商品服务,则需要在订单服务的RestTemplate生成方法上面添加注解@LoadBalanced

package com.yangjing.config;

import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * <p>
 *
 * </p>
 *
 * @author:yangjing2@foreveross.com
 * @date:2021-04-16
 */
@Configuration
public class ApplicationConfig {
    @Bean
    @LoadBalanced //使用Ribbon负载均衡
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
}

改造方法

由于此处使用了Ribbon,所以调用方法需要改下。

说通俗点Ribbon将nacos上面注册的服务拉取到本地通过每个服务的服务名称可以替换之前写的ip+prot。

package com.yangjing.cotroller;

import com.alibaba.fastjson.JSON;
import com.yangjing.entity.Order;
import com.yangjing.entity.Product;
import com.yangjing.entity.UserDo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * <p>
 *
 * </p>
 *
 * @author:yangjing2@foreveross.com
 * @date:2021-04-16
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderCotroller {


    private static final String PRODUCT_URL = "http://localhost:8081/product/";
    private static final String PRODUCT_SERVER = "product-service";

    private static final String USER_URL = "http://localhost:8071/user/";
    private static final String USER_SERVER = "user-service";

    @Autowired
    RestTemplate restTemplate;

    //专门负责服务注册和发现的,我们可以通过它获取到注册到注册中心的所有服务
    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/prod/{pid}")
    public Order order3(@PathVariable("pid") Integer pid){
        log.info(">>>客户下单,调用商品微服务查询商品信息<<<");
        // 采用restTemplate调用
        Product product = restTemplate.getForObject(PRODUCT_URL+"getProduct/"+pid, Product.class);

        UserDo user = restTemplate.getForObject(USER_URL+"getUserInfo/"+pid,UserDo.class);
        log.info(">>商品信息,查询结果:" + JSON.toJSONString(product));
        log.info(">>用户信息,查询结果:" + JSON.toJSONString(user));
        Order order = new Order();
        order.setUid(user.getId());
        order.setUsername(user.getName());
        order.setPid(product.getId());
        order.setPname(product.getName());
        order.setPprice(product.getPrice());
        order.setNumber(1);
        return order;
    }


    /**
     * 使用nacos方式范问相关接口信息
     * @param pid
     * @return
     */
    @GetMapping("/prodNacos/{pid}")
    public Order prodNacos(@PathVariable("pid") Integer pid){
        log.info(">>>客户下单,调用商品微服务查询商品信息<<<");
        // 采用restTemplate调用
        //从nacos中获取服务地址 获取的是个list集群信息


        ServiceInstance userInstance = discoveryClient.getInstances("user-service").get(0);
        String userUrl = userInstance.getHost() + ":" +userInstance.getPort();
        log.info(">>从nacos中获取到的用户的微服务地址为:" + userUrl);
        UserDo user = restTemplate.getForObject("http://"+userUrl+"/user/getUserInfo/"+pid,UserDo.class);


        ServiceInstance productInstance = discoveryClient.getInstances("product-service").get(0);
        String productUrl = productInstance.getHost() + ":" +productInstance.getPort();
        log.info(">>从nacos中获取到的商品的微服务地址为:" + productUrl);
        Product product = restTemplate.getForObject("http://"+productUrl+"/product/getProduct/"+pid, Product.class);

        log.info(">>商品信息,查询结果:" + JSON.toJSONString(product));
        log.info(">>用户信息,查询结果:" + JSON.toJSONString(user));
        Order order = new Order();
        order.setUid(user.getId());
        order.setUsername(user.getName());
        order.setPid(product.getId());
        order.setPname(product.getName());
        order.setPprice(product.getPrice());
        order.setNumber(1);
        return order;
    }

    /**
     * 使用ribbon方式范问相关接口信息
     * @param pid
     * @return
     */
    @GetMapping("/prodRibbon/{pid}")
    public Order prodRibbon(@PathVariable("pid") Integer pid){
        log.info(">>>客户下单,调用商品微服务查询商品信息<<<");
        // 采用restTemplate调用
        //从nacos中获取服务地址 获取的是个list集群信息
        /*ServiceInstance productInstance = discoveryClient.getInstances("product-service").get(0);
        String productUrl = productInstance.getHost() + ":" +productInstance.getPort();
        log.info(">>从nacos中获取到的商品的微服务地址为:" + productUrl);
        Product product = restTemplate.getForObject("http://"+productUrl+"/product/getProduct/"+pid, Product.class);*/
        //此处我删除了用户相关,由于restTemplate 配置了ribbon注解,但是用户服务未配置ribbon,此处调用会报错
        log.info(">>从Ribbon中范问商品的微服务地址为:");
        String productUrl = "product-service";
        Product product = restTemplate.getForObject("http://"+productUrl+"/product/getProduct/"+pid, Product.class);

        log.info(">>商品信息,查询结果:" + JSON.toJSONString(product));
        
        Order order = new Order();
        order.setPid(product.getId());
        order.setPname(product.getName());
        order.setPprice(product.getPrice());
        order.setNumber(1);
        return order;
    }
}

我们将商品服务在启动一个

启动查看nacos是否注册成功(下图可以看到product-service注册了两个实例)

现在进行测试结果调用(执行两次)结果日志如下

Order  log
>>商品信息,查询结果:{"pid":1,"pname":"商品_1","pprice":1000.0,"stock":5000}
>>>客户下单,调用商品微服务查询商品信息<<<
>>从Ribbon中范问商品的微服务地址为:
>>商品信息,查询结果:{"pid":1,"pname":"商品_1","pprice":1000.0,"stock":5000}

product  log
商品信息查询成功,内容为{"pid":1,"pname":"商品_1","pprice":1000.0,"stock":5000}

product2  log
商品信息查询成功,内容为{"pid":1,"pname":"商品_1","pprice":1000.0,"stock":5000}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。 主要功能服务限流降级:默认支持 WebServlet、 WebFlux, OpenFeign、 RestTemplate、 Spring CloudGateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有Worker(schedulerx-client)上执行。阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值