新版Eureka中不支持Ribbon,从而使用LoadBalance切换负载均衡算法


新版Eureka中不支持Ribbon,从而使用LoadBalancer切换负载均衡算法

本文参考官方手册https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#custom-loadbalancer-configuration,日期为2022年6月6日。

前言

​ 学习SpringCloud时学到切换Ribbon负载均衡算法时,教程上使用Ribbon在跟主启动类不同包下(@SpringBootApplication注解扫描不到的包)新建自己的配置类,并且创建一个Bean回传IRule。在网上查询没有对应的解决方法,因为如果添加以下包的话会报错:

1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.6.RELEASE</version>
</dependency>

​ 可能是由于新版的Eureka包中不包含Ribbon而是包含了LoadBalancer的缘故。

​ 所以要想切换负载均衡算法要使用LoadBalancer的方式切换,查询了官方手册,找到了解决办法。

解决办法

​ 根据官方文档:


3.1. Switching between the load-balancing algorithms

The ReactiveLoadBalancer implementation that is used by default is RoundRobinLoadBalancer. To switch to a different implementation, either for selected services or all of them, you can use the custom LoadBalancer configurations mechanism.

For example, the following configuration can be passed via @LoadBalancerClient annotation to switch to using the RandomLoadBalancer:

1
2
3
4
5
6
7
8
9
10
11
public class CustomLoadBalancerConfiguration {

@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
The classes you pass as @LoadBalancerClient or @LoadBalancerClients configuration arguments should either not be annotated with @Configuration or be outside component scan scope.

​ 我们需要创建一个CustomLoadBalancerConfiguration类,并复制代码。根据提示,不用配置@Configration注解,而且需要写在可被扫描的包中。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package top.zshan.springcloud.config;


import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;

/**
* @author SansZhu
* @create 2022/6/6 23:17
*/
public class CustomLoadBalancerConfiguration {

@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(loadBalancerClientFactory
.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}

​ 然后根据官方文档:


3.12. Passing Your Own Spring Cloud LoadBalancer Configuration

You can also use the @LoadBalancerClient annotation to pass your own load-balancer client configuration, passing the name of the load-balancer client and the configuration class, as follows:

1
2
3
4
5
6
7
8
9
10
@Configuration
@LoadBalancerClient(value = "stores", configuration = CustomLoadBalancerConfiguration.class)
public class MyConfiguration {

@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
  • TIP

    In order to make working on your own LoadBalancer configuration easier, we have added a builder() method to the ServiceInstanceListSupplier class.

  • TIP

    You can also use our alternative predefined configurations in place of the default ones by setting the value of spring.cloud.loadbalancer.configurations property to zone-preference to use ZonePreferenceServiceInstanceListSupplier with caching or to health-check to use HealthCheckServiceInstanceListSupplier with caching.

You can use this feature to instantiate different implementations of ServiceInstanceListSupplier or ReactorLoadBalancer, either written by you, or provided by us as alternatives (for example ZonePreferenceServiceInstanceListSupplier) to override the default setup.

You can see an example of a custom configuration here.

The annotation value arguments (stores in the example above) specifies the service id of the service that we should send the requests to with the given custom configuration.

You can also pass multiple configurations (for more than one load-balancer client) through the @LoadBalancerClients annotation, as the following example shows:

1
2
3
4
5
6
7
8
9
10
@Configuration
@LoadBalancerClients({@LoadBalancerClient(value = "stores", configuration = StoresLoadBalancerClientConfiguration.class), @LoadBalancerClient(value = "customers", configuration = CustomersLoadBalancerClientConfiguration.class)})
public class MyConfiguration {

@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
}
The classes you pass as @LoadBalancerClient or @LoadBalancerClients configuration arguments should either not be annotated with @Configuration or be outside component scan scope.

​ 示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package top.zshan.springcloud.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
* @author SansZhu
* @create 2022/5/27 21:43
*/
@Configuration
@LoadBalancerClients(@LoadBalancerClient(value = "CLOUD-PAYMENT-SERVICE",configuration = CustomLoadBalancerConfiguration.class))
public class ApplicationContextConfig {

@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}

}

​ 一定要有@LoadBalanced注解,@LoadBalancerClient可以传递自己的负载均衡客户端的配置,@LoadBalancerClients可以传递多个配置,格式要与官方文档的所说一致,value的值复制Eurake可视化界面的Application名称。

​ 启动客户端后经测试,从轮询算法切换随机算法成功。


  TOC