0
点赞
收藏
分享

微信扫一扫

【设计模式】Head First 设计模式——抽象工厂模式 C++实现

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 id="restTemplate" clase ="xxx.xxx.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<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;
}

@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的负载均衡策略

在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<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博客

举报

相关推荐

0 条评论