1.Ribbon配置初步
servicecloud-consumer-dept-80工程 修改pom.xml文件
<!-- Ribbon相关 -->
<!—springboot2.0—>
<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-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
修改application.yml 追加eureka的服务注册地址
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
对ConfigBean进行新注解@LoadBalanced 获得Rest时加入Ribbon的配置
package com.goolecloud.springcoud.cfgBean;
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 ConfigBen {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
主启动类ServicecloudConsumerDept80Application添加@EnableEurekaClient
修改DeptController_Consumer客户端访问类
将private static final String REST_URL_PREFIX = "http://localhost:8001" ;改为
private static final String REST_URL_PREFIX = "http://SERVICECLOUD-DEPT" ;SERVICECLOUD-DEPT 为服务名称
先启动3个eureka集群后,再启动servicecloud-provider-dept-8001并注册进eureka
启动servicecloud-consumer-dept-80
启动microservicecloud-consumer-dept-80
测试
http://localhost/consumer/dept/get/1
http://localhost/consumer/dept/list
http://localhost/consumer/dept/add?dname=大数据部
2.Ribbon负载均衡
参考servicecloud-provider-dept-8001,新建两份,分别命名为8002,8003
新建8002/8003数据库,各自微服务分别连各自的数据库(
DROP DATABASE IF EXISTS cloudDB02;
CREATE DATABASE cloudDB02 CHARACTER SET UTF8;
USE cloudDB02;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR (60),
db_source VARCHAR (60)
);
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());
SELECT * FROM dept;
DROP DATABASE IF EXISTS cloudDB03;
CREATE DATABASE cloudDB03 CHARACTER SET UTF8;
USE cloudDB03;
CREATE TABLE dept
(
deptno BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
dname VARCHAR (60),
db_source VARCHAR (60)
);
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());
SELECT * FROM dept;
)
启动servicecloud-consumer-dept-80
客户端通过Ribbo完成负载均衡并访问上一步的Dept微服务
http://localhost/consumer/dept/list
注意观察看到返回的数据库名字,各不相同,负载均衡实现
3.Ribbon核心组件IRule
IRule:根据特定算法中从服务列表中选取一个要访问的服务 RoundRobinRule 轮询 RandomRule 随机 AvailabilityFilteringRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务, 还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问 WeightedResponseTimeRule 根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。 刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够, 会切换到WeightedResponseTimeRule RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务 BestAvailableRule 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务 ZoneAvoidanceRule 默认规则,复合判断server所在区域的性能和server的可用性选择服务器 | |
4.Ribbon自定义
修改servicecloud-consumer-dept-80
主启动类添加@RibbonClient
在启动该微服务的时候就能去加载我们的自定义Ribbon配置类,从而使配置生效,形如:
@RibbonClient (name= "MICROSERVICECLOUD-DEPT" ,configuration=MySelfRule. class )
//MySelfRule自定义
官方文档明确给出了警告:
这个自定义配置类不能放在@ComponentScan所扫描的当前包下以及子包下,
否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,也就是说
我们达不到特殊化定制的目的了。
新建package com.goolecloud.myrule
新建自定义Robbin规则类
package com.goolecloud.myrule;
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 myIRule {
@Bean
public IRule getIRbule(){
return new RandomRule(); //Ribbon默认是轮询,我自定义为随机
//return new myIRuble_DY();
}
}
启动类:
package com.goolecloud.springcoud;
import com.goolecloud.myrule.myIRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "SERVICECLOUD-DEPT",configuration = myIRule.class)
public class ServicecloudConsumerDept80Application {
public static void main(String[] args) {
SpringApplication.run(ServicecloudConsumerDept80Application.class, args);
}
}
测试
http://localhost/consumer/dept/list
问题:依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。也即
以前是每台机器一次,现在是每台机器5次
参考源码修改为我们需求要求的RandomRule_ZY.java
package com.goolecloud.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;
public class myIRuble_DY extends AbstractLoadBalancerRule {
private int total=0;
private int indexcount=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;
}
//int index = chooseRandomInt(serverCount);
//server = upList.get(index);
if (total<5){
server=upList.get(indexcount);
total++;
}else {
total=0;
indexcount++;
if (indexcount>=upList.size()){
indexcount=0;
}
}
if (server == null) {
Thread.yield();
continue;
}
if (server.isAlive()) {
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
}
package com.goolecloud.myrule;
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 myIRule {
@Bean
public IRule getIRbule(){
return new myIRuble_DY();
}
}