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

Posted Roam-G

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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实现负载均衡

 1-配置pom

<!--        ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>
<!--        eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.7.RELEASE</version>
        </dependency>

 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<T> 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<Dept> list()
        return restTemplate.getForObject(REST_URL_PREFIX+"/dept/list",List.class);
    

运行获取数据

 

 

自定义算法

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

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

 

重写随机实现类 

//
// 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<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);
//              自定义,每个服务执行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();//使用自定义的策略
    

以上是关于ribbon实现负载均衡和自定义算法的主要内容,如果未能解决你的问题,请参考以下文章

springcloud之Ribbon负载均衡

springCloud:Ribbon实现客户端侧负载均衡-消费者整合Ribbon

Ribbon负载均衡

Ribbon如何自定义实现负载均衡策略

最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇

最新版Spring Cloud Alibaba微服务架构-Ribbon负载均衡篇