Spring Cloud (two): Web services client's Ribbon

How to achieve the above-described service registration, as well as how to obtain a list of services from Eureka has been registered by Eureka. So get the registration list of services, how to make service calls? A simple implementation is a service instance can choose from a list of examples of services being called by its hostname (or IP), port, and path API spliced ​​into a complete url, to complete the call via http client. But the production environment, in order elements, service call performance, high availability and other generally relates to load balancing, failover, failure retry the achievement, so the introduction of the client components to achieve these functions has also become an essential micro-service architecture elements. Spring Cloud can be achieved through service calls between Ribbon and Feign.

This series of articles written and examples are based on the latest version of Spring Cloud Hoxton.

Ribbon

Ribbon is a load-balanced Web client. Our general understanding of load balancing is implemented on the server side, such as Nginx (but this is relative, if the relative back-end services, it is also possible to achieve Nginx as a load balancing client), and Ribbon customers end load balancing to achieve.

Ribbon core concept is named client (named client), Spring Cloud will create a sub-application context (ApplicationContext) for each named client, in this context, to create ILoadBalancer, RestClient, ServerListFilter etc. Bean by RibbonClientConfiguration.

The default Ribbon bean and instructions provided by Spring Cloud Netflix

Bean type The default implementation class Explanation
IClientConfig DefaultClientConfigImpl Ribbon client configuration to achieve load, load implementations of the bean and the client connection timeout, communications timeout configuration
IRule ZoneAvoidanceRule Based zone and availability to achieve filtering rules server
IPing DummyPing Achieve determine whether the survival of the server, the default is always returns true
ServerList ConfigurationBasedServerList Get the list of servers to achieve, based on the default configuration
ServerListFilter ZonePreferenceServerListFilter Server filters realized, the default server list filters out with a client in the same zone of
ILoadBalancer ZoneAwareLoadBalancer Load balancing to achieve, at the request of the default load zone of highest load exclude the zone, from the rest of the zone, select a select a server from the given Rule
ServerListUpdater PollingServerListUpdater Dynamic server list updater

 

Spring Cloud a configuration allows us to customize the client by declaring to adjust or cover the default implementation, such as

@Configuration
@RibbonClient(name = "custom", configuration = CustomConfiguration.class)
public class TestConfiguration {

}

Thus, the composition together with the client by RibbonClientConfiguration defined CustomConfiguration assembly, and the assembly will CustomConfiguration over the former.

Note CustomConfiguration must be @Configuration modified class, and can not be the main @ComponentScan scanning application context, otherwise it will be shared by all @RibbonClients

If you want to customize the default configuration for all Ribbon Clients, you can use @RibbonClients comment

@RibbonClients(defaultConfiguration = DefaultRibbonConfig.class)
public class RibbonClientDefaultConfigurationTestsConfig {

}

 

也可以通过配置属性来定制Ribbon Client,支持的配置属性

<clientName>.ribbon.NFLoadBalancerClassName: ILoadBalancer接口实现类
<clientName>.ribbon.NFLoadBalancerRuleClassName: IRule接口实现类
<clientName>.ribbon.NFLoadBalancerPingClassName: IPing接口实现类
<clientName>.ribbon.NIWSServerListClassName: ServerList接口实现类
<clientName>.ribbon.NIWSServerListFilterClassName: ServerListFilter接口实现类

 

比如对于一个服务名称为users的配置

users:
ribbon:
NIWSServerListClassName: com.netflix.loadbalancer.ConfigurationBasedServerList
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

 

配置属性的优先级 > configuration指定配置类的优先级 > 默认RibbonClientConfiguration的优先级, 即同样的实现,前者覆盖后者。

当Eureka与Ribbon同时存在时,ribbonServerList会被 DiscoveryEnabledNIWSServerList覆盖,从Eureka来获取server list,同时 NIWSDiscoveryPing也会替换IPing接口,代理Eureka来确定服务器是否处于运行状态。

