SpringCloud Hello Ribbon

原文来自《重新定义Spring Cloud实战》

负载均衡

负载均衡(LoadBalance),即利用特定方式将流量分摊到多个操作单元上的一种手段,它对系统吞吐量与系统处理能力有着质的提升,毫不夸张地说,当今极少有企业没有用到负载均衡器或是负载均衡策略的。

  • 服务端负载均衡(硬负载、集中式负载均衡)[例子:Nginx]
SpringCloud Hello Ribbon
  • 客户端负载均衡(软负载、进程内负载均衡)[例子:Ribbon]

Ribbon简介

Ribbon是一个客户端负载均衡器,它赋予了应用一些支配HTTP与TCP行为的能力,可以得知,这里的客户端负载均衡(许多人称之为后端负载均衡)也是进程内负载均衡的一种。它在SpringCloud生态内是一个不可缺少的组件,少了它,服务便不能横向扩展,这显然是有违云原生12要素的。此外,Feign与Zuul中已经默认集成了Ribbon,在我们的服务之间凡是涉及调用的,都可以集成它并应用,从而使我们的调用链具备良好的伸缩性。

Hello World Demo

示例环境

  1. JDK8
  2. Maven

示例简介

  1. 服务1 – 注册中心 eureka服务端
  2. 服务2 – 提供接口功能的eureka客户端
  3. 服务3 – 服务2的调用者 ribbon

编码实现

code

  • 服务1 – 注册中心 eureka服务端

maven依赖

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

代码

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.classargs);
    }
}

配置文件

server:
port: 8888
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  • 服务2 – 提供接口功能的eureka客户端

maven依赖

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

编码

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

@RestController
public class TestController {

 @GetMapping("/add")
 public String add(Integer a, Integer b, HttpServletRequest request){
  return " From Port: "+ request.getServerPort() + ", Result: " + (a + b);
 }
}

配置文件

server:
port: 7070
spring:
application:
name: client-a
eureka:
client:
serviceUrl:
defaultZone: http://${eureka.host:127.0.0.1}:${eureka.port:8888}/eureka/
instance:
prefer-ip-address: true
  • 服务3 – 服务2的调用者 ribbon (可以修改端口启动两个服务)

maven依赖

<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

编码

@SpringBootApplication
@EnableDiscoveryClient
public class RibbonLoadbalancerApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonLoadbalancerApplication.classargs);
    }
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@RestController
public class TestController {
 
    @Autowired
    private RestTemplate restTemplate;

 @GetMapping("/add")
 public String add(Integer a, Integer b) {
  String result = restTemplate
    .getForObject("http://CLIENT-A/add?a=" + a + "&b=" + b, String.class);
  System.out.println(result);
  return result;
 }
}

测试验证

  • eureka 服务端站点查看服务注册情况是否正常
SpringCloud Hello Ribbon
  • 调用 ribbon 客户端服务
curl -X GET 
  'http://127.0.0.1:7777/add?a=1111&b=2222' 
  -H 'Postman-Token: 08f23b90-de98-4145-9f70-0e50c5caa22a' 
  -H 'cache-control: no-cache'
  • 第一次触发
SpringCloud Hello Ribbon
  • 第二次触发
SpringCloud Hello Ribbon

实战

Ribbon负载均衡策略与自定义配置

  1. ribbon支持的负载均衡策略

    策略类 命名 描述
    RandomRule 随机策略 随机选择server
    RoundRobinRule(默认) 轮询策略 按顺序循环选择server
    RetryRule 重试策略 在一个配置时间段内,当选择server不成功,则尝试选择一个可用的server
    BestAvailableRule 最低并发策略 逐个考察server,如果server断路器打开,则忽略,再选择其中并发连接最低的server
    AvailabilityFilteringRule 可用过滤策略 过滤掉一直连接失败并被标记为circuit tripped的server,过滤掉哪些高并发连接的server(active connections超过设置的阈值)
    ResponseTimeWeightedRule 响应时间加权策略 根据server的响应时间分配权重。响应时间越长,权重越低,被选择到的概率就越低;响应时间越短,权重越高,被选择到的概率就越高。这个策略很贴切,中和了各种因素,如:网络、磁盘、IO等,这些因素直接影响着响应时间。
    ZoneAvoidanceRule 区域权衡策略 综合判断server所在区域的性能和server的可用性轮询选择server,并且判定一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有server
  2. 自定义配置

    @Configuration
    public class TestConfiguration {
     
     @Bean
     public IRule ribbonRule(IClientConfig config) {
      return new RandomRule();
     }
    }
    • 方式一 :在@RibbonClients中配置
    • 方式二
    • 基于注解的策略配置(针对某个源服务进行配置)

      注意 : 这里使用@ComponentScan注解的意思是让Spring不去扫描被@AvoidScan注解标记的配置类,因为我们的配置是对单个源服务生效的,所以不能应用于全局,如果不排除,启动就会报错

      @SpringBootApplication
      @EnableDiscoveryClient
      @RibbonClients(value = {
        @RibbonClient(name = "client-a", configuration = TestConfiguration.class),
        @RibbonClient(name 
      "client-b", configuration = TestConfiguration.class)
      })
      public class RibbonLoadbalancerApplication 
      {

          public static void main(String[] args) {
              SpringApplication.run(RibbonLoadbalancerApplication.classargs);
          }
          
          @Bean
          @LoadBalanced
          public RestTemplate restTemplate() {
              return new RestTemplate();
          }
      }
      @Configuration
      @AvoidScan
      public class TestConfiguration {
       
       @Autowired
          IClientConfig config;

       @Bean
       public IRule ribbonRule(IClientConfig config) {
        return new RandomRule();
       }
      }
      @Configuration
      @AvoidScan
      public class TestConfiguration {
       
       @Autowired
          IClientConfig config;

       @Bean
       public IRule ribbonRule(IClientConfig config) {
        return new RandomRule();
       }
      }
      @SpringBootApplication
      @EnableDiscoveryClient
      @RibbonClient(name = "client-a", configuration = TestConfiguration.class)
      @ComponentScan(excludeFilters 
      = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {AvoidScan.class})})
      public class RibbonLoadbalancerApplication 
      {

          public static void main(String[] args) {
              SpringApplication.run(RibbonLoadbalancerApplication.classargs);
          }
          
          @Bean
          @LoadBalanced
          public RestTemplate restTemplate() {
              return new RestTemplate();
          }
      }
    • 全局策略设置
  • 基于配置文件的策略配置
clienta.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

Ribbon超时与重试

client-a:
  ribbon:
    ConnectTimeout: 3000
    ReadTimeout: 60000
    MaxAutoRetries: 1 #对第一次请求的服务的重试次数
    MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量(不包括第一个服务)
    OkToRetryOnAllOperations: true

Ribbon的饥饿加载

Ribbon在进行客户端负载均衡的时候并不是在启动时就加载上下文,而是在实际请求的时候才去创建,因此这个特性往往会让我们的第一次调用显得颇为疲软乏力,严重的时候会引起调用超时。所以我们可以通过指定Ribbon具体的客户端的名称来开启饥饿加载,即在启动的时候便加载所有配置项的应用程序上下文。

ribbon:
  eager-load:
    enabled: true
    clients: client-a, client-b, client-c

利用配置文件自定义Ribbon客户端

使用配置文件来指定一些默认加载类,从而更改Ribbon客户端的行为方式,并且使用这种方式优先级最高,优先级高于使用注解@RibbonClient指定的配置和源码中加载的相关Bean。

client:
  ribbon:
    NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule


原文始发于微信公众号(灰气球):SpringCloud Hello Ribbon

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/66516.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!