All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.tencent.polaris.circuitbreak.client.task.InstancesCircuitBreakTask Maven / Gradle / Ivy
/*
* Tencent is pleased to support the open source community by making Polaris available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.tencent.polaris.circuitbreak.client.task;
import static com.tencent.polaris.api.plugin.registry.InstanceProperty.PROPERTY_CIRCUIT_BREAKER_STATUS;
import com.tencent.polaris.api.plugin.circuitbreaker.CircuitBreakResult;
import com.tencent.polaris.api.plugin.circuitbreaker.CircuitBreakResult.ResultKey;
import com.tencent.polaris.api.plugin.circuitbreaker.InstanceCircuitBreaker;
import com.tencent.polaris.api.plugin.compose.Extensions;
import com.tencent.polaris.api.plugin.registry.InstanceProperty;
import com.tencent.polaris.api.plugin.registry.ResourceFilter;
import com.tencent.polaris.api.plugin.registry.ServiceUpdateRequest;
import com.tencent.polaris.api.pojo.CircuitBreakerStatus;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceEventKey;
import com.tencent.polaris.api.pojo.ServiceEventKey.EventType;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.pojo.StatusDimension;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.MapUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.client.pojo.ServiceInstancesByProto;
import com.tencent.polaris.logging.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
/**
* 熔断单个实例的任务
*/
public class InstancesCircuitBreakTask implements Runnable, Comparable {
@Override
public int compareTo(InstancesCircuitBreakTask o) {
return this.priority.ordinal() - o.priority.ordinal();
}
/**
* 任务优先级
*/
public enum TaskPriority {
HIGH,
LOW,
}
private static final Logger LOG = LoggerFactory.getLogger(InstancesCircuitBreakTask.class);
private final ServiceKey serviceKey;
private final String cbName;
private final Collection instances;
private final String instId;
private final Extensions extensions;
private final TaskPriority priority;
public InstancesCircuitBreakTask(ServiceKey serviceKey, String cbName, Collection instances,
String instId, Extensions extensions, TaskPriority priority) {
this.serviceKey = serviceKey;
this.cbName = cbName;
this.instId = instId;
this.instances = instances;
this.extensions = extensions;
this.priority = priority;
}
private Instance getInstance() {
ServiceEventKey serviceEventKey = new ServiceEventKey(serviceKey, EventType.INSTANCE);
ResourceFilter resourceFilter = new ResourceFilter(serviceEventKey, true, true);
ServiceInstancesByProto instances = (ServiceInstancesByProto) extensions.getLocalRegistry()
.getInstances(resourceFilter);
if (!instances.isInitialized()) {
return null;
}
return instances.getInstance(instId);
}
@Override
public void run() {
Map allResults = new HashMap<>();
Set statusChangedInstances = new HashSet<>();
Collection targetInstances = instances;
if (StringUtils.isNotEmpty(instId)) {
Instance instance = getInstance();
if (null != instance) {
targetInstances = new ArrayList<>();
targetInstances.add(instance);
}
}
if (CollectionUtils.isEmpty(targetInstances)) {
return;
}
for (InstanceCircuitBreaker circuitBreaker : extensions.getInstanceCircuitBreakers()) {
if (StringUtils.isNotBlank(cbName) && !cbName.equals(circuitBreaker.getName())) {
continue;
}
CircuitBreakResult circuitBreakResult = circuitBreaker.checkInstance(targetInstances);
if (null == circuitBreakResult || circuitBreakResult.isEmptyResult()) {
continue;
}
cleanInstanceSet(circuitBreakResult.getInstancesToOpen(), statusChangedInstances);
cleanInstanceSet(circuitBreakResult.getInstancesToHalfOpen(), statusChangedInstances);
cleanInstanceSet(circuitBreakResult.getInstancesToClose(), statusChangedInstances);
allResults.put(circuitBreaker.getName(), circuitBreakResult);
}
ServiceUpdateRequest updateRequest = buildServiceUpdateRequest(serviceKey, allResults);
if (CollectionUtils.isEmpty(updateRequest.getProperties())) {
return;
}
LOG.info("update cache for circuitbreaker, value is {}", updateRequest);
extensions.getLocalRegistry().updateInstances(updateRequest);
}
private void cleanInstanceSet(Map instanceSet, Set allInstances) {
Set instIdsToRemove = new HashSet<>();
for (Map.Entry entry : instanceSet.entrySet()) {
ResultKey resultKey = entry.getKey();
if (allInstances.contains(resultKey)) {
instIdsToRemove.add(resultKey);
} else {
allInstances.add(resultKey);
}
}
instIdsToRemove.forEach(instanceSet::remove);
}
@SuppressWarnings("unchecked")
private void buildInstanceProperty(long now, Map results, int maxRequestAfterHalfOpen,
Map instanceProperties, String cbName, CircuitBreakerStatus.Status status) {
if (MapUtils.isEmpty(results)) {
return;
}
for (Map.Entry entry : results.entrySet()) {
ResultKey resultKey = entry.getKey();
Instance instance = entry.getValue();
String instId = resultKey.getInstId();
InstanceProperty instanceProperty = instanceProperties.get(instId);
if (null == instanceProperty) {
Map properties = new HashMap<>();
properties.put(PROPERTY_CIRCUIT_BREAKER_STATUS, new HashMap());
instanceProperty = new InstanceProperty(instance, properties);
instanceProperties.put(instId, instanceProperty);
}
Map statusMap = (Map)
instanceProperty.getProperties().get(PROPERTY_CIRCUIT_BREAKER_STATUS);
statusMap.put(resultKey.getStatusDimension(),
new CircuitBreakerStatus(cbName, status, now));
}
}
private ServiceUpdateRequest buildServiceUpdateRequest(
ServiceKey serviceKey, Map allResults) {
Map properties = new HashMap<>();
allResults.forEach((cbName, result) -> {
buildInstanceProperty(result.getCreateTimeMs(), result.getInstancesToOpen(),
result.getMaxRequestCountAfterHalfOpen(), properties, cbName, CircuitBreakerStatus.Status.OPEN);
buildInstanceProperty(result.getCreateTimeMs(), result.getInstancesToHalfOpen(),
result.getMaxRequestCountAfterHalfOpen(), properties, cbName,
CircuitBreakerStatus.Status.HALF_OPEN);
buildInstanceProperty(result.getCreateTimeMs(), result.getInstancesToClose(),
result.getMaxRequestCountAfterHalfOpen(), properties, cbName, CircuitBreakerStatus.Status.CLOSE);
});
return new ServiceUpdateRequest(serviceKey, properties.values());
}
}