Ribbon的超时与重试配置

  • <clientName>.ribbon.ConnectTimeout: 请求连接超时时间,默认2000
  • <clientName>.ribbon.ReadTimeout: 请求处理超时时间,默认5000
  • <clientName>.ribbon.MaxAutoRetries: 在同一台服务器上的重试次数,排除第一次调用,默认0
  • <clientName>.ribbon.MaxAutoRetriesNextServer: 切换服务器的重试次数,默认1
  • <clientName>.ribbon.OkToRetryOnAllOperations: 对所有请求都进行重试,默认false

当项目中添加了Spring Retry的依赖,则会启用重试机制。当请求失败时,会再尝试访问当前服务器(次数由MaxAutoRetries配置),如果不行,就换一个服务器进行访问,如果还是不行,再换服务器访问(更换次数由MaxAutoRetriesNextServer配置),如果还是不行,则返回请求失败。

Ribbon的负载均衡策略

前文提到Ribbon的负载均衡默认实现为ZoneAwareLoadBalancer,那么Ribbon提供的负载均衡策略还有哪些? 罗列如下

  • BestAvailableRule: 排除掉断路器打开的服务器,选取并发请求最小的服务器
  • AvailabilityFilteringRule: 过滤掉断路器打开或活跃连接数超过限制(通过<clientName>.<nameSpace>.ActiveConnectionsLimit配置,默认为Integer.MAX_VALUE)的服务器
  • WeightedResponseTimeRule: 根据平均响应时间来动态为服务器赋予权值,实现基于权重的轮询
  • RetryRule: 对选择负载均衡策略添加重试机制
  • RoundRobinRule: 简单轮询
  • RandomRule: 随机轮询
  • ZoneAvoidanceRule: 结合区域与可用性来选择服务器,也是默认实现

可通过如下配置修改Ribbon的负载均衡策略

client-name:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule

 

案例演示

本文案例演示基于上文搭建的springcloud-eureka 与 springcloud-eureka-client 两个示例项目 (源码),依次启动两个项目,然后将springcloud-eureka-client项目的端口 server.port改为8081,新开一个springboot运行配置,如图

Eureka客户端2

以8081端口再起一个springcloud-eureka-client的服务实例。这是查看Eureka页面 http://localhost:8761/, 可以看到hello-service服务注册了两个实例

hello服务注册

新建springcloud-ribbon项目 (源码

pom.xml中引入依赖

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

 

编写测试接口, LoadBalanceClient 是Ribbon的API

@RestController
public class RibbonTestController {

@Autowired
private LoadBalancerClient loadBalancer;

@GetMapping("ribbon")
public String testRibbon(){
ServiceInstance instance = loadBalancer.choose("hello-service");
return String.format("http://%s:%s", instance.getHost(),
instance.getPort());
}
}

 

启动springcloud-ribbon, 调用测试接口 http://localhost:8082/ribbon, 可以看到返回结果交替显示 http://CN-201911061714:8080, http://CN-201911061714:8081 (CN-201911061714是我电脑的hostname,你的可能不一样),可见Ribbon实现了客户端的负载均衡。

一些知识点

  1. Ribbon如果对所有请求进行重试,则需要保证接口的幂等性(多次调用产生的结果是一致的)

  2. 每一个命名的Ribbon客户端都有一个相应的由Spring cloud维护的子应用上下文,默认是lazy load的(第一次请求客户端时才load),可以通过如下配置更改为启动立即加载

    ribbon:
    eager-load:
    enabled: true
    clients: client1, client2, client3
  3. client.ribbon.* 针对单个客户端进行配置,针对所有客户端默认配置,则使用ribbon.*

  4. 当结合断路器使用时, 断路器的超时时间要大于Ribbon的超时时间,不然不会触发重试(还没重试就触发断路器打开了)

  5. 除了Ribbon,能做负载均衡访问的Web客户端还有@LoadBalance 注解的RestTemplate, 与Feign

本文示例代码

 

 


认真生活,快乐分享
欢迎关注微信公众号:空山新雨的技术空间
微信公众号

Guess you like

Origin www.cnblogs.com/spec-dog/p/12196237.html