SpringCloud(七)——Ribbon实现负载均衡
环境搭建
1、新建两个数据表
db02
和db03
db02
CREATE DATABASE `db02`;
USE `db02`;
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`deptno` BIGINT(20) NOT NULL AUTO_INCREMENT,
`dname` VARCHAR(60) DEFAULT NULL,
`db_source` VARCHAR(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());
db03
CREATE DATABASE `db03`;
USE `db03`;
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`deptno` BIGINT(20) NOT NULL AUTO_INCREMENT,
`dname` VARCHAR(60) DEFAULT NULL,
`db_source` VARCHAR(60) DEFAULT NULL,
PRIMARY KEY (`deptno`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO dept(dname,db_source) VALUES('开发部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('人事部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('财务部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('市场部',DATABASE());
INSERT INTO dept(dname,db_source) VALUES('运维部',DATABASE());
2、新建两个提供者模块
1)把8001的依赖复制到这两个模块里
2)把8001的java目录下的所有文件复制到8002和8003里
修改主启动类
3)把resources目录下的所有文件复制到这两个模块里
再修改application.yaml里的配置
环境搭建完成
体验Ribbon负载均衡——轮询
1、先启动springcloud-eureka-7001eureka服务注册中心
2、再启动springcloud-provider-dept-8001,springcloud-provider-dept-8002和springcloud-provider-dept-8003服务提供者,让它们注册进eureka服务注册中心,提供服务
3、访问localhost:7001 测试注册成功
4、最后启动springcloud-consumer-dept-80消费者,注册进eureka服务器注册中心,索取服务
5、访问多次 http://localhost/consumer/dept/list
根据以上再理解
随机轮询
1、在主启动类同级下新建一个rule包(轮询包)
2、在rule包下新建MyRule类(轮询类)
package com.study.rule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRule {
@Bean
public IRule myRule() {
/**
* IRule:
* RoundRobinRule 轮询策略
* RandomRule 随机策略
* AvailabilityFilteringRule : 会先过滤掉,跳闸,访问故障的服务~,对剩下的进行轮询~
* RetryRule : 会先按照轮询获取服务~,如果服务获取失败,则会在指定的时间内进行,重试
*/
return new RandomRule();//使用随机策略
//return new RoundRobinRule();//使用轮询策略
//return new AvailabilityFilteringRule();//使用轮询策略
//return new RetryRule();//使用轮询策略
}
}
3、在主启动类中添加
@RibbonClient
注解开启负载均衡即可实现随机轮询
自定义轮询
1、在rule包下新建MyRandomRule类
package com.study.rule;
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 MyRandomRule extends AbstractLoadBalancerRule {
public MyRandomRule() {
}
/**
* 每个服务访问5次则换下一个服务(总共3个服务)
* <p>
* total=0,默认=0,如果=5,指向下一个服务节点
* index=0,默认=0,如果total=5,index+1
*/
//=====================================
private int total = 0;//被调用的次数
private int currentIndex = 0;//当前是谁在提供服务
//===================================
@SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
} else {
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) {
return null;
}
//int index = this.chooseRandomInt(serverCount);//生成区间随机数
//server = (Server)upList.get(index);//从或活着的服务中,随机获取一个
//=====================自定义代码=========================
if (total < 5) { //如果被调用的次数小于5
server = upList.get(currentIndex); //在活着的服务中获取当前提供服务提供者
total++;
} else { //当前服务被调用5次的时候
total = 0; //被调用次数重新置为0
currentIndex++; //当前服务提供者++,指向下一个服务提供者
if (currentIndex >= upList.size()) {//假设服务提供者大于当前活着的服务
currentIndex = 0;//把当前服务提供者置为0
}
server = upList.get(currentIndex);//从活着的服务中,获取指定的服务来进行操作
}
//======================================================
if (server == null) {
Thread.yield();
} else {
if (server.isAlive()) {
return server;
}
server = null;
Thread.yield();
}
}
return server;
}
}
protected int chooseRandomInt(int serverCount) {
return ThreadLocalRandom.current().nextInt(serverCount);
}
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
2、修改MyRule