转载

Spring Cloud Ribbon — 客户端负载均衡器

Ribbon 是 Netflix 开源的项目,主要用于为提供客户端软件提供负载均衡算法。Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一个基于 HTTP 和 TCP 的客户端负载均衡器。

1. Ribbon 单独使用

创建两个项目:order-service(订单服务,作为服务提供者)、user-center(用户中心,作为服务消费者)。并在 user-center(服务消费者)端使用 Spring Cloud Ribbon 做客户端负载均衡。

Spring Cloud Ribbon — 客户端负载均衡器

1.1 服务提供者

在 order-service/pom.xml 中声明依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

在 order-service/src/main/resources/application.yml 配置两个端口以便启动两个不同实例用于测试:

spring:
 application:
 name: order-service
 profiles:
 active: service1
---
spring:
 profiles: service1
server:
 port: 8881
---
spring:
 profiles: service2
server:
 port: 8882

编写查询用户订单的服务方法:

@RestController
@RequestMapping("/order")
public class OrderController{
    
    @Autowired
    private OrderRepository orderRepository;
    
    @GetMapping("/find/{uid:[1-9]//d+}")
    publicList<Order>findByUid(@PathVariable Integer uid){
        System.out.println("------------------------------------------------");
        System.out.println("------------------ 方法被调用 ------------------");
        System.out.println("------------------------------------------------");
        return orderRepository.findByUid(uid);
    }
    
}

配置根路径的访问许可,以便客户端负载均衡器能够 PING 通本服务:

@Configuration
public class WebConfigextends WebMvcConfigurerAdapter{
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry){
        registry.addStatusController("/", HttpStatus.OK);
    }
    
}

编写 Spring Boot 应用启动类:

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

1.2 服务消费者

在 user-center/pom.xml 中声明依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

在 user-center/src/main/resources/application.yml 配置客户端负载均衡:

server:
 port: 8888
spring:
 application:
 name: user-center
order-service:
 ribbon:
 eureka:
 enabled: false
    # 微服务的服务器列表
 listOfServers: localhost:8881,localhost:8882
    # 刷新微服务的服务器列表信息间隔的毫秒数
 ServerListRefreshInterval: 3000

默认情况下,Spring Cloud Ribbon 使用 NoOpPing 作为 IPing 的实现,NoOpPing 实际上并没有 PING 服务器而是一直返回 true。而 PingUrl 则会通过 PING 服务器根路径地址来检查每一台服务器的状态以确认服务是否还在线。默认情况下,Spring Cloud Ribbon 使用 ZoneAvoidanceRule 作为 IRule 的实现,ZoneAvoidanceRule 基于 AZ(可用区)过滤服务器最大程度避免区域服务器故障。由于本地环境测试,这里采用 AvailabilityFilteringRule,它使用 Ribbon 内置的断路器功能来过滤掉处于开路状态(无法 PING 通)的服务器。

public class RibbonConfiguration{
    
    @Autowired
    private IClientConfig ribbonClientConfig;
    
    @Bean
    publicIPingribbonPing(IClientConfig config){
        return new PingUrl();
    }
    
    @Bean
    publicIRuleribbonRule(IClientConfig config){
        return new AvailabilityFilteringRule();
    }
    
}

编写用户订单查询服务:

@RestController
@RequestMapping("/user")
public class UserController{
    
    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/orders/{uid:[1-9]//d+}")
    publicList<Order>orders(@PathVariable Integer uid){
        return restTemplate.getForObject(String.format("http://order-service/order/find/%d", uid), List.class);
    }
    
}

编写 Spring Boot 应用启动类,使用 @LoadBalanced 注解,为 RestTemplate 开启负载均衡的能力:

@SpringBootApplication
@RibbonClient(name = "order-service", configuration = RibbonConfiguration.class)
public class Application{
    
    @Bean
    @LoadBalanced
    publicRestTemplateproviceRestTemplate(){
        return new RestTemplate();
    }
    
