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 {@BeanReactorLoadBalancer<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 id="restTemplate" clase ="xxx.xxx.RestTemplate"@Bean@LoadBalancedpublic 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 {@BeanReactorLoadBalancer<ServiceInstance> 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;}@Overridepublic 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的负载均衡策略
在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 {@BeanReactorLoadBalancer<ServiceInstance> 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的代码自己实现
可参考Nacos负载均衡策略_nacos负载均衡策略配置_carroll18的博客-CSDN博客