文章目录
- 一、概念:ribbon
- 二、ribbon用处
- 三、实现
- 3.1 客户端配置:springcloud-consumer-dept-80使用Ribbon
- 第一步:首先80项目要添加两个依赖
- 第二步:配置:建立配置类ConfigBean
- 第三步:配置yml
- 第四步:配置主类:DeptConsumer_80
- 第五步:书写DeptConsumerController
- 第一步:创建另外两个数据库:db02、db03
- 第二步:创建另外两个服务提供者:8002、8003
- 第三步:Ribbon自定义均衡算法
- 只需要在80项目的config类里面注册Bean即可
- 优化上一步
- 第一步:编写配置类
- 第二步:写自定义方法
一、概念:ribbon
二、ribbon用处
三、实现
3.1 客户端配置:springcloud-consumer-dept-80使用Ribbon
第一步:首先80项目要添加两个依赖
<!--Ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<!--导入Ribbon的同时要导入erueka,因为它要发现服务从那里来-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
第二步:配置:建立配置类ConfigBean
@Bean
@LoadBalanced //Ribbon,只要加了这个注解,这个RestTemplate就变成了负载均衡
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
由于我们消费者客户端是利用RestTemplate来进行服务的读取,所以我们让RestTemplate实现负载均衡,只需要加一个注解即可@LoadBalanced
第三步:配置yml
server:
port: 80
#Eureka配置
eureka:
client:
register-with-eureka: false #不向eureka中注册自己
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
第四步:配置主类:DeptConsumer_80
//Ribbon和 Eureka整合以后,客户端可以直接调用,不用关心IP地址和端口号
@SpringBootApplication
//@EnableEurekaClient //在服务启动后自动注册到Eureka中
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class, args);
}
}
第五步:书写DeptConsumerController
最后还有一个问题,就是我们的RestTemplate实现了负载均衡,那么怎么体现它呢?我们现在就只是在它身上加了一个注解,那肯定是不行的,我们还要改变RestTemplate的请求路径,让其自动选择,而不是写死,地址应该是一个变量,通过服务名来访问;不是Eureka名
//private static final String REST_URL_PREFIX = "http://localhost:8001";
//用Ribbon做负载均衡的时候不应该写它,不应该写死,地址应该是一个变量,通过服务名来访问
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
最后启动7001、7002、7003项目后再启动8001项目,等8001项目注册到它们3个中后启动80项目
然后访问 http://localhost/consumer/dept/list 可以看到正常返回结果,当然了,在这里也看不出负载均衡,所以下面会配置多个服务提供者和多个数据库,来测试负载均衡的效果。
3.2 使用Ribbon实现负载均衡
第一步:创建另外两个数据库:db02、db03
第二步:创建另外两个服务提供者:8002、8003
直接新建两个子model,然后把8001的所有文件全部拷贝(提供相同的服务),一摸一样的,然后更改一下配置文件即可
pom.xml依赖
application.yml的端口号,对应的数据库,还有instance-id,例如:instance-id: springcloud-provider-dept8002
注意:下面的这个服务ID不要改
spring:
application:
name: springcloud-provider-dept # 3个服务名称一致是前提
然后,启动
springcloud-config-eureka-7001
springcloud-config-eureka-7002
springcloud-config-eureka-7003
springcloud-provider-dept-8001
springcloud-provider-dept-8002
springcloud-provider-dept-8003
springcloud-consumer-dept-80
然后访问http://localhost/consumer/dept/list ,多访问几次,查询的数据没变,但是数据库变了
第三步:Ribbon自定义均衡算法
你会发现是轮询,就是每个服务轮流来,这也Ribbon的默认算法
里面有个接口非常重要:IRule,基本上全部的均衡算法都实现了这个接口
里面有这么多均衡算法,因为默认是轮询算法,也就是RoundRobinRule,那我们要怎么使用别的算法呢?
只需要在80项目的config类里面注册Bean即可
//IRule
//RoundRobinRule:轮询
//RandomRule:随机
//AvailabilityFilteringRule:会先过滤掉跳闸、访问故障的服务~,对剩下的进行轮询
//RetryRule:会先按照轮询获取服务,如果服务获取失败,则会在指定的时间内进行重试
@Bean
public IRule myRule() {
return new RandomRule(); //默认为轮询,现在我们使用随机的
}
然后启动80项目,访问http://localhost/consumer/dept/list,多访问几次,发现每次出现的数据库都没规律可循
优化上一步
我们要学会自定义负载均衡算法,为了体现我们使用了自定义的负载均衡算法,我们建包不建在主启动类的同级目录(官方建议)
把刚刚写在ConfigBean里面的Bean注释掉,我们来模仿它的算法写一个自己的算法
第一步:编写配置类
在主类配置为了扫描到配置类
第二步:写自定义方法
public class KuangRandomRule extends AbstractLoadBalancerRule {
//每个机器,访问5次,换下一个服务(总共3个)
//total = 0 默认=0,如果=5,我们指向下一个服务结点
//index = 0 默认=0,如果total=5,那么index+1,
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) {
return null;
}
//=============================================================
if (total < 5) {
total++;
} else {
total = 0;
currentIndex++;
if (currentIndex >= serverCount) {
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) {
}
}
修改自定义的配置类
@Configuration
public class WuRule {
@Bean
public IRule myRule() {
return new KuangRandomRule(); //默认为轮询,现在试使用自己自定义的
}
}
然后重启80项目,访问http://localhost/consumer/dept/list,多访问几次,可以发现访问的服务每5次切换一下