Spring Cloud Ribbon 实现负载均衡
Spring Cloud Ribbon 实现负载均衡
1.简介
1.1 概述
Ribbon is a client-side load balancer that gives you a lot of control over the behavior of HTTP and TCP clients. Feign already uses Ribbon, so, if you use
@FeignClient, this section also applies.A central concept in Ribbon is that of the named client. Each load balancer is part of an ensemble of components that work together to contact a remote server on demand, and the ensemble has a name that you give it as an application developer (for example, by using the
@FeignClientannotation). On demand, Spring Cloud creates a new ensemble as anApplicationContextfor each named client by usingRibbonClientConfiguration. This contains (amongst other things) anILoadBalancer, aRestClient, and aServerListFilter.
Ribbon是客户端负载平衡器,可让您对HTTP和TCP客户端的行为进行大量控制。 Feign已经使用了Ribbon,因此,如果使用 @FeignClient,则本节也适用。
Ribbon中的中心概念是指定客户端的概念。每个负载平衡器都是组件的一部分,这些组件可以一起工作以按需联系远程服务器,并且该组件具有一个名称,您可以将其命名为应用程序开发人员(例如,使用 @FeignClient 注解)。根据需要,Spring Cloud通过使用 RibbonClientConfiguration 为每个命名客户端创建一个新的集合作为 ApplicationContext。它包含(除其他事项外)一个 ILoadBalancer,一个 RestClient 和一个ServerListFilter。
1.2 自定义 Ribbon
You can configure some bits of a Ribbon client by using external properties in
<client>.ribbon.*, which is similar to using the Netflix APIs natively, except that you can use Spring Boot configuration files. The native options can be inspected as static fields inCommonClientConfigKey(part of ribbon-core).
您可以使用 <client>.ribbon.*中的外部属性来配置Ribbon客户端的某些地方,这与本机使用Netflix API相似,不同之处在于可以使用Spring Boot配置文件。可以在 CommonClientConfigKey(功能区核心的一部分)中将本地选项检查为静态字段。
The following list shows the supported properties>:
<clientName>.ribbon.NFLoadBalancerClassName: Should implementILoadBalancer<clientName>.ribbon.NFLoadBalancerRuleClassName: Should implementIRule<clientName>.ribbon.NFLoadBalancerPingClassName: Should implementIPing<clientName>.ribbon.NIWSServerListClassName: Should implementServerList<clientName>.ribbon.NIWSServerListFilterClassName: Should implementServerListFilter
2.演示环境
- JDK 1.8.0_201
- Spring Boot 2.2.0.RELEASE、Spring Cloud Hoxton.RELEASE
- 构建工具(apache maven 3.6.3)
- 开发工具(IntelliJ IDEA )
3.演示代码

- nfx-ribbon-client:ribbon 客户端,通过 ribbon 负载均衡调用服务;
- nfx-ribbon-server:ribbon 服务端,负责提供服务供客户端调用。
3.1 nfx-ribbon-server
3.1.1 代码说明
提供一个 restful 接口,供客户端调用
3.1.2 maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
3.1.3 配置文件
spring.application.name=nfx-ribbon-server
## 配置浮动ip
server.port=${random.int[8081,8084]}
3.1.4 java代码
NfxRibbonServerApplication.java
@SpringBootApplication
public class NfxRibbonServerApplication {
public static void main(String[] args) {
SpringApplication.run(NfxRibbonServerApplication.class, args);
}
}
RibbonServerController.java
@RestController
@RequestMapping(value = "/server")
public class RibbonServerController {
private static final Logger LOGGER = LoggerFactory.getLogger(RibbonServerController.class);
@GetMapping(value = "/ribbon")
public String ribbon() {
LOGGER.info("ribbon server is calling!");
return "Ribbon server has started!";
}
}
3.2 nfx-ribbon-client
3.2.1 代码说明
通过 ribbon 的负载均衡机制,调用 server 提供的接口
3.2.2 maven 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
</dependencies>
3.2.3 配置文件
spring.application.name=nfx-netflix-ribbon
server.port=8070
ribbon.eureka.enable=false
## 由于没有使用eureka,所以需要配置服务端地址,前面 nfx-ribbon-server 为服务端应用名
nfx-ribbon-server.ribbon.listOfServers=localhost:8081,localhost:8082,localhost:8083
nfx-ribbon-server.ribbon.ServerListRefreshInterval=1500
3.2.4 java代码
NfxRibbonClientApplication.java
@SpringBootApplication
public class NfxRibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(NfxRibbonClientApplication.class, args);
}
}
RibbonConfig.java
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public IRule ribbonRule() {
// 轮询策略
return new RoundRobinRule();
}
}
RibbonClientController.java
@RestController
@RequestMapping(value = "/client")
public class RibbonClientController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancer;
/**
* 直接使用 ribbon api
*/
@GetMapping(value = "/ribbon")
public String ribbon() {
ServiceInstance instance = loadBalancer.choose("nfx-ribbon-server");
String host = instance.getHost();
int port = instance.getPort();
System.err.println("ribbon request: " + host + ":" + port);
return "ribbon request: " + host + ":" + port;
}
/**
* 使用 restTemplate 调用ribbon
*/
@GetMapping(value = "/rest")
public String rest() {
return restTemplate.getForObject("http://nfx-ribbon-server/server/ribbon", String.class);
}
}
3.3 git 地址
spring-cloud-nfx-04-ribbon: Spring Cloud 整合 Ribbon实现的分布式负载均衡方案
4.效果展示
启动三个 nfx-ribbon-server,端口分别为 8081/8082/8083;

然后再启动 nfx-ribbon-client ,在 spring-cloud-netflix-ribbon.http 访问下列地址,观察输出信息是否符合预期。
### GET /client/ribbon (每次返回的地址都是不一样的)
GET http://localhost:8070/client/ribbon
可以看到,由于配置了 RoundRobinRule 的轮询策略,所以会依次输出:ribbon request: localhost:8081、ribbon request: localhost:8082、ribbon request: localhost:8083

在 nfx-ribbon-client 的控制台,可以看到如下内容

### GET /client/rest
GET http://localhost:8070/client/rest
同理,使用 restTemplate 调用 nfx-ribbon-server 的接口时,会分别在三个控制台打印:ribbon server is calling!