在这一章我们要学习ribbon如何做负载均衡,从我上面的服务消费者和服务提供者的案例来看.由于上诉案例中只有一个数据库,所以我们在模拟负载均衡场景的时候应该要考虑多个数据库.浅显的将,就是我们在查询数据库服务时,我们希望服务器不会总是从一个数据库上查询.而是从不同的数据库中查询相同的数据,这样能减少数据库的压力.
首先,我们先多建两个数据库,数据库中的数据都是一样的.但是为了看出数据库的差异,我们需要知道当前的数据是从哪一个数据库中查询,所以说我们会在每个数据库后面的字段加上当前的数据库名.如下图:
当然我们也需要多准备两个服务提供者端口:8002,8003.分别绑定对应的数据库如下图:
点击网址查看eureka7001.com/7001
我们可以发现这里已经有了三个实例
上诉操作完后,我们在浏览器中输入网址localhost/consumer/dept/list.
就能查看数据库中的数据.而且每次刷新网页就能是从不同的数据库中查询出来的,
但是刷新几次后我们会发现,这是一个有规律的查询方式.
这里就又要谈到一个接口IRule.这个接口里面有很多写好的一些负载均衡算法:
当然像我们上面的那种有规律的查询就是这里方法中的RoundRobinRule.策称为轮询规则.源码如下:
其中还有一些常用的比如随机算法,
还有一种是WeightedResponseTimeRule权重算法,计算加权
RetryRule:重试策略,会先按照轮询获取服务,如果服务获取失败,则会在指定的时间内进行重试.
AvailabilityFilteringRule:会先过滤掉崩溃的服务,跳闸的服务(访问故障).对剩下的进行轮询
这些是源码中提供给我们的一些策略,当然我们可以自己自定义一些算法.
步骤如下:
我们需要在不同于主启动类的包下新建一个包比如:
第一步:需要在ConfigBean中注册我们自定义的策略,然后添加@Bean,交由spring托管.
@Bean
public IRule MyIRule(){
return new MyRule();//默认的是轮询,现在我们自定义的就是我们自己写的算法
}
第二步: 在主启动类中添加注释@@RibbonClient,在微服务加载的时候就能区域加载我们自定义的Ribbon类
//在微服务加载的时候就能区域加载我们自定义的Ribbon类
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = MyRule.class)
第三步:编写自定义策略代码:
package com.qiu.myRule;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
public class MyRule extends AbstractLoadBalancerRule {
//要求就是每个机器访问5次,然后换下一个服务(3个)
//大于三个就置于0
//total=0.默认的也是0,如果=5我们就指向下一个节点
//index=0,默认0,如果total=5,那么index+1,如果index=3,那么就将index置为0
private int total = 0;//被调用的次数
private int currentIndex = 0;//当前是谁在提供服务
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List<Server> upList = lb.getReachableServers();//获得活着的服务
List<Server> allList = lb.getAllServers();//获得全部的服务
int serverCount = allList.size();
if (serverCount == 0) {
/*
* No servers. End regardless of pass, because subsequent passes
* only get more restrictive.
*/
return null;
}
// int index = chooseRandomInt(serverCount);//生成区间随机数
// server = upList.get(index);//从活着的服务中随机获取一个
//==============================================
if(total<5){
server = upList.get(currentIndex);
total++;
}else {
total=0;
currentIndex++;
if (currentIndex>upList.size()){//当前的服务(第几个)大于最大的,则将服务置为最开始的那一个
currentIndex=0;
}
server = upList.get(currentIndex);//从活着的服务中获取指定的服务进行操作
}
//=======================================
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
server = null;
Thread.yield();
}
return server;
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
这里的代码可以借鉴源码给予我们的再进行修改即可.