Nacos 2021 不再集成 Ribbon,建议使用spring cloud loadbalancer
引入
引入依赖spring cloud loadbalancer
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-loadbalancer</artifactId>
- </dependency>
RestTemplate集成
启动类的restTemplate bean方法添加@LoadBalanced注解
- @Bean
- @LoadBalanced
- public RestTemplate restTemplate(){
- return new RestTemplate();
- }
Spring Cloud Balancer中实现了轮询RoundRobinLoadBalancer和随机数RandomLoadBalancer两种负载均衡算法
默认情况下的负载均衡为轮询RoundRobinLoadBalancer
如果我们需要改成随机RandomLoadBalancer,可以自定义
新建文件 CustomLoadBalancerConfiguration.java
- package com.itmuch.contentcenter.rule;
-
- import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
- import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer;
- 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.RoundRobinLoadBalancer;
- import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
- import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.env.Environment;
-
- @Configuration
- public class CustomLoadBalancerConfiguration {
-
- @Bean
- ReactorLoadBalancer<ServiceInstance> loadBalancer(Environment environment,
- LoadBalancerClientFactory loadBalancerClientFactory, NacosDiscoveryProperties nacosDiscoveryProperties) {
- String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
-
-
- //轮询加载,默认就是这个
- /*return new RoundRobinLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,
- ServiceInstanceListSupplier.class),name);*/
-
- //返回随机轮询负载均衡方式
- return new RandomLoadBalancer(loadBalancerClientFactory.
- getLazyProvider(name, ServiceInstanceListSupplier.class),
- name);
-
- //nacos的负载均衡策略,按权重分配
- /*return new NacosLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,
- ServiceInstanceListSupplier.class),
- name, nacosDiscoveryProperties);*/
- }
- }
-
然后在启动类加注解@LoadBalancerClient,参数name为spring.application.name,configuration为上面自定义的类
- package com.itmuch.contentcenter;
-
- import com.itmuch.contentcenter.rule.CustomWeightLoadBalancerConfiguration;
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.cloud.client.loadbalancer.LoadBalanced;
- import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
- import org.springframework.context.annotation.Bean;
- import org.springframework.web.client.RestTemplate;
- import tk.mybatis.spring.annotation.MapperScan;
-
- // 扫描mybatis哪些包里面的接口
- @MapperScan("com.itmuch")
- @SpringBootApplication
- @LoadBalancerClient(name = "user-center",configuration = CustomLoadBalancerConfiguration.class)
- public class ContentCenterApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ContentCenterApplication.class, args);
- }
-
- //在spring容器装载哪一个对象,类型为RestTemplate 名称为restTemplate
- //
- @Bean
- @LoadBalanced
- public RestTemplate restTemplate(){
- return new RestTemplate();
- }
- }
如果我们想自定义策略。可以参考RoundRobinLoadBalancer类自己实现
以下为调3次轮换的自定义策略
CustomWeightLoadBalancerConfiguration.java
- package com.itmuch.contentcenter.rule;
-
- import org.springframework.cloud.client.ServiceInstance;
- 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.context.annotation.Configuration;
- import org.springframework.core.env.Environment;
-
- @Configuration
- public class CustomWeightLoadBalancerConfiguration {
-
- @Bean
- ReactorLoadBalancer
weightloadBalancer(Environment environment, - LoadBalancerClientFactory loadBalancerClientFactory) {
- String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
-
- //返回自定义负载均衡方式
- return new WeightLoadBalancer(loadBalancerClientFactory.
- getLazyProvider(name, ServiceInstanceListSupplier.class),
- name);
-
- }
- }
-
WeightLoadBalancer.java
核心在于重载实现ReactorServiceInstanceLoadBalancer类的choose方法
- package com.itmuch.contentcenter.rule;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.beans.factory.ObjectProvider;
- import org.springframework.cloud.client.ServiceInstance;
- import org.springframework.cloud.client.loadbalancer.DefaultResponse;
- import org.springframework.cloud.client.loadbalancer.EmptyResponse;
- import org.springframework.cloud.client.loadbalancer.Request;
- import org.springframework.cloud.client.loadbalancer.Response;
- import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
- import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
- import reactor.core.publisher.Mono;
-
- import java.util.List;
-
- public class WeightLoadBalancer implements ReactorServiceInstanceLoadBalancer {
- private static final Log log = LogFactory.getLog(WeightLoadBalancer.class);
- private int total = 0; // 被调用的次数
- private int index = 0; // 当前是谁在提供服务
-
- private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
- private String serviceId;
-
- public WeightLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
- this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;
- this.serviceId = serviceId;
- }
-
- @Override
- public Mono<Response<ServiceInstance>> choose(Request request) {
- ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable();
- return supplier.get().next().map(this::getInstanceResponse);
- }
-
- //每个服务访问3次,然后换下一个服务
- private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
- log.info("进入自定义负载均衡");
- if (instances.isEmpty()) {
- return new EmptyResponse();
- }
-
- log.info("每个服务访问3次后轮询");
- int size = instances.size();
-
- ServiceInstance serviceInstance = null;
- while (serviceInstance == null) {
- System.out.println("===");
- if (total < 3) {
- serviceInstance = instances.get(index);
- total++;
- } else {
- total = 0;
- index++;
- if (index >= size) {
- index = 0;
- }
- serviceInstance = instances.get(index);
- }
- }
- return new DefaultResponse(serviceInstance);
- }
-
-
- }
最后跟上面一样,启动类加注解@LoadBalancerClient,指向自定义的config
@LoadBalancerClient(name = "user-center",configuration = CustomWeightLoadBalancerConfiguration.class)
在nacos定义了负载均衡策略类NacosLoadBalancer,我们可以直接使用
使用配置类方式
- package com.itmuch.contentcenter.rule;
-
- import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
- import com.alibaba.cloud.nacos.loadbalancer.NacosLoadBalancer;
- 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.RoundRobinLoadBalancer;
- import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
- import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.env.Environment;
-
- @Configuration
- public class CustomLoadBalancerConfiguration {
-
- @Bean
- ReactorLoadBalancer
loadBalancer(Environment environment, - LoadBalancerClientFactory loadBalancerClientFactory, NacosDiscoveryProperties nacosDiscoveryProperties) {
- String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
-
-
- //nacos的负载均衡策略,按权重分配
- return new NacosLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,
- ServiceInstanceListSupplier.class),
- name, nacosDiscoveryProperties);
- }
- }
-
然后还是启动类加注解@LoadBalancerClient,指向自定义的config
@LoadBalancerClient(name = "user-center",configuration = CustomLoadBalancerConfiguration.class)
配置文件方式
- #开启nacos的负载均衡策略
- spring.cloud.loadbalancer.nacos.enabled=true
如果需要根据nacos的权重进一步自定义,可参考NacosLoadBalancer的代码自己实现