客户端负载工具Ribbon
Ribbon是Netflix公司提供的一个客户端负载工具,Spring Cloud也对其进行了集成支持。使用Ribbon需要在pom.xml中添加如下依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
为了使用LoadBalancerClient,还需要在Classpath下存在RestTemplate,为此引入如下依赖。
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
然后在@Configuration
类上使用@org.springframework.cloud.netflix.ribbon.RibbonClient
声明一个Ribbon Client,指定Client的名称。如下代码声明了一个名称为hello
的Ribbon Client。
@SpringBootApplication
@RibbonClient("hello")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
然后可以通过下面的方式指定服务端的地址,其中hello
是上面声明的Ribbon Client的名称。
hello.ribbon.listOfServers=http://localhost:8900,http://localhost:8901
然后可以在应用中注入org.springframework.cloud.client.loadbalancer.LoadBalancerClient
,并通过它来获取服务端地址了。
@SpringBootTest(classes=Application.class)
@RunWith(SpringRunner.class)
public class RibbonTest {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Test
public void test() {
String serviceId = "hello";
for (int i=0; i<5; i++) {
ServiceInstance instance = this.loadBalancerClient.choose(serviceId);
System.out.println(i + ". " + instance.getUri());
}
}
}
上面的代码就通过LoadBalancerClient连续获取了5次服务端地址,运行代码你会看到如下这样的输出。
0. http://localhost:8900
1. http://localhost:8901
2. http://localhost:8900
3. http://localhost:8901
4. http://localhost:8900
Spring Cloud会注册Ribbon Client需要的IRule、IPing和ILoadBalancer等bean,它们由org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
负责注册。我们可以通过注册自己的相关类型的bean来覆盖默认的bean定义,比如下面的代码就指定了使用的IRule是基于轮询的RoundRobinRule实现。
@Configuration
public class RibbonConfiguration {
@Bean
public IRule rule() {
return new RoundRobinRule();
}
}
也可以通过@RibbonClients
的defaultConfiguration指定通用的配置信息。
@SpringBootApplication
@RibbonClient(value="hello")
@RibbonClients(defaultConfiguration=RibbonConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
也可以专门为某个Ribbon Client定义特殊配置信息,此时可以通过@RibbonClient
的configuration属性指定需要应用的@Configuration
配置类。
@SpringBootApplication
@RibbonClient(value="hello", configuration=RibbonConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Ribbon Client的配置参数也可以通过application.properties进行配置,属性名格式是clientName.ribbon.property
。比如下面的配置指定了名称为hello的Ribbon Client的服务地址和使用的IRule。更多的配置参数可以参考com.netflix.client.config.CommonClientConfigKey
的API文档,这些参数的默认值可以参考com.netflix.client.config.DefaultClientConfigImpl
。
hello.ribbon.listOfServers=http://localhost:8900,http://localhost:8901
hello.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
使用配置文件指定的参数比使用
@RibbonClient(value="hello", configuration=RibbonConfiguration.class)
指定的配置拥有更高的优先级。
Ribbon和Eureka一起使用
当应用中存在Eureka Client时,可以不通过hello.ribbon.listOfServers=http://localhost:8900,http://localhost:8901
写死hello客户端对应的服务地址。此时可以通过Eureka Client从Eureka Server获取服务地址,从而达到动态获取服务地址的目的。此时如果声明了名为hello的Ribbon Client,则会从Eureka Server获取serviceId为hello的服务对应的地址。
eureka.client.registerWithEureka=false
eureka.client.serviceUrl.defaultZone=http://localhost:8089/eureka/
如果应用中存在Eureka Client,但不希望通过Eureka Client来获取Ribbon Client对应的服务地址,可以指定ribbon.eureka.enabled=false
。
hello.ribbon.listOfServers=http://localhost:8900,http://localhost:8901
ribbon.eureka.enabled=false
eureka.client.registerWithEureka=false
eureka.client.serviceUrl.defaultZone=http://localhost:8089/eureka/
RestTemplate负载
RestTemplate可以和Ribbon一起使用,使其具备负载能力。在对应的RestTemplate对应的bean上加上@LoadBalanced
可以使其拥有负载能力。
@Configuration
public class RibbonConfiguration {
@Bean
public IRule rule() {
return new RoundRobinRule();
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
在使用的时候需要把host改为对应的serviceId,比如有一个服务hello,我们想访问它提供的/api/abc
服务,即可以访问http://hello/api/abc
。内部在访问的时候会自动把hello替换为服务hello的一个具体地址(它可能是通过ribbon.listOfServers
指定的,也可能是直接从Eureka获取的)。
@Autowired
private RestTemplate restTemplate;
@GetMapping("hello")
public String hello() {
String result = this.restTemplate.getForObject("http://hello/api/hello/abc", String.class);
return result;
}
如果你的应用中需要同时有多个RestTemplate,有的需要有负载均衡功能,有的不需要有,则可以在应用中创建多个RestTemplate类型的bean,然后根据需要用@Primary
指定一个为自动注入时默认使用的。比如下面我们定义了默认注入的是拥有负载均衡功能的RestTemplate。
@Bean
@LoadBalanced
@Primary
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
@Bean
public RestTemplate commonRestTemplate(RestTemplateBuilder builder) {
return builder.build();
}
WebClient负载
方式一
WebClient也是可以负载的,与RestTemplate类似,它需要定义一个WebClient.Builder
类型的bean,并使用@LoadBalanced
标注。
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
然后使用的时候就注入WebClient.Builder
,通过它创建一个WebClient对象。WebClient进行访问时URI中的host也是需要使用服务名。
@Autowired
private WebClient.Builder webClientBuilder;
@GetMapping("webClient/hello")
public Mono<String> hello() {
return this.webClientBuilder.build().get().uri("http://hello/api/hello/abc").retrieve().bodyToMono(String.class);
}
方式二
方式二是注入一个LoadBalancerExchangeFilterFunction类型的bean,该bean将由Spring Cloud自动创建。然后在通过WebClient.Builder创建WebClient时指定该ExchangeFilterFunction,这样创建出来的WebClient也是具有负载功能的。
@Autowired
private LoadBalancerExchangeFilterFunction lbFunction;
@GetMapping("webClient/lbFunction")
public Mono<String> lbFunction() {
return WebClient.builder().baseUrl("http://hello")
.filter(lbFunction)
.build()
.get()
.uri("/api/hello/abc")
.retrieve()
.bodyToMono(String.class);
}
自动重试
Ribbon和Spring Retry一起使用的时候可以在调用远程服务失败时发起重试。需要先加入spring retry依赖。
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
然后可以通过MaxAutoRetries指定最多重试次数,比如ribbon.MaxAutoRetries=2
指定所有的Ribbon客户端在发起请求时最多重试两次,第一次调用不算在重试次数中。可以通过MaxAutoRetriesNextServer配置最多重试的服务器数量,第一个服务器是不算的。比如MaxAutoRetries=2,MaxAutoRetriesNextServer=1,那么会在第一台服务器上最多调用3次,在第二台服务器上也最多调用3次,如果还有第三台服务器,则第三台服务器不会再调用了。Ribbon默认只对GET请求进行重试,如果需要对POST请求也进行重试,则可以配置ribbon.OkToRetryOnAllOperations=true
。还可以通过retryableStatusCodes来指定需要进行重试的Http状态码,比如只希望在状态码为500或502时进行重试,则配置ribbon.retryableStatusCodes=500,502
。默认情况只要服务器通讯正常都不会重试,即状态码不管是404还是502等都不会发起重试,只有建立连接失败或者请求超时会重试。所以如果我们需要在状态码为502的时候也能发起重试则需要指定retryableStatusCodes。
ribbon.MaxAutoRetries=2
ribbon.MaxAutoRetriesNextServer=2
ribbon.OkToRetryOnAllOperations=true
ribbon.retryableStatusCodes=404,502
示例代码如下。
@GetMapping("retry/{sub}")
public String retryAny(@PathVariable("sub") String sub) {
String result = this.restTemplate.getForObject("http://hello/{sub}", String.class, sub);
return result;
}
如果Classpath下存在Spring Retry的相关jar包,但是又不希望使用它,则可以指定spring.cloud.loadbalancer.retry.enabled=false
。
参考文档
- http://cloud.spring.io/spring-cloud-static/Finchley.SR1/multi/multi_spring-cloud-ribbon.html
- https://github.com/Netflix/ribbon/wiki/Getting-Started
(注:本文是基于Spring cloud Finchley.SR1所写)
相关推荐
Ribbon是一个客户端负载均衡器,它可以很好地控制HTTP和TCP客户端的行为。
良心demo,可以再学习的过程中参考一下,官网的教程是真的需要好好琢磨的,这个可以作为辅助参考,demo采用的版本均为最新版本:springcloud2.0-Finchley.SR1版本,大神提醒我一句学习springcloud不要想的太复杂,...
springcloud入门代码基于Spring Cloud实现的Ribbon客户端负载均衡模板代码
SpringCloud的复杂均衡 属于客户端;nginx辅助均衡属于服务器端 ,restTemplate 进行RPC调用.对外使用 rest http方式。DiscoveryClient 可以自己实现一个负载均衡的算法(使用请求总数 % 服务列表个数).算法文件跟新...
本篇文章主要介绍了Spring Cloud Ribbon实现客户端负载均衡的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Ribbon负载均衡机制Ribbon实现了客户端的负载均衡,调用服务使用的是用@LoadBalanced的RestTemplate:通过对其跟踪,定位到Load
ribbon,客户端负载均衡 feign, hystrix,熔断 turbine Spring Cloud Starters 同一个服务中的多数据库支持(AOP) 全链路traceId追踪 velocity 前端模板 mybatis, pageHelper (分页), druid (连接池) redis(序列...
什么是客户端负载我们在做服务集群的时候,经常会听到负载均衡这个词,比如下图的一个架构:客户端在访问服务器的时候,中间一般会用一些硬件(F5)或软件(nginx)来作负载均衡,从而实现后端各服务器分摊请求压力...
本篇文章主要介绍了Spring Cloud Ribbon实现客户端负载均衡的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
前文 SpringCloud 简介 SpringCloud 版本选型 SpringCloud 工程构建 SpringCloud —— Eureka 注册中心 SpringCloud —— ...SpringCloud —— Ribbon 文章目录前文Ribbon 负载均衡原理Ribbon 源码分析RoundRo
能跑通的springcloud项目,已经整合eureka,ribbon,熔断器,zuul,下下源码启动eureka,再启动消费程序即可。适合初步学习
SpringCloud之三 负载均衡ribbon,使用ribbon进行负载均衡处理
SpringCloud使用Ribbon实现负载均衡https://blog.csdn.net/u012081441/article/details/80761830
spring cloud gateway的负载均衡和动态路由的实现 demo_01,demo_02,demo_03 这三个服务相当于是集群的微服务 gateway这个服务是 springcloude gateway + ribbon 做的负载均衡 gateway_01 这个服务 是动态路由的...
主要介绍了SpringCloud 服务负载均衡和调用 Ribbon、OpenFeign的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
SpringCloud——断路器(Hystrix)之Ribbon使用断路器和Feign使用断路器
下面小编就为大家带来一篇spring cloud 之 客户端负载均衡Ribbon深入理解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
32.尚硅谷_SpringCloud_Ribbon负载均衡 33.尚硅谷_SpringCloud_Ribbon核心组件IRule 34.尚硅谷_SpringCloud_自定义Ribbo的负载均衡策略(上) 35.尚硅谷_SpringCloud_自定义Ribbo的负载均衡策略(下) 36.尚硅谷_Spring...
springcloud+eureka+ribbon多服务负载均衡 springcloud+eureka+ribbon多服务负载均衡