SpringCloud升级之路Hoxton7.后续更新

编程

1. 修正实例列表乱序导致的负载均衡重试相同实例的问题

虽然之前考虑了通过每个请求的traceId隔离负载均衡的position来实现重试不会重试相同实例的问题,但是没有考虑在负载均衡过程中,实例列表的更新。

例如:

  • 请求第一次调用负载均衡,实例列表是:[实例1,实例2],position为1,对2取余=1,所以请求发送到实例2上面了
  • 请求失败,触发重试,实例列表缓存失效,更新后变成了:[实例2,实例1],position为2,对2取余=0,所以请求又发送到实例2上面了

private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> serviceInstances) {

if (serviceInstances.isEmpty()) {

log.warn("No servers available for service: " + this.serviceId);

return new EmptyResponse();

}

Span currentSpan = tracer.currentSpan();

//如果没有 traceId,就生成一个新的,但是最好检查下为啥会没有

//是不是 MQ 消费这种没有主动生成 traceId 的情况,最好主动生成下

if (currentSpan == null) {

currentSpan = tracer.newTrace();

}

long l = currentSpan.context().traceId();

int seed = positionCache.get(l).getAndIncrement();

//这里,serviceInstances可能与上次的内容不同

//例如上次是实例1,实例2

//这次是实例2,实例1

return new DefaultResponse(serviceInstances.get(seed % serviceInstances.size()));

}

所以,在这里追加排序,保证实例有序,从而进一步不会重试相同的实例。

private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> serviceInstances) {

if (serviceInstances.isEmpty()) {

log.warn("No servers available for service: " + this.serviceId);

return new EmptyResponse();

}

Span currentSpan = tracer.currentSpan();

//如果没有 traceId,就生成一个新的,但是最好检查下为啥会没有

//是不是 MQ 消费这种没有主动生成 traceId 的情况,最好主动生成下

if (currentSpan == null) {

currentSpan = tracer.newTrace();

}

long l = currentSpan.context().traceId();

int seed = positionCache.get(l).getAndIncrement();

return new DefaultResponse(serviceInstances.stream().sorted(Comparator.comparing(ServiceInstance::getInstanceId)).collect(Collectors.toList()).get(seed % serviceInstances.size()));

}

以上是 SpringCloud升级之路Hoxton7.后续更新 的全部内容, 来源链接: utcz.com/z/517476.html

回到顶部