ribbon实现负载均衡和自定义算法

 

Ribbon是什么?

  • Spring Cloud Ribbon 是基于Netflix Ribbon 实现的一套客户端负载均衡的工具(80是客户端)

  • 简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 的客户端组件提供一系列完整的配置项,如:连接超时、重试等。简单的说,就是在配置文件中列出 LoadBalancer (简称LB:负载均衡) 后面所有的及其,Ribbon 会自动的帮助你基于某种规则 (如简单轮询,随机连接等等) 去连接这些机器。我们也容易使用 Ribbon 实现自定义的负载均衡算法!

Ribbon能干嘛?

  • LB,即负载均衡 (LoadBalancer) ,在微服务或分布式集群中经常用的一种应用。

  • 负载均衡简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA (高用)。

  • 常见的负载均衡软件有 Nginx、Lvs 等等。

  • Dubbo、SpringCloud 中均给我们提供了负载均衡,SpringCloud 的负载均衡算法可以自定义

  • 负载均衡简单分类:

    • 集中式LB

      • 即在服务的提供方和消费方之间使用独立的LB设施,如Nginx(反向代理服务器),由该设施负责把访问请求通过某种策略转发至服务的提供方!

    • 进程式 LB

      • 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器。

      • Ribbon 就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址!

 ribbon实现负载均衡

ribbon实现负载均衡和自定义算法_第1张图片

 1-配置pom


        
            org.springframework.cloud
            spring-cloud-starter-ribbon
            1.4.7.RELEASE
        

        
            org.springframework.cloud
            spring-cloud-starter-eureka
            1.4.7.RELEASE
        

 2-配置 客户端

··

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/

3- 启动类文件配置类 实现负载均衡

 

package springcloud;

import MyRule.AndyRule;
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;

/**Ribbon and eureka 整合以后,
 *客户端可以直接调用,不用关心ip地址和端口号--
 *  */
@SpringBootApplication
@EnableEurekaClient
//在微服务启动的时候就能去加载 我们自定义的ribbon类
@RibbonClient(name = "SPRINGCLOUD-PROVIDER-DEPT",configuration = AndyRule.class)
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);

    }
}

 4-把固定地址 修改为 动态地址

package springcloud.controller;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import pojo.Dept;

import java.util.List;

@RestController
public class DeptConsumerController {

//    消费者不应该有service层
//    Restful  RestTemplate --提供我们调用,注册到spring就可以了

//   重要的三个参数 (url,实体:map,Class responseType)
    @Autowired
    private RestTemplate restTemplate;
//    提供多种便捷访问远程http服务的方法,简单的restful服务模板
//    Ribbon,这里的地址应该是一个变量,通过服务名【SPRINGCLOUD-PROVIDER-DEPT】来访问
//    private static final String REST_URL_PREFIX="http://localhost:8001";
    private static final String REST_URL_PREFIX="http://SPRINGCLOUD-PROVIDER-DEPT";

    @RequestMapping("/consumer/dept/add")
    public boolean add(Dept dept){
        return restTemplate.postForObject(REST_URL_PREFIX+"/dept/add",dept,boolean.class);
    }
    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){

        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/get/"+id,Dept.class);
    }
    @RequestMapping("/consumer/dept/list")
    public List list(){
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
    }
}

运行获取数据

ribbon实现负载均衡和自定义算法_第2张图片

 ribbon实现负载均衡和自定义算法_第3张图片

 

自定义算法

Intellij IDEA的Search Everwhere查找资料非常方便,默认的快捷键是双击Shift键

搜索Java内部类 快捷键:shift+shift 搜索 IRule 类

ribbon实现负载均衡和自定义算法_第4张图片

ribbon实现负载均衡和自定义算法_第5张图片 

重写随机实现类 

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package MyRule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
//import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class AndyRandomRule extends AbstractLoadBalancerRule {
    private int total;//某服务运行的总次数
    private int currentIndex;//当前从哪一个服务获取数据

    public AndyRandomRule() {
    }

    @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 upList = lb.getReachableServers();
                List allList = lb.getAllServers();
                int serverCount = allList.size();
                if (serverCount == 0) {
                    return null;
                }

//                int index = this.chooseRandomInt(serverCount);//生成随机数
//                server = (Server)upList.get(index);
//              自定义,每个服务执行5次, 共有3个服务。  *************
                if (total<5){
                    server = upList.get(currentIndex);
                    total++;
                }else {
                    total =1;
                    currentIndex++;
                    if (currentIndex >= upList.size()){
                        currentIndex=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) {
    }
}

使用自己定义的策略

package 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 AndyRule {
    @Bean
    public IRule myRule() {
//        return new AndyRandomRule();
        return new AndyRandomRule();//使用自定义的策略
    }
}

你可能感兴趣的:(SpringCloud,ribbon,java,intellij-idea)