通过观察负载均衡规则源码可知,负载均衡器都继承了AbstractLoadBalancerRule抽象父类(负载均衡规则类),我们手写自定义负载均衡器时,可参照源码进行修改
自定义(端口号大于25)的负载均衡器
package com.ssm.ribbon.rule;
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.concurrent.ThreadLocalRandom;
public class SsmRule extends AbstractLoadBalancerRule {
public SsmRule() {
}
@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()) { //如果线程被中断,则返回null
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);
//如果当前服务端口号大于25,就使用它
for(Server upServer : upList) {
int port = upServer.getPort();
if(port > 25) {
server = upServer;
break;
}
}
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 com.ssm.ribbon.rule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SsmRuleConfig {
@Bean
public IRule ssmRule() {
return new SsmRule();
}
}
指定该负载均衡器
package com.ssm.home;
import com.ssm.ribbon.rule.SsmRuleConfig;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@MapperScan(value = "com.ssm.*.mapper")
@ComponentScan(value = "com.ssm")
@RibbonClient(name = "ape-cloud-sku", configuration = SsmRuleConfig.class)
public class HomeApplication {
public static void main(String[] args) {
System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
SpringApplication.run(HomeApplication.class, args);
}
}
当home微服务调用sku微服务时,使用自定义的负载均衡器