SpringCloud(5)-Ribbon
SpringCloud(5)-Ribbon
Ribbon简介
- Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具 。
- 简单的说,Ribbon是Netflix发布的开源项目, 主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon的客户端组件提供一系列完整的配置项如:连接超时、重试等等。简单的说,就是在配置文件中列出LoadBalancer (简称LB:负载均衡)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等等)去连接这些机器。我们也很容易使用Ribbon实现自定义的负载均衡算法!
负载均衡(Load Balance)
-
LB,即负载均衡(Load Balance) ,在微服务或分布式集群中经常用的一种应用。
-
负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA (高可用)。
-
常见的负载均衡软件有Nginx, Lvs 等等。
-
dubbo、 SpringCloud中均给我们提供了负载均衡,SpringCloud的负载均衡算法可以自定义。
-
负载均衡简单分类:
- 集中式LB
即在服务的消费方和提供方之间使用独立的LB设施,如Nginx(反向代理服务器),由该设施负责把访问请求通过某种策略转发至服务的提供方!
- 进程式LB
将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器。Ribbon就属于进程式LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址!
集成Ribbon
- 在原本的客户端springcloud-consumer-dept-80项目的pom文件中添加Ribbon依赖与Eureka依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 在application.yml中配置Eureka
eureka:
instance:
hostname: localhost #eureka服务端实例名称
client:
register-with-eureka: false #表示是否向eureka注册自己
fetch-registry: false #如果为false表示自己为注册中心
service-url: #监控页面
defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
- 在主启动类上开启EurekaClient
@EnableEurekaClient
@SpringBootApplication
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
- 修改原本的BeanConfig
//配置负载均衡实现RestTemplate
@Bean
@LoadBalanced //Ribbon
public RestTemplate restTemplate(){
return new RestTemplate();
}
- 修改DeptConsumerController中原本的REST_PATH_PREFIX为application name,基于服务名去访问。客户端不用关心服务提供者的IP地址与端口号了!(原本:private static final String REST_PATH_PREFIX="http://localhost:8001")
private static final String REST_PATH_PREFIX="http://springcloud-provider-dept";
- 启动项目,访问http://localhost/consumer/dept/all测试:

Ribbon实现负载均衡
-
新建两个数据库sc02,sc03,数据与sc01除db_source其余一致。
-
新建两个Maven项目springcloud-provider-dept-8002,springcloud-provider-dept-8003。复制springcloud-provider-dept-8001项目中的所有内容。
-
修改springcloud-provider-dept-8002,springcloud-provider-dept-8003的application.yml中的端口号,连接的数据库名字与Eureka的默认描述信息。
-
保证3个服务提供者的application name一致。
spring:
application:
name: springcloud-provider-dept
- 记得修改mapper里面查询对应数据库的dept表。
- 编写对应的启动类。
- 启动项目,访问http://localhost:7001/:

访问http://localhost/consumer/dept/all,多次刷新页面,发现查询了不同的数据库(默认算法为简单轮询):



自定义负载均衡算法
- 选择服务消费者springcloud-consumer-dept-80,在com.yinrz包下新建一个包myrule,编写自定义的负载均衡算法类MyRule:
//自定义负载均衡算法:一个服务连续访问5次后,换下一个服务
public class MyRule extends AbstractLoadBalancerRule {
public MyRule(){
}
private int total=0;
private int current=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;
}
//========================核心算法开始==============================
System.out.println(111);
if(total<=5){
server = upList.get(current);
total++;
}else {
total=0;
current++;
if (current>=upList.size()){
current=0;
}
server = upList.get(current);
}
//========================核心算法结束==============================
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);
}
@Override
public Server choose(Object key) {
return this.choose(this.getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
}
- 在myrule包下写一个配置类MyRuleConfig:
@Configuration
public class MyRuleConfig {
@Bean
public IRule myRule(){
return new MyRule();
}
}
- 在主启动类上添加注解@RibbonClient:
@EnableEurekaClient
@SpringBootApplication
@RibbonClient(name = "springcloud-provider-dept",configuration = MyRuleConfig.class)//在微服务启动的时候就能加载我们自定义的Ribbon类
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class,args);
}
}
- 运行3个服务提供者,Eureka服务端,服务消费者项目,访问http://localhost/consumer/dept/all测试。

浙公网安备 33010602011771号