SpingBoot Cloud LoadBalancer问题解决

概述

记录一次解决SpringBoot Cloud之网关负载均衡的问题。

环境说明

SpringBoot: 2.3.12.RELEASE
Cloud:Hoxton.SR12
项目:spring-cloud-starter-gateway

问题描述

You already have RibbonLoadBalancerClient on your classpath. It will be used by default. As Spring Cloud Ribbon is in maintenance mode. We recommend switching to BlockingLoadBalancerClient instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or remove spring-cloud-starter-netflix-ribbon from your project.

每次项目启动,都会提示下面这个告警信息,虽然不影响使用,但是基于开发人员的通病,看见warn信息都想解决一下,于是开启了研究旅程。

解决方式

1、查找原因

首先上网查询了一下,了解了这个问题的大概来龙去脉,简单描述就是,最开始spring使用的是Spring Cloud Ribbon(基于Netflix Ribbon 实现的一套客户端的负载均衡工具),但是Netflix Ribbon已经闭源了,所以spring官方就自己开发了客户端负载均衡器spring-cloud-loadbalancer。

但是就实现的负载均衡算法而言,Ribbon更丰富,那么问题就出现了,spring保留了老的Ribbon,同时又引入了自己的loadbalancer,默认实现的是Ribbon,通过代码可以看到接口LoadBalancerClient有两个实现类,分别是Ribbon的RibbonLoadBalancerClient和loadbalancer的BlockingLoadBalancerClient,所以每次项目启动都会提示上面的信息。

接口实现

在这里插入图片描述

默认负载均衡

类BlockingLoadBalancerClientAutoConfiguration:

	@Bean
	@ConditionalOnClass(
			name = "org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient")
	@ConditionalOnProperty(value = "spring.cloud.loadbalancer.ribbon.enabled",
			matchIfMissing = true)
	public BlockingLoadBalancerClientRibbonWarnLogger blockingLoadBalancerClientRibbonWarnLogger() {
		return new BlockingLoadBalancerClientRibbonWarnLogger();
	}
告警出处
static class BlockingLoadBalancerClientRibbonWarnLogger {

		private static final Log LOG = LogFactory
				.getLog(BlockingLoadBalancerClientRibbonWarnLogger.class);

		@PostConstruct
		void logWarning() {
			if (LOG.isWarnEnabled()) {
				LOG.warn(
						"You already have RibbonLoadBalancerClient on your classpath. It will be used by default. "
								+ "As Spring Cloud Ribbon is in maintenance mode. We recommend switching to "
								+ BlockingLoadBalancerClient.class.getSimpleName()
								+ " instead. In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false` or "
								+ "remove spring-cloud-starter-netflix-ribbon from your project.");
			}
		}

	}

想着应该官方想推广的自己的负载均衡,但是又不太成熟,就导致了这种结果。

2、解决问题

根据以上信息及告警提示,相信大家已经知道怎么解决这个问题,对,就是在配置文件中添加以下配置:

spring: 
  cloud:
    loadbalancer:
      ribbon: 
        enabled: false 

经测试,以上可以解决该问题。

想着到这已经结束了,但是警告提示中用了“or”,就是说用另一种方法也是可以的,于是就尝试用第二种方法试了一下。

通过查看包依赖,发现spring-cloud-starter-netflix-ribbon在spring-cloud-start-netflix-eureka-client中,于是在pom中排除点spring-cloud-starter-netflix-ribbon。

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

启动,不出意外的出意外了。

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method loadBalancerWebClientBuilderBeanPostProcessor in org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration required a bean of type 'org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction' that could not be found.


Action:

Consider defining a bean of type 'org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction' in your configuration.

提示没有配置DeferringLoadBalancerExchangeFilterFunction,这就复杂了,以为简单排除了依赖就没问题,谁知道又出现了其他问题。

查看了确实也依赖了官方自己的loadbalancer,为什么还在使用默认的。

 <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-loadbalancer</artifactId>
      <version>2.2.9.RELEASE</version>
      <scope>compile</scope>
 </dependency>

于是又将第一种通过配置的方式,将ribbon禁用,测试了,好使。

由此得知,虽然移除了spring-cloud-starter-netflix-ribbon,但是还在使用ribbon的功能,这与提示的信息明显不符。

突然想到了项目中默认配置Ribbon的地方,BlockingLoadBalancerClientAutoConfiguration其实总开关还是在这个地方,移除spring-cloud-starter-netflix-ribbon,按说已经移除了这部分逻辑,但是项目却出现了问题,是不是某个地方还有配置。

查看BlockingLoadBalancerClientAutoConfiguration发现一行代码:


@ConditionalOnClass(
			name = "org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient")

注解的意思是当项目中存在某个类时才会使标有该注解的类或方法生效,意思就是项目中还有RibbonLoadBalancerClient这个类,在开始的时候说过,这个类其实就是Ribbon的实现类,也就是这个类还存在。

这个类其实在spring-cloud-netflix-ribbon-2.2.9.RELEASE.jar中,在包依赖中查找这个包,确实还有这个jar包。

包大概的结构:

spring-cloud-start-netflix-eureka-client
---- spring-cloud-starter-netflix-ribbon
--------  spring-cloud-netflix-ribbon
---- spring-cloud-starter-netflix-archaius
--------  spring-cloud-netflix-ribbon

这样问题就清晰了,于是又排除了archaius包下的ribbon,重启,成功!!!

总结

1、你看到的不一定是对的,要分析根本原因,才能解决根本问题。

2、不要怕尝试,多试一次可能离结果就进一步。

3、只要坚持不懈,问题总能解决。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值