敖胤

绳锯木断,水滴石穿;聚沙成塔,集腋成裘。

导航

Spring Cloud Netflix 学习笔记(二)—负载均衡(Ribbon)

Ribbon是用于实现服务与服务之间的负载均衡的技术。官网原文:Ribbon is a client-side load balancer that gives you a lot of control over the behavior of HTTP and TCP clients.

已知Eureka Client会从Eureka Server上拉取服务信息保存在本地缓存中,当被调用的服务是集群方式部署时,调用端本地缓存就会存在多个目标服务的信息,而此时就需要通过一定的策略决定调用哪个服务(负载均衡)。而Ribbon就是用来实现负载均衡的。根据实施位置,可分为:

  • 客户端负载均衡:调用方将被调用方的信息全部拉取到本地缓存,在本地通过一定的策略选择其中一个。代表:Ribbon
  • 服务端负载均衡:在服务的注册中心中,根据调用方将负载均衡策略,选择一个被调用的服务返回给调用方。代表:Dubbo

1、基本使用

示例提供两个dept服务给emp模块调用

1.1、启动多个服务提供Client

dept中提供的对外接口

@RestController
@RequestMapping("/dept")
public class DeptController {
    @Value("${server.port}")
    private String port;


    @GetMapping("/all")
    public String getAll() {
        return "dept=====>" + port;
    }
}

复制一个dept模块的启动器,并修改启动端口为8082

1.2、在被调用方引入依赖包

在emp模块中添加如下依赖

<!--Ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

1.3、整合 RestTemplate和Ribbon

  • 在emp模块的RestTemplate的配置类中给RestTemplate的bean实例加上@LoadBalanced注解
@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
  • 修改服务调用

    修改接口调用的代码,将IP+PORT改成服务名称,也就是注册到Eureka中的名称。接口调用的时候,框架内部会将服务名称替换成具体的服务IP信息,然后进行调用。

    使用restTemplate.getForObject("http://目标服务名/目标接口路径", 返回值类型)的方法,获取返回值。

    @RestController
    public class EmpController {
        @Autowired
        private RestTemplate restTemplate;
    
        @GetMapping("/emp/all")
        public String getAll() {
            //通过restTemplate对象访问目标服务
            String result = restTemplate.getForObject("http://dept/dept/all", String.class);
            //获取目标结果并返回
            System.out.println(result);
            return "emp: " + "\t" + result;
        }
    }
    

1.4、测试

启动Eureka Server及Eureka Client,访问emp模块的功能。

2、负载均衡策略

Ribbon作为一款客户端负载均衡框架,默认的负载策略是轮询,同时也提供了很多其他的策略,能够让用户根据自身的业务需求进行选择。

2.1、策略类型

如下是Ribbon提供的策略接口IRule及其实现类 的UML图

常用策略介绍:

  • RoundRobinRule——轮询策略(默认),轮询index,选择index对应位置服务
  • RandomRule——随机策略
  • WeightedResponseTimeRule——响应权重策略,轮询的子类,默认使用轮询,后续根据服务的响应时间决定
  • BestAvailableRule——最优访问策略,根据被调用方并发数决定,即最少访问优先。如果服务的断路器打开,则忽略,再选择其中并发链接最低的服务

  • RetryRule——重试策略,在一个配置时间段内,当选择的服务不成功,则一直尝试选择一个可用的服务
  • ZoneAvoidanceRule——区域权重策略,综合判断服务所在区域的性能,和服务的可用性,轮询选择服务并且判断一个AWS Zone的运行性能是否可用,剔除不可用的Zone中的所有服务
  • AvailabilityFilteringRule——过滤掉那些一直连接失败的且被标记为circuittripped的服务,并过滤掉那些高并发的服务或者使用一个AvailabilityPredicate来包含过滤服务的逻辑。其实就是检查Status里记录的各个服务 的运行状态。

2.2、策略配置

2.2.1、配置类方式

在EMP模块添加如下配置类即可

@Configuration
public class RibbonConfig {
    @Bean
    public IRule rule() {
        return new RandomRule();
        //return new RoundRobinRule();
        //return new WeightedResponseTimeRule();
        //return new BestAvailableRule();
    }
}
2.2.2、配置文件方式(推荐)

在调用方yml文件中指定目标服务的负载均衡策略,此方式可单独指定每个服务的策略类型。配置如下:

dept:	#目标服务名
  ribbon:
  	#指定负载均衡策略
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

官网说明如下 :

https://docs.spring.io/spring-cloud-netflix/docs/2.2.7.RELEASE/reference/html/#customizing-the-ribbon-client-by-setting-properties

3、重试机制

在集群环境中,用多个节点来提供服务,难免会有某个节点出现故障。由于Eureka是基于AP原则构建的,牺牲了数据的一致性,每个Eureka服务都会保存注册的服务信息,当注册的客户端与Eureka的心跳无法保持时,有可能是网络原因,也有可能是服务挂掉了。在这种情况下,Eureka中还会在一段时间内保存注册信息。这个时候客户端就有可能拿到已经挂掉了的服务信息,故Ribbon就有可能拿到已经失效了的服务信息,从而导致发生失败的请求。这种情况可以利用重试机制来避免。

重试机制就是当Ribbon发现请求的服务不可到达时,重新请求另外的服务。

RetryRule重试

最简单的方法就是利用Ribbon自带的重试策略进行重试,此时只需要在服务调用方指定调用的某个服务的负载策略为重试策略即可。

dept:	#目标服务名
  ribbon:
    #指定负载均衡策略
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RetryRule

posted on 2021-03-14 23:42  敖胤  阅读(155)  评论(0编辑  收藏  举报