1、解析配置中的服务列表:spring-cloud-ribbon-order.ribbon.listOfServers
2、基于负载均衡算法实现请求的分发
Ribbon负载均衡实现方式(本质相同:在服务请求到目标服务前增加了Interceptor拦截器实现负载均衡):
1、@LoadBalanced(在http请求对象(RestTemplate、httpClient、okHttp等)加上该注解), LoadBalanced本质是一个@Qualifier的注解(所有加了@LoadBalanced注解的请求对象都会被扫描到加载到LoadBalancerAutoConfiguration类中的restTemplates对象中,因为restTemplates加了LoadBalanced注解)
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RestTemplate.class})
@ConditionalOnBean({LoadBalancerClient.class})
@EnableConfigurationProperties({LoadBalancerRetryProperties.class})
public class LoadBalancerAutoConfiguration {
@LoadBalanced
@Autowired(
required = false
)
private List<RestTemplate> restTemplates = Collections.emptyList();
@Autowired(
required = false
)
2、LoadBalancerClinet(在起始服务中注入LoadBalancerClinet对象)
核心api:ILoadBalancer、IRule(负载均衡规则:轮询,随机,时间响应权重(定时任务在不断的发送请求,根据相应时间,根据特定算法))、Iping(定时任务每10s检查服务存活状态(心跳机制))、ServerList(定时任务,每30s执行一次更新服务列表)
//Qualifier注解的作用:标记作用,这里表示将所有加了Qualifier注解的bean,加载到testList中
@Qualifier
@Autowired
private List<TestClass> testList;
详见源码:
Ribbon负载均衡策略源码(轮询实现):
AbstractServerPredicate类
private int incrementAndGetModulo(int modulo) {
for (;;) {
int current = nextIndex.get();
int next = (current + 1) % modulo;
if (nextIndex.compareAndSet(current, next) && current < modulo)
return current;
}
}
心跳机制底层实现:
通过定时任务向指定服务发送http请求,若请求返回状态码为200,则表示当前服务未存活状态,否则为非存活状态
public boolean isAlive(Server server) {
String urlStr = "";
if (this.isSecure) {
urlStr = "https://";
} else {
urlStr = "http://";
}
urlStr = urlStr + server.getId();
urlStr = urlStr + this.getPingAppendString();
boolean isAlive = false;
HttpClient httpClient = new DefaultHttpClient();
HttpUriRequest getRequest = new HttpGet(urlStr);
String content = null;
try {
HttpResponse response = httpClient.execute(getRequest);
content = EntityUtils.toString(response.getEntity());
isAlive = response.getStatusLine().getStatusCode() == 200;
if (this.getExpectedContent() != null) {
LOGGER.debug("content:" + content);
if (content == null) {
isAlive = false;
} else if (content.equals(this.getExpectedContent())) {
isAlive = true;
} else {
isAlive = false;
}
}
} catch (IOException var11) {
var11.printStackTrace();
} finally {
getRequest.abort();
}
return isAlive;
}
关于@LoadBalanced源码解析:
LoadBalancerAutoConfiguration系统配置类中包含以下代码:
@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
@LoadBalanced包含@Qualifier会将所有直接或者间接加了@Qualifier注解的Bean加载到restTemplates数组中
springcloud ribbon负载均衡策略配置(随机):
springboot-eureka-clent.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
延伸:
Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方]
先说明一下好处有哪些:
1,如果你想 new 一个空的 List ,而这个 List 以后也不会再添加元素,那么就用 Collections.emptyList() 好了。
new ArrayList() 或者 new LinkedList() 在创建的时候有会有初始大小,多少会占用一内存。
每次使用都new 一个空的list集合,浪费就积少成多,浪费就严重啦,就不好啦
2,为了编码的方便。
比如说一个方法返回类型是List,当没有任何结果的时候,返回null,有结果的时候,返回list集合列表。
那样的话,调用这个方法的地方,就需要进行null判断。使用emptyList这样的方法,可以方便方法调用者。返回的就不会是null,省去重复代码。
注意的地方:
这个空的集合是不能调用.add(),添加元素的。因为直接报异常。因为源码就是这么写的:直接抛异常。
哦,Collections里面没这么写,但是EmptyList继承了AbstractList这个抽象类,里面简单实现了部分集合框架的方法。
这里面的add方法最后调用的方法体,就是直接抛异常。
throw new UnsupportedOperationException();
使用场景:
web开发中经常使用rest + json的技术组合来进行前后端交互,那么当前端调用一个接口时,接口有可能需要返回一个空的集合给到前端,比如你根据某个条件查数据库得不到数据时,那么此时Collections.emptyXXX()就非常合适了
网友评论