您的位置:首页 > 编程语言 > Java开发

SpringCloud -- ribbon

2020-06-30 09:38 100 查看

ribbon

  • 配置详解
  • Ribbon

    搭建提供者集群

    在之前的Eureka中我们搭建了一个简单的服务调用,其中就有一个服务提供者,我们需要做的就是将服务者提供者在创建一份一样的;

    具体搭建就不明说;可以参考Eureka篇章,不过这里为了方便将原本消费者的端口8082改为了8083,新的服务提供者改为了8082;(创建新的服务者后,注意应用名称取一样的,不需要修改)

    完成后打开eureka可以发现

    服务者是一个集群了

    开启负载均衡

    在完成服务提供者集群搭建后;这个时候我们需要改造我们的消费者

    1. 修改restTemplate
    @SpringBootApplication
    @EnableDiscoveryClient // 开启Eureka客户端
    public class ConsumerApplication {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
    return new RestTemplate();
    }
    
    public static void main(String[] args) {
    SpringApplication.run(ConsumerApplication.class, args);
    }
    }

    我们要做的就是在restTemplate上面加上一个注解@LoadBalanced;这就代替开启了负载均衡了;

    1. 修改查询代码
    @RestController
    @RequestMapping("consumer")
    @Slf4j
    public class ConsumerController {
    
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    //springcloud中的服务发现
    private DiscoveryClient discoveryClient;
    
    @GetMapping("{id}")
    public User queryById(@PathVariable("id") Long id){
    // 根据服务id(spring.application.name),获取服务实例列表
    List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
    // 取出一个服务实例
    ServiceInstance instance = instances.get(0);
    // 从实例中获取host和port,组成url
    /*        String url = String.format("http://%s:%s/user/%s", instance.getHost(), instance.getPort(), id);
    User user = restTemplate.getForObject(url, User.class);*/
    String url = "http://user-service/user/" + id;
    User user = restTemplate.getForObject(url, User.class);
    return user;
    }
    }

    这时候注释掉原来的从注册中心获取地址的代码,将url换成服务的名称即可;

    1. 启动程序
      服务的时候会发现,启动依旧成功

    实现原因

    在使用@LoadBalanced 注解以后,springCloud底层开始启用了负载均衡,这个时候不会再通过 DiscoveryClient 来发现服务的地址,而是通RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

    源码跟踪

    在其底层源码中可以发现会拦RestTemplate的请求
    继续跟入execute方法:发现获取了8082端口的服务

    负载均衡器根据负载均衡算法选择一个适合的服务地址信息来替换url中的服务名称

    源码位置:

    注:在配置集群后,eureka中也是有集成负载均衡的依赖;所以如果配置集群后不用springcloud @LoadBalanced注解,eureka本身也会用负载均衡来调用服务

    总结

    配置详解

    负载均衡的策略比较多,默认使用的是轮询
    SpringBoot也帮我们提供了修改负载均衡规则的配置入口:

    user-service:
    ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

    格式是:

    {服务名称}.ribbon.NFLoadBalancerRuleClassName
    ,值就是IRule的实现类。

    注:

    • BestAvailableRule public class BestAvailableRule extends - p-- --ClientConfigEnabledRoundRobinRule 选择一个最小的并发请求的server 逐个考察Server,如果Server被tripped了,则忽略,在选择其中–ActiveRequestsCount最小的server
    • AvailabilityFilteringRule public class AvailabilityFilteringRule extends PredicateBasedRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
    • WeightedResponseTimeRule public class WeightedResponseTimeRule extends RoundRobinRule 根据相应时间分配一个weight,相应时间越长,weight越小,被选中的可能性越低。 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成statas时,使用roubine策略选择server。
    • RetryRule public class RetryRule extends AbstractLoadBalancerRule 对选定的负载均衡策略机上重试机制。 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
    • RoundRobinRule public class RoundRobinRule extends AbstractLoadBalancerRule roundRobin方式轮询选择server 轮询index,选择index对应位置的server
    • RandomRule public class RandomRule extends AbstractLoadBalancerRule 随机选择一个server 在index上随机,选择index对应位置的server
    • ZoneAvoidanceRule public class ZoneAvoidanceRule extends - PredicateBasedRule 复合判断server所在区域的性能和server的可用性选择server 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

    附加:

    Ribbon默认是采用懒加载,即第一次访问时才会去创建负载均衡客户端。往往会出现超时。如果需要采用饥饿加载,即项目启动即创建,可以这样配置:

    ribbon:
    eager-load:
    enabled: true
    clients: user-service
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: