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