}

return response;

}, new LoadBalancedRecoveryCallback() {

//This is a special case, where both parameters to LoadBalancedRecoveryCallback are

//the same. In most cases they would be different.

@Override

protected ClientHttpResponse createResponse(ClientHttpResponse response, URI uri) {

return response;

}

});

}

doExecute方法:

protected T doExecute(RetryCallback retryCallback,

RecoveryCallback recoveryCallback, RetryState state)

throws E, ExhaustedRetryException {

//省略部分代码

/*

We allow the whole loop to be skipped if the policy or context already forbid the first try. This is used in the case of external retry to allow a recovery in handleRetryExhausted without the callback processing (which would throw an exception).

*/

//执行逻辑的关键方法

while (canRetry(retryPolicy, context) && !context.isExhaustedOnly()) {

}

继续跟踪canRetry方法

@Override

public boolean canRetry(RetryContext context) {

LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext)context;

if(lbContext.getRetryCount() == 0 && lbContext.getServiceInstance() == null) {

//We haven’t even tried to make the request yet so return true so we do

//设置选中的服务提供者

lbContext.setServiceInstance(serviceInstanceChooser.choose(serviceName));

return true;

}

return policy.canRetryNextServer(lbContext);

}

我们跟踪serviceInstanceChooser.choose(serviceName)看看怎么通过serviceName选服务提供者的。

@Override

public ServiceInstance choose(String serviceId) {

//选择server

Server server = getServer(serviceId);

if (server == null) {

return null;

}

return new RibbonServer(serviceId, server, isSecure(server, serviceId),

serverIntrospector(serviceId).getMetadata(server));

}

跟踪getServer方法

protected Server getServer(ILoadBalancer loadBalancer) {

if (loadBalancer == null) {

return null;

}

//可以看出是loadBalancer在选择

return loadBalancer.chooseServer(“default”); // TODO: better handling of key

}

继续深入

public Server chooseServer(Object key) {

if (counter == null) {

counter = createCounter();

}

//有一个调用次数在+1

counter.increment();

if (rule == null) {

return null;

} else {

try {

//委托给了IRule,所以Irule是负载均衡的关键,最后来总结

return rule.choose(key);

} catch (Exception e) {

logger.warn(“LoadBalancer [{}]: Error choosing server for key {}”, name, key, e);

return null;

}

}

}

查看Irule的实现

public Server choose(Object key) {

ILoadBalancer lb = getLoadBalancer();

//lb.getAllServers里面是所有的服务提供者列表

Optional server = getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);

if (server.isPresent()) {

return server.get();

} else {

return null;

}

}

跟踪chooseRoundRobinAfterFiltering方法

public Optional chooseRoundRobinAfterFiltering(List servers, Object loadBalancerKey) {

//拿到筛选后的servers

List eligible = getEligibleServers(servers, loadBalancerKey);

if (eligible.size() == 0) {

return Optional.absent();

}

//incrementAndGetModulo方法拿到下标,然后根据list.get取到一个服务

return Optional.of(eligible.get(incrementAndGetModulo(eligible.size())));

}

至此就拿到了具体的服务提供者。

但是到这里还有个问题?

怎么根据服务名拿到server的? 有一个ServerList接口是用于拿到服务列表的。我们使用的loadBalancer(ZoneAwareLoadBalancer)的父类DynamicServerListLoadBalancer类的构造方法里,有一个restOfinit方法

public DynamicServerListLoadBalancer(IClientConfig clientConfig, IRule rule, IPing ping,

ServerList serverList, ServerListFilter filter,

ServerListUpdater serverListUpdater) {

super(clientConfig, rule, ping);

this.serverListImpl = serverList;

this.filter = filter;

this.serverListUpdater = serverListUpdater;

if (filter instanceof AbstractServerListFilter) {

((AbstractServerListFilter) filter).setLoadBalancerStats(getLoadBalancerStats());

}

restOfInit(clientConfig);

}

跟踪restOfInit方法

void restOfInit(IClientConfig clientConfig) {

boolean primeConnection = this.isEnablePrimingConnections();

// turn this off to avoid duplicated asynchronous priming done in BaseLoadBalancer.setServerList()

this.setEnablePrimingConnections(false);

enableAndInitLearnNewServersFeature();

//用于获取所有的serverList

updateListOfServers();

if (primeConnection && this.getPrimeConnections() != null) {

this.getPrimeConnections()

.primeConnections(getReachableServers());

}

this.setEnablePrimingConnections(primeConnection);

LOGGER.info(“DynamicServerListLoadBalancer for client {} initialized: {}”, clientConfig.getClientName(), this.toString());

}

继续跟踪updateListOfServers方法

public void updateListOfServers() {

List servers = new ArrayList();

if (serverListImpl != null) {

//查询serverList

servers = serverListImpl.getUpdatedListOfServers();

LOGGER.debug(“List of Servers for {} obtained from Discovery client: {}”,

getIdentifier(), servers);

if (filter != null) {

servers = filter.getFilteredListOfServers(servers);

LOGGER.debug(“Filtered List of Servers for {} obtained from Discovery client: {}”,

getIdentifier(), servers);

}

}

updateAllServerList(servers);

}

继续跟踪源码到obtainServersViaDiscovery方法,

private List obtainServersViaDiscovery() {

List serverList = new ArrayList();

//eurekaClientProvider.get()会去获取EurekaClient

if (eurekaClientProvider == null || eurekaClientProvider.get() == null) {

logger.warn(“EurekaClient has not been initialized yet, returning an empty list”);

return new ArrayList();

}

EurekaClient eurekaClient = eurekaClientProvider.get();

//vipAddresses就是serviceName

if (vipAddresses!=null){

for (String vipAddress : vipAddresses.split(“,”)) {

// if targetRegion is null, it will be interpreted as the same region of client

//此处获取到服务的信息

List listOfInstanceInfo = eurekaClient.getInstancesByVipAddress(vipAddress, isSecure, targetRegion);

for (InstanceInfo ii : listOfInstanceInfo) {

if (ii.getStatus().equals(InstanceStatus.UP)) {

if(shouldUseOverridePort){

if(logger.isDebugEnabled()){

logger.debug("Overriding port on client name: " + clientName + " to " + overridePort);

}

// copy is necessary since the InstanceInfo builder just uses the original reference,

// and we don’t want to corrupt the global eureka copy of the object which may be

// used by other clients in our system

InstanceInfo copy = new InstanceInfo(ii);

if(isSecure){

ii = new InstanceInfo.Builder(copy).setSecurePort(overridePort).build();

}else{

ii = new InstanceInfo.Builder(copy).setPort(overridePort).build();

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)

目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。**

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。 [外链图片转存中…(img-P2zagjBz-1712554598055)] [外链图片转存中…(img-YyInNasF-1712554598056)] [外链图片转存中…(img-yWVSEsrk-1712554598056)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取) [外链图片转存中…(img-dHctzu4c-1712554598056)]

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: