第一步添加依赖
如果添加过
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
无需依赖
第二步写注解 @LoadBalanced
在RestTemplate的ioc上面写一下
代码如下
//在容器中,创建一个对象
@Bean //这是Spring的注解,可以在相关的页面自动注入。
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
Ribbon自带整合发现。所以上一章节的DiscoveryClient就不需要了。替换代码如下,
原来的
private final DiscoveryClient discoveryClient;
discoveryClient.getInstances("user-center");
现在的
this.restTemplate.getForObject(
"http://user-center/users/{id}",
UserDTO.class,
userId);
//user-center 为模块名称,自动实现负载均衡。
这就使用好了
以下是配置的总结,也就是根据实际需求来定制负载的请求。
首先讲一下java代码配置
第一步
新建一个包、路径为com.liuyun.contentcenter.configuration
新建一个类 UserCenterRibbonConfiguration.java
内容如下:可以直接复制使用。
@Configuration
@RibbonClient(configuration = RibbonConfiguration.class) //不是全局的配置。
@RibbonClients(defaultConfiguration = RibbonConfiguration.class) // 是全局的配置。
public class UserCenterRibbonConfiguration {
}
RibbonConfiguration //这个类在下面配置
第二步
新建一个包、路径为main/java/ribbonconfiguration/
新建一个类 RibbonConfiguration.java 注意这个类不在com 包下面,这样做是为了配置冲突。
内容如下:可以直接复制使用。
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
也可以继承相关类IRule等等实现自定义规则
拓展: 实现Ribbon支持nacos的权重,代码如下
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {
//
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
//读取配置文件
}
@Override
public Server choose(Object o) {
try {
BaseLoadBalancer loadBalancer = (BaseLoadBalancer)this.getLoadBalancer();
//想要请求的微服务名称
String name = loadBalancer.getName();
//实现服务发现的相关api
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
//nacos server自动实现基于权重的算法。
Instance instance = namingService.selectOneHealthyInstance(name);
log.info("port = {} , instance = {}" ,instance.getPort(),instance);
//通过NacosServer可以把Instance转换成Server
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
return null;
}
}
}
在下面配置
@Configuration
public class RibbonConfiguration {
@Bean
public IRule ribbonRule(){
return new NacosWeightedRule();
}
}
以下代码是扩展Ribbon:支持Nacos同集群优先调用的配置
可以在application.yml文件里面加入。
spring:
cloud:
nacos:
metadata:
# 自己这个实例的版本
version: v1
# 允许调用的提供者版本
target-version: v1
在调用者的代码里面配置。
@Slf4j
public class NacosFinalRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public Server choose(Object key) {
// 负载均衡规则:优先选择同集群下,符合metadata的实例
// 如果没有,就选择所有集群下,符合metadata的实例
// 1. 查询所有实例 A
// 2. 筛选元数据匹配的实例 B
// 3. 筛选出同cluster下元数据匹配的实例 C
// 4. 如果C为空,就用B
// 5. 随机选择实例
try {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
String targetVersion = this.nacosDiscoveryProperties.getMetadata().get("target-version");
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String name = loadBalancer.getName();
NamingService namingService = this.nacosDiscoveryProperties.namingServiceInstance();
// 所有实例
List<Instance> instances = namingService.selectInstances(name, true);
List<Instance> metadataMatchInstances = instances;
// 如果配置了版本映射,那么只调用元数据匹配的实例
if (StringUtils.isNotBlank(targetVersion)) {
metadataMatchInstances = instances.stream()
.filter(instance -> Objects.equals(targetVersion, instance.getMetadata().get("version")))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(metadataMatchInstances)) {
log.warn("未找到元数据匹配的目标实例!请检查配置。targetVersion = {}, instance = {}", targetVersion, instances);
return null;
}
}
List<Instance> clusterMetadataMatchInstances = metadataMatchInstances;
// 如果配置了集群名称,需筛选同集群下元数据匹配的实例
if (StringUtils.isNotBlank(clusterName)) {
clusterMetadataMatchInstances = metadataMatchInstances.stream()
.filter(instance -> Objects.equals(clusterName, instance.getClusterName()))
.collect(Collectors.toList());
if (CollectionUtils.isEmpty(clusterMetadataMatchInstances)) {
clusterMetadataMatchInstances = metadataMatchInstances;
log.warn("发生跨集群调用。clusterName = {}, targetVersion = {}, clusterMetadataMatchInstances = {}", clusterName, targetVersion, clusterMetadataMatchInstances);
}
}
Instance instance = ExtendBalancer.getHostByRandomWeight2(clusterMetadataMatchInstances);
return new NacosServer(instance);
} catch (Exception e) {
log.warn("发生异常", e);
return null;
}
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}
负载均衡的算法,是上面类的 ExtendBalancer
public class ExtendBalancer extends Balancer {
/**
* 根据权重,随机选择实例
*
* @param instances 实例列表
* @return 选择的实例
*/
public static Instance getHostByRandomWeight2(List<Instance> instances) {
return getHostByRandomWeight(instances);
}
}
下面是配置文件方式的配置。
第一种是默认的轮询策略 RoundRobinRule
第二种是 RandomRule(随机策略) 可以在application.yml文件里面加入。
ribbon:
eager-load:
enabled: true
clients: user-center
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
其实如果公司不大的话,普通的配置足以应付日常的负载了,推荐使用配置文件配置。一下是相关配置的key
NFLoadBalancerClassName
NFLoadBalancerRuleClassName IRule子类
NFLoadBalancerPingClassName IPing子类
NIWSServerListClassName
NIWSServerListFilterClassName