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
@FeignClient
annotation). On demand, Spring Cloud creates a new ensemble as anApplicationContext
for 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!