栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Cloud 入门(5):Ribbon的定义,配置策略,超时重置,饥饿加载

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Cloud 入门(5):Ribbon的定义,配置策略,超时重置,饥饿加载

Ribbon 是什么

Ribbon 是一个客户端负载均衡器,它赋予了应用一些支配HTTP 与 TCP 行为的能力,这里的负载均衡是客户端的负载均衡,也有人称为后端负载均衡是进程内负载均衡的一种。

前面分析了 Eureka 的使用,作为服务注册中心,Eureka 分为 Server 端和 Client 端,Client 端作为服务的提供者,将自己注册到 Server 端,Client 端高可用的方式是使用多机部署然后注册到 Server,Server 端为了保证服务的高可用,也可以使用多机部署的方式。前面简单搭建了Eureka Client 和 Server,然后将Client成功注册到 Server,本节我们将来看看如何调用Eureka 服务,在多机部署情况下如何保证负载均衡。Spring Cloud 提供了一个组件:Ribbon。Ribbon是客户端负载均衡器,可以对 HTTP 和 TCP 客户端的行为进行大量控制。Ribbon中的中心概念是指定客户端的概念。 Ribbon API

服务端负载均衡

服务端负载均衡。将多个服务注册到一个公共的注册中心,服务调用者访问注册中心,由注册中心提供服务的负载均衡。

客户端负载均衡:

服务端负载均衡的代表性例子就是nginx,LVS。那么客户端的负载均衡就是我们要说的Ribbon。Ribbon主要提供客户端负载平衡算法,除此之外,Ribbon还提供:

服务发现集成 : 功能区负载平衡器在动态环境(如云)中提供服务发现。功能区库中包含与Eureka和Netflix服务发现组件的集成;容错 : Ribbon API 可以动态确定服务器是否已在实时环境中启动并运行,并且可以 检测到那些已关闭的服务器;可配置的负载平衡规则 : Ribbon支持开箱即用的 RoundRobinRule,AvailabilityFilteringRule,WeightedResponseTimeRule,还支持定义自定义规则。

Ribbon API

Rule :定义负载均衡策略;Ping : 定义如何 ping 目标服务实例来判断是否存活, ribbon 使用单独的线程每隔一段时间(默认10s)对本地缓存的 ServerList 做一次检查;ServerList :定义如何获取服务实例列表. 两种实现基于配置的 ConfigurationbasedServerList 和基于Eureka 服务发现的 DiscoveryEnabledNIWSServerList;ServerListFilter: 用来使用期望的特征过滤静态配置,动态获得的候选服务实例列表. 若未提供, 默认使用ZoneAffinityServerListFilter;ILoadBalancer: 定义了软负载均衡器的操作的接口。一个典型的负载均衡器至少需要一组用来做负载均衡的服务实例;ServerListUpdater: DynamicServerListLoadBalancer用来更新实例列表的策略(推EurekaNotificationServerListUpdater/拉PollingServerListUpdater, 默认是拉) Ribbon 的搭建

由于客户端负载均衡需要从注册中心获取服务列表,所以需要集成注册中心。

创建注册中心

创建父级工程 cloud-ribbon-practice


    org.springframework.boot
    spring-boot-starter-parent
    2.2.3.RELEASE
     



    UTF-8
    UTF-8
    1.8
    Hoxton.SR3



    
        
            org.springframework.cloud
            spring-cloud-dependencies
            ${spring.cloud-version}
            pom
            import
        
    



    
        org.springframework.boot
        spring-boot-starter-web
    
    
        org.springframework.boot
        spring-boot-starter-actuator
    



    
        
            org.springframework.boot
            spring-boot-maven-plugin
        
    

创建注册中心 cloud-eureka-server


        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-server
        
    

配置文件 application.yaml

server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}
创建源服务的提供者 cloud-ribbon-hello-b1、cloud-ribbon-hello-b2、cloud-ribbon-hello-b3

每个工程都引入 Eureka


     
         org.springframework.cloud
         spring-cloud-starter-netflix-eureka-client
     
 

配置文件 application.xml
b1

spring:
  application:
    name: ribbon-service-b
server:
  port: 7777
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

b2

spring:
  application:
    name: ribbon-service-b
server:
  port: 7778
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

b3

	spring:
  application:
    name: ribbon-service-b
server:
  port: 7779
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

b1、b2、b3的controller

@RestController
public class OrderController {

    @Value("${server.port}")
    private Integer port;

    @Value("${spring.application.name}")
    private String name;

    @GetMapping("/test")
    public String add() {
        return "this service name is " + name + " and port is " + port;
    }

}

b1、b2、b3的启动类

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

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

@SpringBootApplication
@EnableDiscoveryClient
public class ServiceB3Application {
    public static void main(String[] args) {
        SpringApplication.run(ServiceB3Application.class, args);
    }
}
创建服务的调用者 cloud-ribbon-hello-a

spring-cloud-starter-netflix-eureka-client 已经集成了 ribbon。不需要额外引入,直接使用即可。


    
        org.springframework.cloud
        spring-cloud-starter-netflix-eureka-client
    

配置文件 application.yml

spring:
  application:
    name: ribbon-hello-a
server:
  port: 7776
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

启动类,RestTemplate 使用了@LoadBalanced,这样 RestTemplate 就开启了 ribbon 的负载均衡了。

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

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
controller

