负载均衡器Ribbon中的IRule负责选择什么样的负载均衡算法
源码中IRule的接口
package com.netflix.loadbalancer;
/**
- Interface that defines a "Rule" for a LoadBalancer. A Rule can be thought of
- as a Strategy for loadbalacing. Well known loadbalancing strategies include
- Round Robin, Response Time based etc.
-
- @author stonse
-
*/
public interface IRule{
/*
* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/
public Server choose(Object key);
public void setLoadBalancer(ILoadBalancer lb);
public ILoadBalancer getLoadBalancer();
}
该接口的实现类有
- RoundRobinRule:轮询(默认)
- RandomRule:随机
- RetryRule:重试(先按照轮询规则获取服务,如果获取服务失败则在指定时间内进行重试)
如果修改规则为源码中的其他规则吗可以在配置类中注入相应的Bean
demo
package com.mark.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.springcloud.MyRandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by Choisaaaa on 2018/7/9.
* 自定义的轮询算法的配置类
*/
@Configuration
public class MyRuleConfig {
@Bean //修改轮询规则为随机
public IRule iRule(){
return new RandomRule();
}
}
随机规则RandomRule源码中的choose方法
/**
* Randomly choose from all living servers
*/
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 = rand.nextInt(serverCount);
server = upList.get(index);//从存活的列表中获取server
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;//调到下一次循环(server == null)会为真继续进入while循环
}
if (server.isAlive()) { //如果服务实例是存活的则返回该服务实例
return (server);
}
// Shouldn't actually happen.. but must be transient or a bug.
server = null;
Thread.yield();
}
return server;
}
编写自定义的轮询规则
1.编写自定义的轮写规则类(该类不能和主程序类在同一层目录结构或者在子包下)
demo
package com.springcloud;
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;
import java.util.Random;
/**
* Created by Choisaaaa on 2018/7/9.
* 自定义随机算法
*
* 一个服务实例server 用3次 在轮询选择下一个server
*/
public class MyRandomRule extends AbstractLoadBalancerRule {
Random rand;
public MyRandomRule() {
rand = new Random();
}
/**
* Randomly choose from all living servers
*/
public Server choose(ILoadBalancer lb, Object key) {
//重写该方法
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
2.编写配置类将自定义的规则类注入到IOC容器中
demo
package com.mark.config;
import com.netflix.loadbalancer.IRule;
import com.springcloud.MyRandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by Choisaaaa on 2018/7/9.
* 自定义的轮询算法的配置类
*/
@Configuration
public class MyRuleConfig {
@Bean //注入自定义的负载均衡的算法
public IRule iRule(){
return new MyRandomRule();
}
}
3.修改主程序类
@RibbonClient(name = “PROVIDERPRODUCT”,configuration = MyRuleConfig.class)
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
//为服务PROVIDERPRODUCT指定自定义的负载均衡算法
@RibbonClient(name = "PROVIDERPRODUCT",configuration = MyRuleConfig.class)
public class ConsumerApplication {