SpringCloud XIV custom ribbon load balancing strategy.

① modified microservicecloud-consumer-dept-80, the master boot class @RibbonClient add comments.

When the micro services will be able to start to load our custom Ribbon class configuration (no ribbon factory default load balancing mode, with ribbon load balancing methods define yourself), so that the configuration to take effect, like this:

@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)

name = "MICROSERVICECLOUD-DEPT", indicates that the micro service MICROSERVICECLOUD-DEPT for use of eureka.

configuration = MySelfRule.class, MySelfRule a custom class, which is written polling rules and algorithms our custom.

DeptConsumer80_App.java entire contents are:

package com.lss.springcloud;

import java.util.List;


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;

import com.lss.myrule.MySelfRule;

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="MICROSERVICECLOUD-DEPT",configuration=MySelfRule.class)
public class DeptConsumer80_App {

	public static void main(String[] args) {
		SpringApplication.run(DeptConsumer80_App.class, args);
	}

}

② create MySelfRule class.

Official documents are given clear warning:
this custom configuration class can not be placed under the current package @ComponentScan scanned and sub-package, or we customize the configuration of this class will be shared by all of the Ribbon client, that is, that we can not reach specialized custom purpose.

@SpringBootApplication comment which contains @ComponentScan comment.

And @SpringBootApplication annotations are annotated in the primary package start classes DeptConsumer80_App.java com.lss.springcloud, described in sub-packet of the packet and the packet com.lss.springcloud: com.lss.springcloud.cfgbeans, com.lss under .springcloud.controller not define MySelfRule class.

It is necessary to create a new package, the new package: com.lss.myrule.

 

 

 

 

 

 

③新建自定义Robbin规则类MySelfRule。并修改内容。

MySelfRule.java的内容是:

package com.lss.myrule;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;

@Configuration
public class MySelfRule {

	
	
	 @Bean
	  public IRule myRule()
	  {
	   return new RandomRule();//Ribbon默认是轮询,我自定义为随机
	  }

}

④问题:依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。也即以前是每台机器一次,现在是每台机器5次。借鉴源码。

找到GitHub上对应的源码。

地址栏输入:

解析源码:

https://github.com/Netflix/ribbon/blob/master/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java

GitHub上的源码内容是:

/*
 *
 * Copyright 2013 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.netflix.loadbalancer;

import com.netflix.client.config.IClientConfig;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * A loadbalacing strategy that randomly distributes traffic amongst existing
 * servers.
 * 
 * @author stonse
 * 
 */
public class RandomRule extends AbstractLoadBalancerRule {

    /**
     * Randomly choose from all living servers
     */
    @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
    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) {
                /*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 */
                return null;
            }

            int index = chooseRandomInt(serverCount);
            server = upList.get(index);

            if (server == null) {
                /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
                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;

    }

    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

	@Override
	public Server choose(Object key) {
		return choose(getLoadBalancer(), key);
	}
}

 

我们要用到上面的源码,需要新建一个类。

 

 RandomRule_ZY.java需要增加的内容是:

 //总共被调用的次数,目前要求每台被调用5次,当total为5,指针currentIndex才能往下走,即+1。
		 private int total = 0;   
		 //当currentIndex达到上限,即如果有n台机器,currentIndex=n,total=5,则需要
		 //将currentIndex清零。
		 private int currentIndex = 0;//当前提供服务的机器号




  if(total < 5)
            {
            server = upList.get(currentIndex);
            total++;
            }else {
            total = 0;
            currentIndex++;
            if(currentIndex >= upList.size())
            {
              currentIndex = 0;
            }
            
            }
            

 

 

 RandomRule_ZY.java全部内容是:

package com.lss.myrule;

import java.util.List;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

public class RandomRule_ZY extends AbstractLoadBalancerRule {

		 //总共被调用的次数,目前要求每台被调用5次,当total为5,指针currentIndex才能往下走,即+1。
		 private int total = 0;   
		 //当currentIndex达到上限,即如果有n台机器,currentIndex=n,total=5,则需要
		 //将currentIndex清零。
		 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) {
                /*
                 * No servers. End regardless of pass, because subsequent passes
                 * only get more restrictive.
                 */
                return null;
            }

            
            if(total < 5)
            {
            server = upList.get(currentIndex);
            total++;
            }else {
            total = 0;
            currentIndex++;
            if(currentIndex >= upList.size())
            {
              currentIndex = 0;
            }
            
            }
            
            
            
            
            
            
//            int index = chooseRandomInt(serverCount);
//            server = upList.get(index);

            
            
            
            
            if (server == null) {
                /*
                 * The only time this should happen is if the server list were
                 * somehow trimmed. This is a transient condition. Retry after
                 * yielding.
                 */
                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;

    }

//    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 arg0) {
	
}
}

⑤MySelfRule.java的全部内容是:

package com.lss.myrule;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;

@Configuration
public class MySelfRule {

	
	
	 @Bean
	  public IRule myRule()
	  {
	   //return new RandomRule();//Ribbon默认是轮询,我自定义为随机
	   //return new RoundRobinRule();
	   return new RandomRule_ZY();//我自定义为每个机器被访问5次

	  }

}

测试,利用虚拟机。

http://192.168.10.115:83/consumer/dept/list

依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。也即以前是每台机器一次,现在是每台机器5次。

发布了155 篇原创文章 · 获赞 1 · 访问量 1万+

Guess you like

Origin blog.csdn.net/lbh19630726/article/details/104107602