本篇文章是继上一篇SpringCloud入门(三)之Ribbon(上)之后的,因此目录也是从之下的第四开始
四,负载均衡算法IRule
4.1 Ribbon默认IRule
- RoundRobinRule:轮询
- RandomRule:随机
- RetryRule:先按照轮询RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行忽略跳过
- …
在servicecloud-consumer-dept-80服务消费者的配置类中定义其他算法:
package com.lmc.springcloud.cfgbeans;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate()
{
return new RestTemplate();
}
/**
* 默认负载均衡算法是轮询算法,通过注入方式修改调度算法
* @return
*/
@Bean
public IRule myRule(){
//return new RoundRobinRule();//轮询算法
return new RandomRule();//随机算法
}
}
4.2 自定义IRule
@RibbonClient:在启动微服务时就能去加载我们自定义的Ribbon配置类,从而使配置生效。
4.2.1 启动类
在servicecloud-consumer-dept-80服务消费者的启动类中增加注解@RibbonClient
package com.lmc.springcloud;
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.lmc.myrules.MySelfRule;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "SERVICECLOUD-DEPT", configuration = MySelfRule.class)
public class DeptConsumer80_App {
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(DeptConsumer80_App.class, args);
}
}
4.2.2 配置类
在启动类之外中再创建包,然后创建新配置类:
package com.lmc.myrules;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RoundRobinRule();
}
}
此时的80服务消费方就是通过轮询算法进行服务访问的。
4.2.3 自定义规则
在这里我们定义一个每台微服务轮询三次的算法规则,具体如下:
package com.lmc.myrules;
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;
/**
* 自定义负载均衡轮询算法,每个微服务轮询3次再切换下一台微服务
* @author lmc
*
*/
public class MyRule_LMC extends AbstractLoadBalancerRule{
//每个微服务轮询次数
private static final int ROUND_NUM = 3;
//当前被调用的次数
private int total = 0;
//当前的微服务索引
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 < ROUND_NUM){
server = upList.get(currentIndex);
++total;
}else {
total = 0;
++currentIndex;
if(currentIndex >= upList.size()){
currentIndex = 0;
}
}
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;
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
4.2.4 测试
http://localhost/consumer/dept/list
不断刷新页面,每个微服务轮询3次再切换则部署成功。