ribbon负载均衡服务调用
概叙:
Ribbon其实就是一个软负载均衡的客户端
组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例
切记:是在客户端,也就是说在用户(服务请求者)
依赖:
最新版eureka不用导入,因为已经引入了ribbon,大家可以看下
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
核心组件:
IRule:
有一系列特定算法让客户从服务列表选取一个访问的服务
- com.netflix.loadbalancer.RoundRobinRule 轮询
- com.netflix.loadbalancer.RandomRule 随机
- com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试
- WeightedResponseTimeRule 对RoundRobinRule的扩展,响应速度越快的实例选择权重越大,越容易被选择
- BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务
- AvailabilityFilteringRule 先过滤掉故障实例,再选择并发较小的实例
- ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器
如何使用?
首先我们要明白一点,在看源码的注释也应该看得到
所以我们第一步就是:在能扫描到的包外面定义一个专门放rule的包,
这样让他扫描不到
再新建这样一个规则类:
/**
* 自定义Rule
* Created by IntelliJ IDEA.
* User: kt
* Date: 2020/12/2 22:27
*
* @author kt
*/
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
//定义为随机
return new RandomRule();
}
}
再在启动类加上注解@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
标明服务名和自定义rule的class
/**
* Created by IntelliJ IDEA.
* User: kt
* Date: 2020/11/25 19:40
*
* @author kt
*/
@EnableEurekaClient
@SpringBootApplication
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
配置完毕!可以开始测试
rule的关系结构:
轮询rule(RoundRobinRule)的实现原理:
负载均衡算法:rest接口第几次请求数 % 服务器集群总数量 =实际调用服务器的下表 重启后归1
public Server choose(ILoadBalancer lb, Object key) {
//如果负载均衡算法为空 就返回空了
if (lb == null) {
log.warn("no load balancer");
return null;
} else {
Server server = null;
int count = 0;
while(true) {
//如果服务为空且符合条件
if (server == null && count++ < 10) {
//拿到所有或者的机器/服务
List<Server> reachableServers = lb.getReachableServers();
//所有的
List<Server> allServers = lb.getAllServers();
//up的数量
int upCount = reachableServers.size();
//所有服务的数量
int serverCount = allServers.size();
if (upCount != 0 && serverCount != 0) {
//把服务的总数传入
int nextServerIndex = this.incrementAndGetModulo(serverCount);
server = (Server)allServers.get(nextServerIndex);
if (server == null) {
Thread.yield();
} else {
if (server.isAlive() && server.isReadyToServe()) {
return server;
}
server = null;
}
continue;
}
log.warn("No up servers available from load balancer: " + lb);
return null;
}
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: " + lb);
}
return server;
}
}
}
private int incrementAndGetModulo(int modulo) {
//juc 的自旋锁
int current;
int next;
do {
current = this.nextServerCyclicCounter.get();
next = (current + 1) % modulo;
//比较并交换 如果有其他线程干扰 就继续循环 如果没有修改就返回true
} while(!this.nextServerCyclicCounter.compareAndSet(current, next));
return next;
}
搞定收工,有需要源码联系博主哦!