zoukankan      html  css  js  c++  java
  • Ribbon导航

    简介

    最近都在弄微服务的东西,现在来记录下收获。我从一知半解到现在能从0搭建使用最大的感触有两点

    1.微服务各大组件的版本很多,网上很多博客内容不一定适合你的版本,很多时候苦苦琢磨都是无用功

    2.网上博客参差不齐,有些甚至错误的。更离谱的是,好的文章阅读量除非高出天际,不然就都很低,比那些复制粘贴,随便应付的都低(这个搜索推荐算法不知道基于什么的)

    通过这段时间学习,我觉得最重要是从好的博客入手,先不要着急怎么组件怎么使用,而是先了解组件的作用,大概的原理,然后才是使用,这样搭建和尝试的过程中才能更好的定位问题,最后再次回到原理和一些实际问题的处理(不知道实际问题怎样的,直接搜那个组件的面试题往往效果最好)

    接下来的内容,都以导航的形式展现给大家(毕竟优秀的轮子很多,直接看大佬写的不香嘛),再顺带提些自己的理解

    传送门

    更多微服务的介绍可点击下方链接

    微服务介绍Nginx导航Nacos导航Gateway导航Ribbon导航Feign导航Sentinel导航

    博主微服务git练手项目:https://github.com/NiceJason/SpringCloudDemo

    Ribbon简介

    ribbon简介:https://blog.csdn.net/f641385712/article/details/104761814

    说到负载均衡,常指两个地方:Ng负载均衡和服务负载均衡。服务负载均衡指SpringCloudGateWay网关开始,到里面的各种Server服务,都是基于Ribbon进行负载均衡的。

    SpringCloud下的Ribbon

    参考资料:https://louluan.blog.csdn.net/article/details/83060310

            文章讲了Ribbon几大核心组件的作用和负载均衡的过程,当然总的流程是这样的,但是和具体的组件结合时候会有点变化,例如和Nacos结合时,Nacos并没有实现自己的IPing,而是把这个定时检测都去掉了,换成了定时刷新服务列表(自身每10秒刷新),外部Ribbon没变,一样是每30秒刷新一次

           在文章开头也讲了Feign和Ribbon结合,所以重试机制默认Feign是关闭的(具体代码里可以看到),调用的是Ribbon。同理可以推测出,和Ribbon整合的组件(如SpringCloudGateaWay)他们的重试机制应该都是基于Ribbon,因此Ribbon的配置十分重要

    Ribbon的重试机制

    参考资料:https://blog.csdn.net/east123321/article/details/82385816(这篇文章的评论也能看看)

    想要Ribbon开启重试,需要导入SpringRetry包,因为Ribbon重试先关的类和拦截器都依赖RetryTemplate.class,代码里写着ConditionOnClass(RetryTemplate.class)。

    这个太重要了,不知道为什么很多博客都没提及,没有依赖此包Ribbon并不会报错和提示,所以找了很久没不知道什么问题

       <!--重试依赖-->
            <dependency>
                <groupId>org.springframework.retry</groupId>
                <artifactId>spring-retry</artifactId>
            </dependency>

    这里的版本应该依赖于Springboot而不是自己去指定

    ribbon:
      ReadTimeout: 15000
      ConnectTimeout: 5000
      MaxAutoRetries: 1 #同一台实例最大重试次数,不包括首次调用
      MaxAutoRetriesNextServer: 1 #重试负载均衡其他的实例最大重试次数,不包括首次调用
      OkToRetryOnAllOperations: false  #是否所有操作都重试,改为true要注意接口是否实现了幂等性
    重试次数: MaxAutoRetries + MaxAuthRetriesNextServer * ( 1 + MaxAutoRetries) ,这里面的1是指MaxAutoRetries首次调用
     
    总共调用次数为:(1+ MaxAutoRetriesNextServer)*(1 + MaxAutoRetries ),两边的1都是首次调用,拆开了其实就是上面的公式少了1次
     
    如果不配置ribbon的重试次数,默认重试1次
    注意:
    默认情况下,GET方式请求无论是连接异常还是读取异常,都会进行重试
    非GET方式请求,只有连接异常时,才会进行重试

    Ribbon的配置

    ############## ribbon配置 ##############
    #想要更好的理解Nacos和Ribbon的结合,关闭饥饿加载,打断点
    ribbon.eager-load.enabled=true
    ## 从注册中心刷新servelist的时间 默认30秒,单位ms
    ribbon.ServerListRefreshInterval=15000
    ## 请求连接的超时时间 默认1秒,单位ms。更改这个值时,需要考虑熔断时间是否要重新计算
    ribbon.ConnectTimeout=1000
    ## 请求处理的超时时间 默认1秒,单位ms。更改这个值时,需要考虑熔断时间是否要重新计算
    ribbon.ReadTimeout=10000
    #同一台实例最大重试次数,不包括首次调用。更改这个值时,需要考虑熔断时间是否要重新计算
    ribbon.MaxAutoRetries=2
    #重试负载均衡其他的实例最大重试次数,不包括首次调用。更改这个值时,需要考虑熔断时间是否要重新计算
    ribbon.MaxAutoRetriesNextServer=2
    #是否所有操作都重试 可能存在幂等性问题,在幂等性未解决之前设置为false,只有get请求会进行重试
    ribbon.OkToRetryOnAllOperations=false

    @LoadBalance的使用

    将@LoadBalance注解放在RestTemplate上便能赋予RestTemplate负载均衡的能力

    1   @LoadBalanced
    2   @Autowired
    3   RestTemplate restTemplate;

    为什么这么神奇,这其实涉及到Spring注解的使用,详情看:https://fangshixiang.blog.csdn.net/article/details/100890879

    @Qualifier+@Autowired可以加载指定类型的类,这样在系统启动的时候就可以获得这部分特殊的类进行加强

    我们可以学习这种设计模式,对一些老旧的工具类(自己建的或者第三方的)进行升级而不影响原来的业务逻辑

    针对@LoadBalanced下的RestTemplate的使用,我总结如下细节供以参考:
    1.传入的String类型的url必须是绝对路径(http://...),否则抛出异常:java.lang.IllegalArgumentException: URI is not absolute
    2.serviceId不区分大小写(http://user/...效果同http://USER/...,不过具体还是看服务中心,这个是由服务中心来决定是否区分大小写的,Ribbon只是传这个地址给服务中心,让服务中心给回个ip就行)
    3.serviceId后请不要跟port端口号了~
    标注有@LoadBalancedRestTemplate只能书写serviceId而不能再写IP地址/域名去发送请求了。若你的项目中两种case都有需要,请定义多个RestTemplate分别应对不同的使用场景~

    自定义Rule

     1 /**
     2  * @Author DiaoJianBin
     3  * @Description Ribbon的自定义规则
     4  *              仿照NacosRule进行书写
     5  *              如果直接加@Compoment,将会成为user-service里的全局规则
     6  *              无论请求哪个服务,都会用此规则,这样不好,所以在配置文件中指定
     7  * @Date 2021/3/10 14:51
     8  */
     9 public class CustomRuleA extends AbstractLoadBalancerRule {
    10 
    11     @Autowired
    12     private NacosDiscoveryProperties nacosDiscoveryProperties;
    13     @Autowired
    14     private NacosServiceManager nacosServiceManager;
    15 
    16     @Override
    17     public void initWithNiwsConfig(IClientConfig clientConfig) {
    18         System.out.println("CustomRuleA初始化,这里有各种配置信息可以获得,可以debug此处查看clientConfig里面的信息");
    19     }
    20 
    21     @SneakyThrows
    22     @Override
    23     public Server choose(Object key) {
    24 
    25         //获取服务配置的集群名
    26         String clusterName = nacosDiscoveryProperties.getClusterName();
    27         //当前的版本号 配置文件配置的metadata信息
    28         String currentVersion = nacosDiscoveryProperties.getMetadata().get("version");
    29         System.out.println("当前服务集群名称="+clusterName+" 版本号="+currentVersion);
    30         //获得当前服务分组
    31         String group = nacosDiscoveryProperties.getGroup();
    32         //获取负载均衡器
    33         ZoneAwareLoadBalancer baseLoadBalancer = (ZoneAwareLoadBalancer) getLoadBalancer();
    34         //调用服务的名字
    35         String invokedServerName = baseLoadBalancer.getName();
    36         //获取namingServer(包含nacos注册发现相关api)
    37         NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
    38         //获取被调用的服务的所有实例
    39         List<Instance> invokedAllInstanceList = namingService.getAllInstances(invokedServerName,group);
    40 
    41         Instance instance = null;
    42         if(invokedAllInstanceList.size()>0){
    43             //默认获取最后一个
    44             instance = invokedAllInstanceList.get(invokedAllInstanceList.size()-1);
    45             System.out.println("CustomRuleA 选择好服务的端口="+instance.getPort());
    46             return new NacosServer(instance);
    47         }
    48 
    49         return null;
    50     }
    51 }

    user-service的配置文件

    #指定当请求该服务时,所用的特定规则
    blank-service.ribbon.NFLoadBalancerRuleClassName=com.nicebin.user.ribbon.rule.CustomRuleA

    小结

         本篇博客讲的都是比较零碎的Ribbon知识,具体的体系知识大家可以自己搜索,基本都是大同小异。看完了再结合博客进行补充也是不错的。Ribbon作为微服务的核心,很多组件能跟其结合(如Feign,网关等等底层都是调用Ribbon),所以了解Ribbon大致的原理就能让很多发送问题有了解决的头绪,希望能帮到大家啦。

    学习和点赞一样,可不能下次一定啊! 感谢你的三连~
  • 相关阅读:
    Spring restful
    LDAP & Implementation
    Restful levels and Hateoas
    事务隔离的级别
    servlet injection analysis
    session and cookie
    write RE validation
    hello2 source analysis
    匿名函数和递归函数
    生成器和迭代器,列表推导式
  • 原文地址:https://www.cnblogs.com/top-housekeeper/p/14788048.html
Copyright © 2011-2022 走看看