    public static void main(String[] args){
        SpringApplication.run(Application.class);
    }
    
}

1.3 启动服务

启动两个服务提供者服务:

$ java -jar order-service-0.0.1-SNAPSHOT.jar
$ java -Dspring.profiles.active=service2 -jar order-service-0.0.1-SNAPSHOT.jar

启动一个服务消费者服务:

$ java -jar user-center-0.0.1-SNAPSHOT.jar

你可以尝试多次访问用户订单服务,或尝试途中关闭其中一个服务提供者服务再访问用户订单服务,以便查看其效果。

$ curl -i -X GET http://localhost:8888/user/orders/1001

2. 整合 Eureka

创建三个项目:eureka-server(服务注册中心)、order-service(订单服务,作为服务提供者)、user-center(用户中心,作为服务消费者)。并在 user-center(服务消费者)端使用 Spring Cloud Ribbon 做客户端负载均衡。

Spring Cloud Ribbon — 客户端负载均衡器

2.1 服务注册中心

在 eureka-server/pom.xml 中声明依赖:

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

eureka-server/src/main/resources/application.yml 配置示例:

server:
 port: 8761
spring:
 application:
 name: eureka-server
eureka:
 instance:
 hostname: localhost
 server:
 renewal-percent-threshold: 0.49
 client:
 register-with-eureka: false
 fetch-registry: false
 service-url:
 default-zone: http://${eureka.instance.hostname}:${server.port}/eureka/
logging:
 level:
    com.netflix.eureka: 'off'
    com.netflix.discovery: 'off'

Spring Boot 应用启动类:

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

2.2 服务提供者

在 order-service/pom.xml 中声明依赖:

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

在 order-service/src/main/resources/application.yml 配置两个端口以便启动两个不同实例用于测试:

spring:
 application:
 name: order-service
 profiles:
 active: service1
eureka:
 client:
 service-url:
 defaultZone: http://localhost:8761/eureka/
---
spring:
 profiles: service1
server:
 port: 8881
---
spring:
 profiles: service2
server:
 port: 8882

编写查询用户订单的服务方法:

@RestController
@RequestMapping("/order")
public class OrderController{
    
    @Autowired
    private OrderRepository orderRepository;
    
    @GetMapping("/find/{uid:[1-9]//d+}")
    publicList<Order>findByUid(@PathVariable Integer uid){
        System.out.println("------------------------------------------------");
        System.out.println("------------------ 方法被调用 ------------------");
        System.out.println("------------------------------------------------");
        return orderRepository.findByUid(uid);
    }
    
}

编写 Spring Boot 应用启动类:

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

2.3 服务消费者

在 user-center/pom.xml 中声明依赖:

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

user-center/src/main/resources/application.yml 配置示例:

server:
 port: 8888
spring:
 application:
 name: user-center
eureka:
 client:
 register-with-eureka: false
 serviceUrl:
 defaultZone: http://localhost:8761/eureka/

编写用户订单查询服务:

@RestController
@RequestMapping("/user")
public class UserController{
    
    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/orders/{uid:[1-9]//d+}")
    publicList<Order>orders(@PathVariable Integer uid){
        return restTemplate.getForObject(String.format("http://order-service/order/find/%d", uid), List.class);
    }
    
}

编写 Spring Boot 应用启动类,使用 @LoadBalanced 注解,为 RestTemplate 开启负载均衡的能力:

@SpringBootApplication
@RibbonClient(name = "order-service", configuration = RibbonConfiguration.class)
public class Application{
    
    @Bean
    @LoadBalanced
    publicRestTemplateproviceRestTemplate(){
        return new RestTemplate();
    }
    
    public static void main(String[] args){
        SpringApplication.run(Application.class);
    }
    
}

2.4 启动服务

启动服务注册中心:

$ java -jar eureka-server-0.0.1-SNAPSHOT.jar

启动两个服务提供者服务:

$ java -jar order-service-0.0.1-SNAPSHOT.jar
$ java -Dspring.profiles.active=service2 -jar order-service-0.0.1-SNAPSHOT.jar

启动一个服务消费者服务:

$ java -jar user-center-0.0.1-SNAPSHOT.jar

你可以尝试多次访问用户订单服务,或尝试途中关闭其中一个服务提供者服务再访问用户订单服务,以便查看其效果。

$ curl -i -X GET http://localhost:8888/user/orders/1001

示例项目开发环境:Java-8、Maven-3、IntelliJ IDEA-2017、Spring Cloud-Dalston.SR1

完整示例项目链接: spring-cloud-netflix-ribbon-sample 、 spring-cloud-netflix-ribbon-with-eureka-sample

参考文档文献链接: client-side-load-balancing 、 spring-cloud-ribbon

原文  http://fanlychie.github.io/post/spring-cloud-netflix-ribbon.html
正文到此结束
Loading...