SpringCloud(Greenwich版)Ribbon集成REST实现负载均衡

推荐以下稳定版本号:

Spring Boot: 2.1.9.RELEASE

Spring Cloud: Greenwich.SR3

一、Ribbon简介

  Ribbon 是 Netflix 发布的一个客户端负载均衡器,它有助于控制 HTTP 和 TCP 客户端的行为。为 Ribbon 配置服务提供者(provider)地址列表后,Ribbon 就可基于某种负载均衡算法,自动地帮助服务消费者(consumer)去请求。在Spring Cloud中,Eureka一般配合Ribbon进行使用。

 

常见Ribbon的负载均衡策略:

  • RoundRobinRule:轮询策略,所有请求被依次分发到每台应用服务器上,每个节点具备相同的配置,以循环的方式选择服务器,默认值

  • RandomRule:随机策略,Ribbon会随机从服务器列表中选择一个进行访问

  • WeightedResponseTimeRule:加权的轮询策略,对各个服务器响应时间进行加权处理,然后在采用轮询的方式来获取相应的服务器

  • 源地址哈希(Hash)策略:将请求来源的IP地址进行Hash计算,得到对应的服务器,这样来自同一个IP的请求总在同一个服务器上处理

  • AvailabilityFilteringRule:过滤策略,先过滤出访问故障的或并发请求大于阈值的一部分服务实例,然后再以轮询的方式从过滤后的服务实例清单中选出一个   

  • RetryRule:重试策略,会先按照轮询获取服务实例,如果服务实例获取失败,则会在指定的时间内进行重试。

 

二、在SpringCloud中Ribbon整合Eureka使用

服务提供者请参考Eureka注册中心客户端,本节角色是服务消费者。

1)build.gradle项目依赖

创建gradle模块consumer-service并添加web、eureka客户端与ribbon依赖

dependencies {
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'

   compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-eureka-client'

   compile group: 'org.springframework.cloud', name: 'spring-cloud-starter-netflix-ribbon'
}

2)application.yaml配置文件

配置服务消费者代码

server:
  port: 8000
spring:
  application:
    name: consumer-service
eureka:
  instance:
    hostname: localhost
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://localhost:8761/eureka/
service-url:
  provider-service: http://provider-service
View Code

3)启动类ConsumerServiceApplication.java

在启动类上实例化一个RestTemplate Bean,并在RestTemplate方法上添加@LoadBalanced注解

package org.wesson.springcloud.ribbon;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerServiceApplication {

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

    public static void main(String[] args) {
        SpringApplication.run(ConsumerServiceApplication.class, args);
    }

}
View Code

标记@LoadBalanced注解:开启客户端负载均衡功能。

4)Controller

  需要注入RestTemplate与LoadBalancerClient。通过yaml配置文件配置了 provider-service 的 http 请求地址,请求方式变成了 http://provider-service/。而 provider-service 是微服务的主机名,当 Ribbon 和 Eureka 配合使用时,自动将主机名映射成微服务的网络地址。然后再Controller使用@Value注解读取配置自定义属性。

package org.wesson.springcloud.ribbon.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/client")
public class RibbonController {

    private static final Logger LOGGER = LoggerFactory.getLogger(RibbonController.class);

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Value("${service-url.provider-service}")
    private String consumerServiceUrl;

    @GetMapping("/info")
    public String info() {
        // getForObject方法
        return restTemplate.getForObject(consumerServiceUrl + "/client/info", String.class);
    }

    @GetMapping("/log-info-instance")
    public void logInfo() {
        ServiceInstance serviceInstance = this.loadBalancerClient.choose("provider-service");
        // 打印当前选择的是哪个节点
        RibbonController.LOGGER.info("{}:{}:{}", serviceInstance.getServiceId(),
                serviceInstance.getHost(), serviceInstance.getPort());
    }

}
View Code

在 logInfo() 方法中使用 LoadBalancerClient 的 API 更加直观地获取当前选择的微服务节点。

5)测试

Step1:运行 eureka-server 启动类,端口为8761

Step2:运行 provider-service 启动类2个实例,端口为8081、8082

Step3:运行 consumer-service 启动类,端口为8000

Step4:先访问http://localhost:8761/,结果如下图:

Step5:多次访问http://localhost:8000/client/info,返回结果如下:

Step6:多次访问http://localhost:8000/client/log-info-instance,控制台会打印如下日志信息:

可以看出,此时请求会以循环的方式分布到两个微服务节点上,说明已经实现了轮询负载均衡策略。

 
posted @ 2020-03-03 18:16  wessonshin  阅读(276)  评论(0编辑  收藏  举报