@RestController
@RequestMapping("ribbon")
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/test")
    public String test(){
        String body = restTemplate.getForEntity("http://RIBBON-SERVICE-B/test", String.class).getBody();
        return body;
    }

}
测试

测试,使用postman访问几次:http://localhost:7776/ribbon/...


Ribbon 的服务策略配置 策略配置参数

从上一节可以看到,开启负载均衡只需通过@LoadBalanced注解即可。

定义一个负载均衡的 RestTemplate,使用了 @LoadBalanced注解,该注解配合覆盖均衡策略一起使用 RestTemplate 发出的请求才能生效。

可以根据实际的业务场景选择最合适的策略:

策略类命名描述
RandomRule随机策略随机选择Server
RoundRobinRule轮询策略按顺序选择Server
RetryRule重试策略在一个配置时间段内当选择 Server 不成功,则一直尝试选择一个可用的Server
BestAvailableRule最低并发策略先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。
AvailabilityFilteringRule可用过滤策略过滤一直连接失败并标记为circuit tripped的Server,过滤掉那些高并发连接的Server(active connections超过配置的阈值)
ResponseTimeWeightedRule响应时间加权策略已经被弃用,作用同WeightedResponseTimeRule
WeightedResponseTimeRule响应时间加权策略根据Server的响应时间分配权重,响应时间越长,权重越低,被选中的概率就越低。响应时间越短,权重越高,被选择到的概率越高
ZoneAvoidanceRule区域权衡策略综合判断 Server 所在区域的性能和Server 的可用性轮询选择 Server,并且判断一个 AWS Zone 的运行性能是否可用,剔除不可用的 Zone 中 的所有 Server
配置方式

全局配置

使用 Ribbon 时配置全局的负载均衡策略,需要加一个配置类。该配置类需要被 @ComponentScan 扫描到才能全局生效。

@Configuration
public class GlobalRuleConfig {
    @Bean
    public IRule ribbonRule() {
        return new RandomRule();
    }
}

上面配置了随机的策略,多次访问http://localhost:7776/ribbon/...

基于 @RibbonClient 或@RibbonClients注解的配置

注意:编写自定义配置类,需要特别注意的是官方文档明确给出了警告:这个自定义配置类不能放在@ComponentScan所扫描的包以及其子包下(即不能放在主启动类所在的包及其子包下,因此我们需要新建一个包来放该配置类),否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就达不到特殊化定制的目的了

策略配置

@Configuration
public class AnnoRuleConfig {
    @Bean
    public IRule ribbonRule() {
        return new RandomRule();
    }
}

启动类的配置

@SpringBootApplication
@EnableDiscoveryClient
@RibbonClient(name = "ribbon-service-b", configuration = AnnoRuleConfig.class)
public class ServiceAApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceAApplication.class, args);
    }

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

通过 @RibbonClient 指定某个服务的负载均衡策略,其他没有被指定的,就是用默认的负载均衡策略。

@RibbonClient 注解可以把其他的配置类作为另外一个IOC容器导入到应用中,相当于加载了两个完全不相干的 Spring 的 beans 配置文件,此时应用中会有两个IOC容器。

@RibbonClient(name = "RIBBON-SERVICE-B", configuration = AnnoRuleConfig.class)

也可以使用 RibbonClients 指定多个服务的负载均衡策略

@RibbonClients(value = {
        @RibbonClient(name = "RIBBON-SERVICE-B", configuration = AnnoRuleConfig.class),
        @RibbonClient(name = "RIBBON-SERVICE-C", configuration = AnnoRuleConfig.class)
})

基于配置文件

下面对服务 ribbon-service-b 的负载均衡策略使用

RIBBON-SERVICE-B:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
Ribbon 超时与重试

使用 HTTP 发起请求难免会发生问题,在F版开始 Ribbon 的重试机制默认是开启的,需要添加对超时时间与重试策略的配置。

列如下面 ribbon-service-b 服务的配置

RIBBON-SERVICE-B:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    ConnectTimeout: 3000
    ReadTimeout: 60000
    MaxAutoRetries: 3 #对第一次请求的服务的重试次数
    MaxAutoRetriesNextServer: 1 #要重试的下一个服务的最大数量(不包括第一个服务)
    OkToRetryOnAllOperations: true

也可以全局配置

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

一般 Ribbon 都是搭配 OpenFeign 这类 Http 客户端或者其他RPC 使用。因为这样去调用远程服务会更加优雅和方便。而OpenFeign默认是继承了Ribbon,对于Ribbon的超时时间配置也是很简单。

对于网络抖动这些可以使用spring-retry,spring-retry是spring提供的一个基于spring的重试框架,非常好用。

Ribbon 饥饿加载

Ribbon 在进行客户端负载均衡的时候,并不是启动时就加载上下文,而是在实际请求的时候采取创建。

因为要加载上下文的原因,在第一次调用时可能会很慢,甚至导致超时。

所以我们可以指定 Ribbon 客户端开启立即加载(饥饿加载),在应用启动的时候就立即加载所有配置项的应用程序上下文。

ribbon:
  eager-load:
    clients: ribbon-service-b, ribbon-service-order
    enabled: true
Eureka 在 Ribbon 的作用

下面看一下整合 Eureka 和 Ribbon 如何实现服务调用 和 负载均衡。有了 Eureka 之后,服务调用就无需关注服务提供者的IP

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/709541.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号