Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。
一、为消费者整合Ribbon
1、复制项目eureka-client-consumer为eureka-client-consumer-ribbon
2、向pom.xml添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
3、为RestTemplate添加@LoadBalanced注解
package com.springclouddemo.eurekaclientconsumerribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @author 何昌杰
*/
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientConsumerRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientConsumerRibbonApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 只需要添加@LoadBalanced注解就可以为RestTemplate整合Ribbon实现负载均衡。
4、修改DemoController如下:
package com.springclouddemo.eurekaclientconsumerribbon.controllers;
import org.springframework.beans.factory.annotation.Autowired;
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.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author 何昌杰
*/
@RestController
public class DemoController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/helloribbon")
public void ribbonDemo(){
ServiceInstance choose = this.loadBalancerClient.choose("eureka-client-provider");
System.out.println((choose.getInstanceId() + "," + choose.getHost() + ":" + choose.getPort()));
}
@GetMapping("/hello/{name}")
public String demo1(@PathVariable("name") String name){
return this.restTemplate.getForObject("http://localhost:7100/hello/"+name,String.class);
}
}
5、修改application配置文件
spring.application.name=eureka-client-consumer-ribbon
server.port=7201
eureka.client.service-url.defaultZone=http://localhost:7000/eureka/
eureka.instance.prefer-ip-address=true
6、启动main
启动eureka-client-consumer-ribbon实例后,再启动两个eureka-client-provider实例端口分别为7100、7101。
eureka-client-consumer-ribbon作为服务消费者去消费eureka-client-provider。
idea使用不同端口启动同一项目的方法大家可以查看这篇文章。
通过浏览器多次访问http://localhost:7201/helloribbon
2019-07-06 21:32:07.796 INFO 10760 --- [nio-7201-exec-7] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:32:07.968 INFO 10760 --- [nio-7201-exec-9] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:32:08.152 INFO 10760 --- [nio-7201-exec-1] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:32:08.320 INFO 10760 --- [nio-7201-exec-3] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:32:08.496 INFO 10760 --- [nio-7201-exec-5] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:32:08.672 INFO 10760 --- [nio-7201-exec-7] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:32:08.840 INFO 10760 --- [nio-7201-exec-9] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:32:09.016 INFO 10760 --- [nio-7201-exec-1] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:32:09.184 INFO 10760 --- [nio-7201-exec-3] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:32:09.360 INFO 10760 --- [nio-7201-exec-5] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:32:09.536 INFO 10760 --- [nio-7201-exec-7] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:32:09.696 INFO 10760 --- [nio-7201-exec-9] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
通过控制台我们可以直观的看到请求被均匀的分配到两个provider。
二、自定义Ribbon负载均衡规则
1、使用Java代码自定义Ribbon负载均衡规则
1、复制项目eureka-client-ribbon为eureka-client-ribbon-java
2、修改配置文件
spring.application.name=eureka-client-consumer-java
server.port=7202
eureka.client.service-url.defaultZone=http://localhost:7000/eureka/
eureka.instance.prefer-ip-address=true
3、编写config/RibbonConfiguration.java
package com.springclouddemo.eurekaclientconsumerjava.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author 何昌杰
*/
@Configuration
public class RibbonConfiguration {
/**
* 修改负载均衡规则为随机
*/
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
4、编写config/RibbonClientConfiguration.java
package com.springclouddemo.eurekaclientconsumerjava.config;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Configuration;
/**
* @author 何昌杰
*/
@Configuration
@RibbonClient(name = "eureka-client-provider",configuration = RibbonConfiguration.class)
public class RibbonClientConfiguration {
}
- 为特定的name【eureka-client-provider】指定Ribbon配置类
5、启动main类
启动eureka-client-consumer-ribbon实例后,再启动两个eureka-client-provider实例端口分别为7100、7101。
eureka-client-consumer-java作为服务消费者去消费eureka-client-provider。
idea使用不同端口启动同一项目的方法大家可以查看这篇文章。
通过浏览器多次访问http://localhost:7202/helloribbon
2019-07-06 21:46:37.039 INFO 10124 --- [nio-7202-exec-4] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:46:37.219 INFO 10124 --- [nio-7202-exec-6] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:46:37.383 INFO 10124 --- [nio-7202-exec-8] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:46:37.566 INFO 10124 --- [io-7202-exec-10] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:46:37.746 INFO 10124 --- [nio-7202-exec-1] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:46:37.926 INFO 10124 --- [nio-7202-exec-4] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:46:38.102 INFO 10124 --- [nio-7202-exec-6] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:46:38.294 INFO 10124 --- [nio-7202-exec-8] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:46:38.454 INFO 10124 --- [io-7202-exec-10] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:46:38.606 INFO 10124 --- [nio-7202-exec-1] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
由此可以看到请求被随机分配到两个微服务。
2、使用属性自定义Ribbon负载均衡规则
1、复制项目eureka-client-ribbon为eureka-client-ribbon-java
2、修改配置文件
spring.application.name=eureka-client-consumer-properties
server.port=7203
eureka.client.service-url.defaultZone=http://localhost:7000/eureka/
eureka.instance.prefer-ip-address=true
eureka-client-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
- 通过配置指定Ribbon负载均衡规则为随机类
3、启动main类
启动eureka-client-consumer-ribbon实例后,再启动两个eureka-client-provider实例端口分别为7100、7101。
eureka-client-consumer-properties作为服务消费者去消费eureka-client-provider。
idea使用不同端口启动同一项目的方法大家可以查看这篇文章。
通过浏览器多次访问http://localhost:7203/helloribbon
2019-07-06 21:47:30.164 INFO 468 --- [nio-7203-exec-1] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:31.016 INFO 468 --- [nio-7203-exec-3] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:31.192 INFO 468 --- [nio-7203-exec-5] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:31.368 INFO 468 --- [nio-7203-exec-7] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:31.536 INFO 468 --- [nio-7203-exec-9] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:47:31.712 INFO 468 --- [nio-7203-exec-1] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
2019-07-06 21:47:31.880 INFO 468 --- [nio-7203-exec-3] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:32.048 INFO 468 --- [nio-7203-exec-5] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:32.208 INFO 468 --- [nio-7203-exec-7] c.s.e.controllers.DemoController : 192.168.1.108:7101,192.168.1.108:7101
2019-07-06 21:47:32.375 INFO 468 --- [nio-7203-exec-9] c.s.e.controllers.DemoController : 192.168.1.108:7100,192.168.1.108:7100
由此可以看到请求被随机分配到两个微服务。