服务负载均衡调用Ribbon

Ribbon概述:

  Ribbon是 Netflixfa 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中,Eureka一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Eureka中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载。
  在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务。
Ribbon的主要作用:

  1.服务调用

    基于Ribbon实现服务调用, 是通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助RestTemplate 最终进行调用
  2.负载均衡

    当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址

  3.基于Ribbon实现订单调用商品服务

    不论是基于Eureka的注册中心还是基于Consul的注册中心,SpringCloud Ribbon统一进行了封装,所以对于服务调用,两者的方式是一样的。
    坐标依赖:

      在springcloud提供的服务发现的jar中已经包含了Ribbon的依赖。所以这里不需要导入任何额外的坐标

    工程改造:

      1.服务提供者

        修改product_service模块中ProductController#findById() 方法如下(实际开发不需要做这一步,这里只是方便看到服务提供者)

    @Value("${server.port}")
    private String port;
    @Value("${spring.cloud.client.ip-address}")
    private String ip;

    @GetMapping(value = "/{id}")
    public Product findById(@PathVariable Long id) {
        Product product = productService.findById(id);
        product.setProductDesc("调用product_service服务,ip:" + ip + ",服务提供者端口:" + port);
        return product;
    }

      2.服务消费者

        修改服务消费者 order_service 模块中的启动类OrderApplication ,在创建RestTemplate方法上添加 @LoadBalanced 注解(负载均衡注解)

    /**
     * 基于Ribbon的服务调用与负载均衡
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

        在 order_service 的 OrderController 中修改下面方法,并使用RestTemplate完成服务调用

/**
     * 通过订单系统,调用商品服务根据id查询商品信息
     * @param id
     * @return
     */
    @GetMapping("/buy/{id}")
    public Product findById(@PathVariable("id") Long id) {
        // return restTemplate.getForObject("http://localhost:9001/product/" + id, Product.class);

        /*List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        ServiceInstance instance = instances.get(0);
        return restTemplate.getForObject("http://" + instance.getHost() + ":" + instance.getPort() +"/product/" + id, Product.class);*/

        return restTemplate.getForObject("http://service-product/product/" + id, Product.class);
    }

      3.启动服务,测试

        访问 http://localhost:9002/order/buy/1 查看展示效果如下,已经可以在订单微服务中以服务名称的形式调用商品微服务获取数据

        

服务调用Ribbon高级:

  客户端负载均衡与服务端负载均衡

    服务端负载均衡

      先发送请求到负载均衡服务器或者软件,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法分配

    客户端负载均衡

      客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法分配

  基于Ribbon实现负载均衡

    1.修改 product_service 的 application.yml 配置文件,启动多个实例

      实例1:不修改直接启动

server:
  port: 9001
spring:
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
#配置Eureka
eureka:
  client:
    healthcheck: true #开启健康检查(依赖spring-boot-actuator)
    service-url: #EurekaServer的路径
     defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
  instance:
    prefer-ip-address: true #使用ip注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认90秒)
    lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔(默认30秒)
View Code

      实例2:修改端口为9011,启动

server:
  port: 9011
spring:
  application:
    name: service-product #服务名称
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  jpa:
    database: MySQL
    show-sql: true
    open-in-view: true
#配置Eureka
eureka:
  client:
    healthcheck: true #开启健康检查(依赖spring-boot-actuator)
    service-url: #EurekaServer的路径
     defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
  instance:
    prefer-ip-address: true #使用ip注册
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    lease-expiration-duration-in-seconds: 10 #eureka client发送心跳给server端后,续约到期时间(默认90秒)
    lease-renewal-interval-in-seconds: 5 #发送心跳续约间隔(默认30秒)
View Code

    2.多次访问 http://localhost:9002/order/buy/1 ,调用的实例会一直在切换

      

      

  负载均衡策略

    Ribbon内置了多种负载均衡策略

      com.netflix.loadbalancer.RoundRobinRule :以轮询的方式进行负载均衡(默认)

      com.netflix.loadbalancer.RandomRule :随机策略

      com.netflix.loadbalancer.RetryRule :重试策略

        需要引入坐标:

            <dependency>

              <groupId>org.springframework.retry</groupId>

              <artifactId>spring-retry</artifactId>

            </dependency>

        #    ConnectTimeout: 250 # Ribbon的连接超时时间

        #    ReadTimeout: 1000 # Ribbon的数据读取超时时间

        #    OkToRetryOnAllOperations: true # 是否对所有操作都进行重试

        #    MaxAutoRetriesNextServer: 1 # 切换实例的重试次数

        #    MaxAutoRetries: 1 # 对当前实例的重试次数

      com.netflix.loadbalancer.WeightedResponseTimeRule :权重策略。会计算每个服务的权重,越高的被调用的可能性越大。

      com.netflix.loadbalancer.BestAvailableRule :最佳策略。遍历所有的服务实例,过滤掉故障实例,并返回请求数最小的实例返回。

      com.netflix.loadbalancer.AvailabilityFilteringRule :可用过滤策略。过滤掉故障和请求数超过阈值的服务实例,再从剩下的实例中轮询调用。

    在服务消费者的application.yml配置文件中修改负载均衡策略

    策略选择:

      1、如果每个机器配置一样,则建议不修改策略 (推荐)

      2、如果部分机器配置强,则可以改为 WeightedResponseTimeRule

    

 

posted @ 2020-03-14 20:49  糖不甜,盐不咸  阅读(314)  评论(0编辑  收藏  举报