Nacos 本身里面就内置了Rabbion, 所以 不需要额外添加
添加@LoadBalanced注解:
Rabbion 内置的有好几种 负载均衡器 可以根据业务去选择,我们一般不会额外配置 都是默认的轮询,因为我们是基于docker发布的 大家的资源都是平等的
若真的想额外配置 就在Bean IOC容器里面注册一个规则,这个规则可以是自己Rabbion内置的 也可以是自己手写的
自定义规则:
package com.***.rule;
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.DynamicServerListLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class MyRule extends AbstractLoadBalancerRule {
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Autowired
private NacosServiceManager nacosServiceManager;
//JUC 原子类
private static AtomicInteger count = new AtomicInteger(0);
@SneakyThrows
@Override
public Server choose(Object key) {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
String group = this.nacosDiscoveryProperties.getGroup();
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
String name = loadBalancer.getName();
NamingService namingService = nacosServiceManager.getNamingService();
List<Instance> instances = namingService.selectInstances(name, group, true);
if (CollectionUtils.isEmpty(instances)) {
log.warn("no instance in service {}", name);
return null;
}
Instance maxInstance = instances.stream().max(Comparator.comparing(Instance::getWeight)).get();
Instance minInstance = instances.stream().min(Comparator.comparing(Instance::getWeight)).get();
//一定有实例,根据我们自己的算法给出一个instance
int count1 = count.incrementAndGet();
int mod = count1 % 5 ; //取模运算 5,10,15,20,25 ......
if(mod == 0){
log.debug("{}->小的,权重: 1",count1);
return new NacosServer(minInstance);
} else{
log.debug("{}->大的 权重:5",count1);
return new NacosServer(maxInstance);
}
}
}
package com.***.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
// RestTemplate 默认将一级目录作为主机名,
// 加上@LoadBalanced 之后,就把以及目录作为服务名,通过该服务名能够抓取到该服务名下面的所有实例数据,就可以负载均衡了
// @LoadBalanced 会将RestTemplate 请求的url中的一级目录作为服务名,然后去服务注册中心Nacos抓取对应的ip和端口
// 替换成真正的ip和端口 http://nacos-a/api/a ==> http://192.168.21.43:8080/api/a ,然后再去调用对应的接口
//http://nacos-a/api/a
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-cloud-alibaba-root</artifactId>
<groupId>com.beiyou</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>ribbion-app</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
使用自己的规则(两种配置方式):
① 使用注解配置:(一般不用)
package com.***.config;
import com.beiyou.rule.MyRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Configuration;
@Configuration
//全局设置负载规则。默认是轮询
//@RibbonClients(defaultConfiguration = RoundRobinRule.class )
//设置某一个服务负载规则,特殊配置
//@RibbonClient(name="nacos-a",configuration = MyRule.class)
public class RabbionConfig {
/**
* 全局配置
* 指定负载均衡策略
*/
//@Bean
public MyRule rule(){
//默认轮询
// return new RoundRobinRule();
//return new RandomRule();
return new MyRule();
}
//@Bean
public RoundRobinRule rule2(){
//默认轮询
return new RoundRobinRule();
}
}
② 基于配置文件配置,调用指定微服务提供的服务时,使用对应的负载均衡算法 【推荐使用】
#配置具体某一个服务个性化规则
nacos-b.ribbon.NFLoadBalancerRuleClassName=com.beiyou.config.MyRule
##配置全局的负载均衡规则 (不生效)
default.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
如果同时应用了以上两种方式去配置负载均衡,注解的优先级更高,则以注解为准
因为配置文件的加载顺序在注解之前,后加载的配置会覆盖先前配置。
推荐使用配置文件,可以放进nacos,比较灵活。
Ribbon里面可以配置 超时机制:(了解)版本不一样 默认的超时时间不一样
ribbon.connect-timeout=2000
ribbon.read-timeout=5000
ribbon.ConnectTimeout :连接建立的超时时间 (我第一次跟你握手时 超过两秒 你还没有跟我握手,也就是 超过两秒 还没有响应 ,这就认为 是超时了)
ribbon.ReadTimeout : 服务器读取数据的超时时间(第一次握手 成功了 ,我现在要跟你要数据 结果等了5秒 还没有数据,就认为是超时了)
在 Spring Cloud 中针对特定的服务实例具象化配置:
nacos-a.ribbon.connect-timeout=2000
nacos-a.ribbon.read-timeout=5000