You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2023/02/02 09:15:13 UTC
[servicecomb-java-chassis] branch master updated: [SCB-2672]remove instance isolation and loadbalance stats and using traffic marker instead (#3614)
This is an automated email from the ASF dual-hosted git repository.
liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push:
new 9468eb1d4 [SCB-2672]remove instance isolation and loadbalance stats and using traffic marker instead (#3614)
9468eb1d4 is described below
commit 9468eb1d4b9e7c80c33d2d70e69530cf54f9a6ef
Author: liubao68 <bi...@qq.com>
AuthorDate: Thu Feb 2 17:15:06 2023 +0800
[SCB-2672]remove instance isolation and loadbalance stats and using traffic marker instead (#3614)
---
.../demo/jaxrs/client/TestClientTimeout.java | 18 --
.../servicecomb/loadbalance/LoadBalancer.java | 8 -
.../loadbalance/LoadbalanceHandler.java | 5 +-
.../loadbalance/ServiceCombLoadBalancerStats.java | 181 -------------
.../loadbalance/ServiceCombServerStats.java | 229 ----------------
.../loadbalance/TryingIsolatedServerMarker.java | 56 ----
.../loadbalance/event/IsolationServerEvent.java | 113 --------
.../filterext/IsolationDiscoveryFilter.java | 169 ------------
...che.servicecomb.loadbalance.ServerListFilterExt | 3 +-
.../loadbalance/TestLoadBalanceHandler2.java | 287 +--------------------
.../TestServiceCombLoadBalancerStats.java | 174 -------------
.../loadbalance/TestServiceCombServerStats.java | 139 ----------
.../filter/IsolationDiscoveryFilterTest.java | 229 ----------------
13 files changed, 13 insertions(+), 1598 deletions(-)
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java
index 486d1e8aa..51dd4cf7d 100644
--- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java
@@ -23,13 +23,7 @@ import java.util.Map;
import org.apache.servicecomb.demo.CategorizedTestCase;
import org.apache.servicecomb.demo.TestMgr;
import org.apache.servicecomb.demo.validator.Student;
-import org.apache.servicecomb.loadbalance.ServiceCombLoadBalancerStats;
-import org.apache.servicecomb.loadbalance.ServiceCombServer;
-import org.apache.servicecomb.loadbalance.ServiceCombServerStats;
import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder;
-import org.apache.servicecomb.registry.DiscoveryManager;
-import org.apache.servicecomb.registry.RegistrationManager;
-import org.apache.servicecomb.registry.cache.InstanceCache;
import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@@ -85,16 +79,4 @@ public class TestClientTimeout implements CategorizedTestCase {
TestMgr.check(true, failed);
}
-
- private static ServiceCombServerStats getServiceCombServerStats() {
- InstanceCache instanceCache = DiscoveryManager.INSTANCE.getInstanceCacheManager()
- .getOrCreate(RegistrationManager.INSTANCE.getAppId(),
- "jaxrs", "0+");
- org.apache.servicecomb.registry.api.registry.MicroserviceInstance microserviceInstance = instanceCache
- .getInstanceMap().values().iterator().next();
- ServiceCombServer serviceCombServer = ServiceCombLoadBalancerStats.INSTANCE
- .getServiceCombServer(microserviceInstance);
- return ServiceCombLoadBalancerStats.INSTANCE
- .getServiceCombServerStats(serviceCombServer);
- }
}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
index 4b7dfdab4..0cc69dd87 100644
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
+++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java
@@ -71,14 +71,6 @@ public class LoadBalancer {
if (null == server) {
return null;
}
- ServiceCombServerStats serverStats = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server);
- if (serverStats.isIsolated()) {
- LOGGER.info("The Service {}'s instance {} has been isolated for a while, give a single test opportunity.",
- invocation.getMicroserviceName(),
- server.getInstance().getInstanceId());
- LOGGER.info("stats: {}-{}-{}-{}", serverStats.getTotalRequests(), serverStats.getSuccessRequests(),
- serverStats.getFailedRequests(), serverStats.getContinuousFailureCount());
- }
return server;
}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
index f3fddd1fe..1abdc38d6 100644
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
+++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java
@@ -23,7 +23,6 @@ import java.util.Objects;
import javax.ws.rs.core.Response.Status;
-import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang3.StringUtils;
import org.apache.servicecomb.core.Endpoint;
import org.apache.servicecomb.core.Handler;
@@ -44,6 +43,7 @@ import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.VisibleForTesting;
import com.netflix.config.DynamicPropertyFactory;
/**
@@ -111,7 +111,6 @@ public class LoadbalanceHandler implements Handler {
public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
AsyncResponse response = asyncResp;
asyncResp = async -> {
- ServiceCombServerStats.checkAndReleaseTryingChance(invocation);
response.handle(async);
};
@@ -197,10 +196,8 @@ public class LoadbalanceHandler implements Handler {
if (isFailedResponse(resp)) {
// this stats is for SessionStickinessRule
chosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(server);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
} else {
chosenLB.getLoadBalancerStats().incrementActiveRequestsCount(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
}
asyncResp.handle(resp);
});
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java
deleted file mode 100644
index 0b99139c3..000000000
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance;
-
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.registry.consumer.MicroserviceInstancePing;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.cache.RemovalListener;
-import com.netflix.config.DynamicPropertyFactory;
-
-/**
- * Add special stats that com.netflix.loadbalancer.LoadBalancerStats not provided
- */
-public class ServiceCombLoadBalancerStats {
- private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCombLoadBalancerStats.class);
-
- private final Map<ServiceCombServer, ServiceCombServerStats> pingView = new ConcurrentHashMap<>();
-
- private int serverExpireInSeconds = DynamicPropertyFactory.getInstance()
- .getIntProperty(Configuration.SERVER_EXPIRED_IN_SECONDS, 300).get();
-
- private long timerIntervalInMillis = DynamicPropertyFactory.getInstance()
- .getLongProperty(Configuration.TIMER_INTERVAL_IN_MILLIS, 10000).get();
-
- private LoadingCache<ServiceCombServer, ServiceCombServerStats> serverStatsCache;
-
- private final Map<String, ServiceCombServer> serviceCombServers = new ConcurrentHashMap<>();
-
- public static ServiceCombLoadBalancerStats INSTANCE;
-
- private Timer timer;
-
- static {
- INSTANCE = new ServiceCombLoadBalancerStats();
- INSTANCE.init();
- }
-
- /**
- * Should be singleton, use it only for testing
- */
- ServiceCombLoadBalancerStats() {
- }
-
- public void markIsolated(ServiceCombServer server, boolean isolated) {
- try {
- serverStatsCache.get(server).markIsolated(isolated);
- } catch (ExecutionException e) {
- LOGGER.error("Not expected to happen, maybe a bug.", e);
- }
- }
-
- public void markSuccess(ServiceCombServer server) {
- try {
- serverStatsCache.get(server).markSuccess();
- } catch (ExecutionException e) {
- LOGGER.error("Not expected to happen, maybe a bug.", e);
- }
- }
-
- public void markFailure(ServiceCombServer server) {
- try {
- serverStatsCache.get(server).markFailure();
- } catch (ExecutionException e) {
- LOGGER.error("Not expected to happen, maybe a bug.", e);
- }
- }
-
- public ServiceCombServerStats getServiceCombServerStats(ServiceCombServer server) {
- try {
- return serverStatsCache.get(server);
- } catch (ExecutionException e) {
- LOGGER.error("Not expected to happen, maybe a bug.", e);
- return null;
- }
- }
-
- public ServiceCombServer getServiceCombServer(MicroserviceInstance instance) {
- return serviceCombServers.get(instance.getInstanceId());
- }
-
- @VisibleForTesting
- void setServerExpireInSeconds(int sec) {
- this.serverExpireInSeconds = sec;
- }
-
- @VisibleForTesting
- void setTimerIntervalInMillis(int millis) {
- this.timerIntervalInMillis = millis;
- }
-
- @VisibleForTesting
- Map<ServiceCombServer, ServiceCombServerStats> getPingView() {
- return this.pingView;
- }
-
- @VisibleForTesting
- public void init() {
- // for testing
- if (timer != null) {
- timer.cancel();
- }
- if (serverStatsCache != null) {
- serverStatsCache.cleanUp();
- }
-
- pingView.clear();
-
- serverStatsCache =
- CacheBuilder.newBuilder()
- .expireAfterAccess(serverExpireInSeconds, TimeUnit.SECONDS)
- .removalListener(
- (RemovalListener<ServiceCombServer, ServiceCombServerStats>) notification -> {
- ServiceCombServer server = notification.getKey();
- LOGGER.debug("stats of instance {} removed, host is {}",
- server.getInstance().getInstanceId(), server.getHost());
- pingView.remove(notification.getKey());
- serviceCombServers.remove(notification.getKey());
- })
- .build(
- new CacheLoader<ServiceCombServer, ServiceCombServerStats>() {
- public ServiceCombServerStats load(ServiceCombServer server) {
- ServiceCombServerStats stats = new ServiceCombServerStats(server.getMicroserviceName());
- pingView.put(server, stats);
- serviceCombServers.put(server.getInstance().getInstanceId(), server);
- return stats;
- }
- });
-
- timer = new Timer("LoadBalancerStatsTimer", true);
- timer.schedule(new TimerTask() {
- private final MicroserviceInstancePing ping = SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class);
-
- @Override
- public void run() {
- try {
- Map<ServiceCombServer, ServiceCombServerStats> allServers = pingView;
- allServers.forEach((server, stats) -> {
- if ((System.currentTimeMillis() - stats.getLastVisitTime() > timerIntervalInMillis) && !ping
- .ping(server.getInstance())) {
- LOGGER.info("ping mark server {} failure.", server.getInstance().getInstanceId());
- stats.markFailure();
- }
- });
- serverStatsCache.cleanUp();
- } catch (Throwable e) {
- LOGGER.warn("LoadBalancerStatsTimer error.", e);
- }
- }
- }, timerIntervalInMillis, timerIntervalInMillis);
- }
-}
-
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServerStats.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServerStats.java
deleted file mode 100644
index 140ad215c..000000000
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServerStats.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance;
-
-import java.time.Clock;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.foundation.common.utils.TimeUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Special stats that com.netflix.loadbalancer.ServerStats not provided.
- *
- * In concurrent scenarios, we can't count statistics accurately, but it's fine.
- */
-public class ServiceCombServerStats {
- private static final long TIME_WINDOW_IN_MILLISECONDS = 60000;
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCombServerStats.class);
-
- private final Object lock = new Object();
-
- /**
- * There is not more than 1 server allowed to stay in TRYING status concurrently.
- * This flag is designed to ensure such mechanism. And it makes the ServiceCombServerStats stateful.
- * Therefore, the flag should be reset correctly after the trying server gets handled.
- */
- static AtomicReference<TryingIsolatedServerMarker> globalAllowIsolatedServerTryingFlag = new AtomicReference<>();
-
- Clock clock;
-
- private long lastWindow;
-
- private AtomicLong continuousFailureCount;
-
- private long lastVisitTime;
-
- private long lastActiveTime;
-
- private long isolatedTime;
-
- private AtomicLong totalRequests;
-
- private AtomicLong successRequests;
-
- private AtomicLong failedRequests;
-
- private boolean isolated = false;
-
- private final String microserviceName;
-
- public ServiceCombServerStats(String microserviceName) {
- this(microserviceName, TimeUtils.getSystemDefaultZoneClock());
- }
-
- public ServiceCombServerStats(String microserviceName, Clock clock) {
- this.clock = clock;
- this.microserviceName = microserviceName;
- init();
- }
-
- private void init() {
- lastWindow = clock.millis();
- continuousFailureCount = new AtomicLong(0);
- lastVisitTime = clock.millis();
- lastActiveTime = clock.millis();
- totalRequests = new AtomicLong(0L);
- successRequests = new AtomicLong(0L);
- failedRequests = new AtomicLong(0L);
- }
-
- public static boolean isolatedServerCanTry() {
- TryingIsolatedServerMarker marker = globalAllowIsolatedServerTryingFlag.get();
- if (marker == null) {
- return true;
- }
- return marker.isOutdated();
- }
-
- /**
- * Applying for a trying chance for the isolated server. There is only 1 trying chance globally concurrently.
- *
- * @return true if the chance is applied successfully, otherwise false
- */
- public static boolean applyForTryingChance(Invocation invocation) {
- TryingIsolatedServerMarker marker = globalAllowIsolatedServerTryingFlag.get();
- if (marker == null) {
- return globalAllowIsolatedServerTryingFlag.compareAndSet(null, new TryingIsolatedServerMarker(invocation));
- }
- if (marker.isOutdated()) {
- return globalAllowIsolatedServerTryingFlag.compareAndSet(marker, new TryingIsolatedServerMarker(invocation));
- }
- return false;
- }
-
- public static void checkAndReleaseTryingChance(Invocation invocation) {
- TryingIsolatedServerMarker marker = globalAllowIsolatedServerTryingFlag.get();
- if (marker == null || marker.getInvocation() != invocation) {
- return;
- }
- globalAllowIsolatedServerTryingFlag.compareAndSet(marker, null);
- }
-
- public void markIsolated(boolean isolated) {
- this.isolated = isolated;
- this.isolatedTime = System.currentTimeMillis();
- }
-
- public void markSuccess() {
- long time = clock.millis();
- ensureWindow(time);
-
- if (isolated) {
- if (Configuration.INSTANCE.isRecoverImmediatelyWhenSuccess(microserviceName)
- && time - this.isolatedTime > Configuration.INSTANCE
- .getMinIsolationTime(microserviceName)) {
- resetStats();
- LOGGER.info("trying server invocation success, and reset stats.");
- } else {
- LOGGER.info("trying server invocation success!");
- }
- }
-
- totalRequests.incrementAndGet();
- successRequests.incrementAndGet();
- continuousFailureCount.set(0);
- lastVisitTime = time;
- lastActiveTime = time;
- }
-
- public void markFailure() {
- long time = clock.millis();
- ensureWindow(time);
- lastVisitTime = time;
-
- // when isolated, do not update any failure statistics, or we can not recover from failure very quickly
- if (!isolated) {
- totalRequests.incrementAndGet();
- failedRequests.incrementAndGet();
- continuousFailureCount.incrementAndGet();
- }
- }
-
- private void ensureWindow(long time) {
- if (time - lastWindow > TIME_WINDOW_IN_MILLISECONDS) {
- synchronized (lock) {
- if (time - lastWindow > TIME_WINDOW_IN_MILLISECONDS) {
- if (!isolated) {
- resetStats();
- }
- lastWindow = time;
- }
- }
- }
- }
-
- private void resetStats() {
- continuousFailureCount.set(0);
- totalRequests.set(0);
- successRequests.set(0);
- failedRequests.set(0);
- }
-
- public long getLastVisitTime() {
- return lastVisitTime;
- }
-
- public long getIsolatedTime() {
- return isolatedTime;
- }
-
- public long getLastActiveTime() {
- return lastActiveTime;
- }
-
- public long getContinuousFailureCount() {
- return continuousFailureCount.get();
- }
-
- public long getTotalRequests() {
- return totalRequests.get();
- }
-
- public long getSuccessRequests() {
- return successRequests.get();
- }
-
- public long getFailedRequests() {
- return failedRequests.get();
- }
-
- public int getSuccessRate() {
- return calcRequestRate(successRequests);
- }
-
- public int getFailedRate() {
- return calcRequestRate(failedRequests);
- }
-
- private int calcRequestRate(AtomicLong requestCnt) {
- long totalReqs = totalRequests.get();
- if (totalReqs == 0L) {
- return 0;
- }
- return (int) (requestCnt.get() * 100 / totalReqs);
- }
-
- public boolean isIsolated() {
- return isolated;
- }
-}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/TryingIsolatedServerMarker.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/TryingIsolatedServerMarker.java
deleted file mode 100644
index a741a8d71..000000000
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/TryingIsolatedServerMarker.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance;
-
-import java.time.Clock;
-import java.util.Objects;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.foundation.common.utils.TimeUtils;
-
-public class TryingIsolatedServerMarker {
- Clock clock;
-
- final long startTryingTimestamp;
-
- private final Invocation invocation;
-
- /**
- * To make sure even if some error interrupted the releasing operation of
- * {@link ServiceCombServerStats#globalAllowIsolatedServerTryingFlag},
- * the state can still be recovered.
- */
- private final int maxSingleTestWindow;
-
- public TryingIsolatedServerMarker(Invocation invocation) {
- Objects.requireNonNull(invocation, "invocation should be non-null");
- this.invocation = invocation;
- clock = TimeUtils.getSystemDefaultZoneClock();
- startTryingTimestamp = clock.millis();
- maxSingleTestWindow = Configuration.INSTANCE.getMaxSingleTestWindow();
- }
-
- public boolean isOutdated() {
- return this.invocation.isFinished()
- || clock.millis() - startTryingTimestamp >= maxSingleTestWindow;
- }
-
- public Invocation getInvocation() {
- return invocation;
- }
-}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java
deleted file mode 100644
index 50a51d692..000000000
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance.event;
-
-import org.apache.servicecomb.core.Endpoint;
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.foundation.common.event.AlarmEvent;
-import org.apache.servicecomb.loadbalance.ServiceCombServerStats;
-import org.apache.servicecomb.loadbalance.filterext.IsolationDiscoveryFilter;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-
-public class IsolationServerEvent extends AlarmEvent {
-
- private final String microserviceName;
-
- private final Endpoint endpoint;
-
- private final MicroserviceInstance instance;
-
- //当前实例总请求数
- private final long currentTotalRequest;
-
- //当前实例连续出错次数
- private final long currentCountinuousFailureCount;
-
- //当前实例出错百分比
- private final double currentErrorPercentage;
-
- private final int minIsolationTime;
-
- private final long enableRequestThreshold;
-
- private final int continuousFailureThreshold;
-
- private final int errorThresholdPercentage;
-
- private final long singleTestTime;
-
- public IsolationServerEvent(Invocation invocation, MicroserviceInstance instance,
- ServiceCombServerStats serverStats,
- IsolationDiscoveryFilter.Settings settings, Type type, Endpoint endpoint) {
- super(type);
- this.microserviceName = invocation.getMicroserviceName();
- this.endpoint = endpoint;
- this.currentTotalRequest = serverStats.getTotalRequests();
- this.currentCountinuousFailureCount = serverStats.getContinuousFailureCount();
- this.currentErrorPercentage = serverStats.getFailedRate();
- this.minIsolationTime = settings.minIsolationTime;
- this.enableRequestThreshold = settings.enableRequestThreshold;
- this.continuousFailureThreshold = settings.continuousFailureThreshold;
- this.errorThresholdPercentage = settings.errorThresholdPercentage;
- this.singleTestTime = settings.singleTestTime;
- this.instance = instance;
- }
-
- public String getMicroserviceName() {
- return microserviceName;
- }
-
- public long getCurrentTotalRequest() {
- return currentTotalRequest;
- }
-
- public long getCurrentCountinuousFailureCount() {
- return currentCountinuousFailureCount;
- }
-
- public double getCurrentErrorPercentage() {
- return currentErrorPercentage;
- }
-
- public long getEnableRequestThreshold() {
- return enableRequestThreshold;
- }
-
- public int getContinuousFailureThreshold() {
- return continuousFailureThreshold;
- }
-
- public int getErrorThresholdPercentage() {
- return errorThresholdPercentage;
- }
-
- public long getSingleTestTime() {
- return singleTestTime;
- }
-
- public MicroserviceInstance getInstance() {
- return instance;
- }
-
- public int getMinIsolationTime() {
- return minIsolationTime;
- }
-
- public Endpoint getEndpoint() {
- return endpoint;
- }
-}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filterext/IsolationDiscoveryFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filterext/IsolationDiscoveryFilter.java
deleted file mode 100644
index bbbda45e4..000000000
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filterext/IsolationDiscoveryFilter.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance.filterext;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.foundation.common.event.AlarmEvent.Type;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.loadbalance.Configuration;
-import org.apache.servicecomb.loadbalance.ServerListFilterExt;
-import org.apache.servicecomb.loadbalance.ServiceCombLoadBalancerStats;
-import org.apache.servicecomb.loadbalance.ServiceCombServer;
-import org.apache.servicecomb.loadbalance.ServiceCombServerStats;
-import org.apache.servicecomb.loadbalance.event.IsolationServerEvent;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.eventbus.EventBus;
-import com.netflix.config.DynamicBooleanProperty;
-import com.netflix.config.DynamicPropertyFactory;
-
-/**
- * Isolate instances by error metrics
- */
-public class IsolationDiscoveryFilter implements ServerListFilterExt {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(IsolationDiscoveryFilter.class);
-
- private final DynamicBooleanProperty emptyProtection = DynamicPropertyFactory.getInstance()
- .getBooleanProperty(EMPTY_INSTANCE_PROTECTION, false);
-
- private final EventBus eventBus = EventManager.getEventBus();
-
- public static class Settings {
- public int errorThresholdPercentage;
-
- public long singleTestTime;
-
- public long enableRequestThreshold;
-
- public int continuousFailureThreshold;
-
- public int minIsolationTime; // to avoid isolation recover too fast due to no concurrent control in concurrent scenario
- }
-
- @Override
- public int getOrder() {
- return ORDER_ISOLATION;
- }
-
- public IsolationDiscoveryFilter() {
- emptyProtection.addCallback(() -> {
- boolean newValue = emptyProtection.get();
- LOGGER.info("{} changed from {} to {}", EMPTY_INSTANCE_PROTECTION, emptyProtection, newValue);
- });
- }
-
- @Override
- public boolean enabled() {
- return DynamicPropertyFactory.getInstance()
- .getBooleanProperty(ISOLATION_FILTER_ENABLED, false)
- .get();
- }
-
- @Override
- public List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> servers,
- Invocation invocation) {
- if (!Configuration.INSTANCE.isIsolationFilterOpen(invocation.getMicroserviceName())) {
- return servers;
- }
-
- List<ServiceCombServer> filteredServers = new ArrayList<>();
- Settings settings = createSettings(invocation);
- servers.forEach((server) -> {
- if (allowVisit(invocation, server, settings)) {
- filteredServers.add(server);
- }
- });
- if (filteredServers.isEmpty() && emptyProtection.get()) {
- LOGGER.warn("All servers have been isolated, allow one of them based on load balance rule.");
- return servers;
- }
- return filteredServers;
- }
-
- private Settings createSettings(Invocation invocation) {
- Settings settings = new Settings();
- settings.errorThresholdPercentage = Configuration.INSTANCE
- .getErrorThresholdPercentage(invocation.getMicroserviceName());
- settings.singleTestTime = Configuration.INSTANCE.getSingleTestTime(invocation.getMicroserviceName());
- settings.enableRequestThreshold = Configuration.INSTANCE
- .getEnableRequestThreshold(invocation.getMicroserviceName());
- settings.continuousFailureThreshold = Configuration.INSTANCE
- .getContinuousFailureThreshold(invocation.getMicroserviceName());
- settings.minIsolationTime = Configuration.INSTANCE
- .getMinIsolationTime(invocation.getMicroserviceName());
- return settings;
- }
-
- private boolean allowVisit(Invocation invocation, ServiceCombServer server, Settings settings) {
- ServiceCombServerStats serverStats = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server);
- if (!checkThresholdAllowed(settings, serverStats)) {
- if (serverStats.isIsolated()
- && (System.currentTimeMillis() - serverStats.getLastVisitTime()) > settings.singleTestTime) {
- return ServiceCombServerStats.applyForTryingChance(invocation);
- }
- if (!serverStats.isIsolated()) {
- // checkThresholdAllowed is not concurrent control, may print several logs/events in current access.
- serverStats.markIsolated(true);
- eventBus.post(
- new IsolationServerEvent(invocation, server.getInstance(), serverStats,
- settings, Type.OPEN, server.getEndpoint()));
- LOGGER.warn("Isolate service {}'s instance {}.",
- invocation.getMicroserviceName(),
- server.getInstance().getInstanceId());
- }
- return false;
- }
- if (serverStats.isIsolated()) {
- // [2] so that we add a feature to isolate for at least a minimal time, and we can avoid
- // high volume of concurrent requests with a percentage of error(e.g. 50%) scenario with no isolation
- if ((System.currentTimeMillis() - serverStats.getIsolatedTime()) <= settings.minIsolationTime) {
- return false;
- }
- serverStats.markIsolated(false);
- eventBus.post(new IsolationServerEvent(invocation, server.getInstance(), serverStats,
- settings, Type.CLOSE, server.getEndpoint()));
- LOGGER.warn("Recover service {}'s instance {} from isolation.",
- invocation.getMicroserviceName(),
- server.getInstance().getInstanceId());
- }
- return true;
- }
-
- private boolean checkThresholdAllowed(Settings settings, ServiceCombServerStats serverStats) {
- if (serverStats.getTotalRequests() < settings.enableRequestThreshold) {
- return true;
- }
-
- if (settings.continuousFailureThreshold > 0) {
- // continuousFailureThreshold has higher priority to decide the result
- if (serverStats.getContinuousFailureCount() >= settings.continuousFailureThreshold) {
- return false;
- }
- }
-
- if (settings.errorThresholdPercentage == 0) {
- return true;
- }
- return serverStats.getFailedRate() < settings.errorThresholdPercentage;
- }
-}
diff --git a/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt b/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt
index 9e8a08479..741fd2c7c 100644
--- a/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt
+++ b/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt
@@ -15,5 +15,4 @@
# limitations under the License.
#
-org.apache.servicecomb.loadbalance.filterext.IsolationDiscoveryFilter
-org.apache.servicecomb.loadbalance.filterext.ZoneAwareDiscoveryFilter
\ No newline at end of file
+org.apache.servicecomb.loadbalance.filterext.ZoneAwareDiscoveryFilter
diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java
index e2a353db4..dd23e8fbe 100644
--- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java
+++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java
@@ -17,13 +17,14 @@
package org.apache.servicecomb.loadbalance;
+import static org.mockito.Mockito.when;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.servicecomb.config.ConfigUtil;
-import org.apache.servicecomb.core.Endpoint;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.NonSwaggerInvocation;
import org.apache.servicecomb.core.SCBEngine;
@@ -35,10 +36,7 @@ import org.apache.servicecomb.core.definition.OperationMeta;
import org.apache.servicecomb.core.definition.SchemaMeta;
import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
import org.apache.servicecomb.core.transport.TransportManager;
-import org.apache.servicecomb.foundation.common.Holder;
-import org.apache.servicecomb.foundation.common.event.EventManager;
import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
-import org.apache.servicecomb.loadbalance.event.IsolationServerEvent;
import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter;
import org.apache.servicecomb.localregistry.LocalRegistryStore;
import org.apache.servicecomb.registry.DiscoveryManager;
@@ -57,16 +55,10 @@ import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.mockito.Mockito;
-import com.google.common.eventbus.Subscribe;
-
import mockit.Mock;
import mockit.MockUp;
-import static org.mockito.Mockito.when;
-
public class TestLoadBalanceHandler2 {
- private Holder<Long> mockTimeMillis;
-
private static SCBEngine scbEngine;
@BeforeClass
@@ -85,27 +77,14 @@ public class TestLoadBalanceHandler2 {
@Before
public void setUp() {
-
- // avoid mock
- ServiceCombLoadBalancerStats.INSTANCE.init();
- TestServiceCombServerStats.releaseTryingChance();
-
- mockTimeMillis = new Holder<>(1L);
- new MockUp<System>() {
- @Mock
- long currentTimeMillis() {
- return mockTimeMillis.value;
- }
- };
}
@After
public void teardown() {
- TestServiceCombServerStats.releaseTryingChance();
}
@Test
- public void testZoneAwareAndIsolationFilterWorks() throws Exception {
+ public void testZoneAwareFilterWorks() throws Exception {
ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class);
OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class);
@@ -201,54 +180,8 @@ public class TestLoadBalanceHandler2 {
loadBalancer = handler.getOrCreateLoadBalancer(invocation);
server = loadBalancer.chooseServer(invocation);
Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
-
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
-
- //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0");
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
-
- //if errorThresholdPercentage greater than 0, it will activate.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20");
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10");
- ServiceCombServer server2 = server;
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint());
- mockDelayMillis(20);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint());
}
- public static class IsolationEndpointListener {
- Holder<Integer> count;
-
- public IsolationEndpointListener(Holder<Integer> count) {
- this.count = count;
- }
-
- @Subscribe
- public void listener(IsolationServerEvent event) {
- count.value++;
- Assertions.assertSame("Isolation Endpoint", "rest://localhost:9090", event.getEndpoint().getEndpoint());
- }
- }
@Test
public void testIsolationEventWithEndpoint() throws Exception {
@@ -313,31 +246,10 @@ public class TestLoadBalanceHandler2 {
loadBalancer = handler.getOrCreateLoadBalancer(invocation);
server = loadBalancer.chooseServer(invocation);
Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
-
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
-
- //if errorThresholdPercentage greater than 0, it will activate.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "10");
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10");
-
- Holder<Integer> count = new Holder<>(0);
- IsolationEndpointListener isolationEndpointListener = new IsolationEndpointListener(count);
- EventManager.getEventBus().register(isolationEndpointListener);
- Assertions.assertEquals(0, count.value.intValue());
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- // no server is available
- Assertions.assertNull(server);
- Assertions.assertEquals(1, count.value.intValue());
- EventManager.unregister(isolationEndpointListener);
}
@Test
- public void testZoneAwareAndIsolationFilterWorksEmptyInstanceProtectionEnabled() throws Exception {
+ public void testZoneAwareFilterWorksEmptyInstanceProtectionEnabled() throws Exception {
ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.emptyInstanceProtectionEnabled", "true");
ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class);
OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
@@ -435,44 +347,12 @@ public class TestLoadBalanceHandler2 {
loadBalancer = handler.getOrCreateLoadBalancer(invocation);
server = loadBalancer.chooseServer(invocation);
Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
-
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
-
- //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0");
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
-
- //if errorThresholdPercentage greater than 0, it will activate.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20");
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "30");
- ServiceCombServer server2 = server;
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint());
- mockDelayMillis(31);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint());
}
@Test
- public void testZoneAwareAndIsolationFilterUsingMockedInvocationWorks() throws Exception {
- Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> aysnc.success("OK"));
+ public void testZoneAwareFilterUsingMockedInvocationWorks() throws Exception {
+ Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+",
+ (inv, aysnc) -> aysnc.success("OK"));
InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class);
TransportManager transportManager = Mockito.mock(TransportManager.class);
@@ -562,47 +442,14 @@ public class TestLoadBalanceHandler2 {
loadBalancer = handler.getOrCreateLoadBalancer(invocation);
server = loadBalancer.chooseServer(invocation);
Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint());
-
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
-
- //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0");
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint());
-
- //if errorThresholdPercentage greater than 0, it will activate.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20");
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "30");
- ServiceCombServer server2 = server;
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint());
- mockDelayMillis(31);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint());
- handler.handle(invocation, (response) -> Assertions.assertEquals("OK", response.getResult()));
}
@Test
public void testStatusFilterUsingMockedInvocationWorks() throws Exception {
ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.status.enabled", "false");
- Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> aysnc.success("OK"));
+ Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+",
+ (inv, aysnc) -> aysnc.success("OK"));
InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class);
TransportManager transportManager = Mockito.mock(TransportManager.class);
@@ -693,40 +540,6 @@ public class TestLoadBalanceHandler2 {
loadBalancer = handler.getOrCreateLoadBalancer(invocation);
server = loadBalancer.chooseServer(invocation);
Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint());
-
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
-
- //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0");
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint());
-
- //if errorThresholdPercentage greater than 0, it will activate.
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20");
- ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10");
- ServiceCombServer server2 = server;
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint());
- mockDelayMillis(20);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint());
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
- loadBalancer = handler.getOrCreateLoadBalancer(invocation);
- server = loadBalancer.chooseServer(invocation);
- Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint());
- handler.handle(invocation, (response) -> Assertions.assertEquals("OK", response.getResult()));
}
@Test
@@ -790,7 +603,8 @@ public class TestLoadBalanceHandler2 {
} catch (Exception e) {
}
- Assertions.assertEquals("rest://127.0.0.1:8080?sslEnabled=true&protocol=http2", invocation.getEndpoint().getEndpoint());
+ Assertions.assertEquals("rest://127.0.0.1:8080?sslEnabled=true&protocol=http2",
+ invocation.getEndpoint().getEndpoint());
// reset
invocation.setEndpoint(null);
@@ -818,85 +632,6 @@ public class TestLoadBalanceHandler2 {
}
}
- @Test
- public void trying_chance_should_be_released() {
- List<ServiceCombServer> servers = new ArrayList<>();
- ServiceCombServer serviceCombServer = createMockedServer("instanceId", "rest://127.0.0.1:8080");
- servers.add(serviceCombServer);
-
- DiscoveryTree discoveryTree = createMockedDiscoveryTree(servers);
- LoadbalanceHandler handler = new LoadbalanceHandler(discoveryTree);
-
- // mock the process of the isolated server selected and changed to TRYING status
- ServiceCombServerStats serviceCombServerStats =
- mockServiceCombServerStats(serviceCombServer, 5, true);
-
- Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+",
- (inv, aysnc) -> {
- Assertions.assertEquals("rest://127.0.0.1:8080", inv.getEndpoint().getEndpoint());
- Assertions.assertTrue(serviceCombServerStats.isIsolated());
- Assertions.assertEquals(5, serviceCombServerStats.getContinuousFailureCount());
- Assertions.assertFalse(ServiceCombServerStats.isolatedServerCanTry());
- aysnc.success("OK");
- });
-
- Assertions.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation));
- ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.enabled", "false");
- try {
- handler.handle(invocation, (response) -> Assertions.assertEquals("OK", response.getResult()));
- } catch (Exception e) {
- Assertions.fail("unexpected exception " + e.getMessage());
- }
- ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.enabled", "true");
- Assertions.assertEquals("rest://127.0.0.1:8080", invocation.getEndpoint().getEndpoint());
- Assertions.assertTrue(serviceCombServerStats.isIsolated());
- Assertions.assertEquals(0, serviceCombServerStats.getContinuousFailureCount());
- Assertions.assertTrue(ServiceCombServerStats.isolatedServerCanTry());
- }
-
- /**
- * Mock the statistics of the specified {@code serviceCombServer}, set the failureCount and status.
- * @return the ServiceCombServerStats object corresponding to the param {@code serviceCombServer}
- */
- private ServiceCombServerStats mockServiceCombServerStats(ServiceCombServer serviceCombServer, int failureCount,
- boolean isIsolatedStatus) {
- ServiceCombServerStats serviceCombServerStats =
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer);
- for (int i = 0; i < failureCount; ++i) {
- serviceCombServerStats.markFailure();
- }
- serviceCombServerStats.markIsolated(isIsolatedStatus);
- return serviceCombServerStats;
- }
-
- /**
- * Create a mocked ServiceCombServer with specified microserviceInstanceId and endpoint.
- */
- private ServiceCombServer createMockedServer(String microserviceInstanceId, String endpoint) {
- MicroserviceInstance microserviceInstance = new MicroserviceInstance();
- microserviceInstance.setInstanceId(microserviceInstanceId);
- return new ServiceCombServer(null,
- new Endpoint(Mockito.mock(Transport.class), endpoint),
- microserviceInstance);
- }
-
- /**
- * Create a mocked DiscoveryTree that always returns {@code servers} as the versionedCache result.
- */
- private DiscoveryTree createMockedDiscoveryTree(List<ServiceCombServer> servers) {
- DiscoveryTree discoveryTree = Mockito.mock(DiscoveryTree.class);
- DiscoveryTreeNode versionedCache = new DiscoveryTreeNode()
- .name("testVersionedCacheName")
- .data(servers);
- Mockito.when(discoveryTree.discovery(Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString()))
- .thenReturn(versionedCache);
- return discoveryTree;
- }
-
- private void mockDelayMillis(long delay) {
- mockTimeMillis.value += delay;
- }
-
private void mockUpInstanceCacheManager(InstanceCacheManager instanceCacheManager) {
new MockUp<DiscoveryManager>() {
@Mock
diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java
deleted file mode 100644
index c3172b1a6..000000000
--- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance;
-
-import java.util.Map;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.servicecomb.core.Transport;
-import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.registry.cache.CacheEndpoint;
-import org.apache.servicecomb.registry.consumer.MicroserviceInstancePing;
-import org.awaitility.Awaitility;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-
-import mockit.Deencapsulation;
-import mockit.Expectations;
-import mockit.Injectable;
-import mockit.Mocked;
-import org.junit.jupiter.api.Assertions;
-
-public class TestServiceCombLoadBalancerStats {
- @Before
- public void before() {
- // Ensure clean all of mocked server cache before running testMultiThread
- // Or the mocked server without instance will cause NPE and the target server will never get ping mark failure
- Map<ServiceCombServer, ServiceCombServerStats> pingView =
- Deencapsulation.getField(ServiceCombLoadBalancerStats.INSTANCE, "pingView");
- pingView.clear();
- ServiceCombLoadBalancerStats.INSTANCE.init();
- }
-
- @AfterClass
- public static void afterClass() {
- Map<ServiceCombServer, ServiceCombServerStats> pingView =
- Deencapsulation.getField(ServiceCombLoadBalancerStats.INSTANCE, "pingView");
- pingView.clear();
- ServiceCombLoadBalancerStats.INSTANCE.init();
- }
-
- @Test
- public void testServiceExpire(@Injectable Transport transport, @Mocked SPIServiceUtils utils, @Injectable
- MicroserviceInstancePing ping) {
- MicroserviceInstance instance = new MicroserviceInstance();
- instance.setInstanceId("instance1");
-
- new Expectations() {
- {
- SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class);
- result = ping;
- ping.ping(instance);
- result = false;
- }
- };
-
- ServiceCombLoadBalancerStats serviceCombLoadBalancerStats = new ServiceCombLoadBalancerStats();
- serviceCombLoadBalancerStats.setServerExpireInSeconds(2);
- serviceCombLoadBalancerStats.setTimerIntervalInMillis(500);
- serviceCombLoadBalancerStats.init();
-
- ServiceCombServer serviceCombServer = new ServiceCombServer(null, transport,
- new CacheEndpoint("rest://localhost:8080", instance));
- serviceCombLoadBalancerStats.markSuccess(serviceCombServer);
- ServiceCombServerStats stats = serviceCombLoadBalancerStats.getServiceCombServerStats(serviceCombServer);
- Assertions.assertEquals(serviceCombLoadBalancerStats.getPingView().size(), 1);
- Awaitility.await().atMost(5, TimeUnit.SECONDS)
- .until(() -> serviceCombLoadBalancerStats.getPingView().size() <= 0);
- Assertions.assertEquals(serviceCombLoadBalancerStats.getPingView().size(), 0);
- System.out.print(stats.getFailedRequests());
- Assertions.assertTrue(stats.getFailedRequests() >= 1);
- }
-
- @Test
- public void testSimpleThread(@Injectable Transport transport) {
- long time = System.currentTimeMillis();
- MicroserviceInstance instance = new MicroserviceInstance();
- instance.setInstanceId("instance1");
- ServiceCombServer serviceCombServer = new ServiceCombServer(null, transport,
- new CacheEndpoint("rest://localhost:8080", instance));
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getContinuousFailureCount(),
- 2);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getContinuousFailureCount(),
- 0);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer);
- Assertions
- .assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getTotalRequests(), 4);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRate(), 50);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getSuccessRate(), 50);
- Assertions.assertTrue(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime() <= System
- .currentTimeMillis()
- && ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime()
- >= time);
- }
-
- @Test
- public void testMultiThread(@Injectable Transport transport) throws Exception {
- long time = System.currentTimeMillis();
- MicroserviceInstance instance = new MicroserviceInstance();
- instance.setInstanceId("instance2");
- ServiceCombServer serviceCombServer = new ServiceCombServer(null, transport,
- new CacheEndpoint("rest://localhost:8080", instance));
-
- CountDownLatch latch = new CountDownLatch(10);
- for (int i = 0; i < 10; i++) {
- new Thread(() -> {
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer);
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer);
- latch.countDown();
- }).start();
- }
- latch.await(30, TimeUnit.SECONDS);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getTotalRequests(),
- 4 * 10);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRate(), 50);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getSuccessRate(), 50);
- Assertions.assertEquals(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getSuccessRequests(), 20);
- Assertions.assertTrue(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime() <= System
- .currentTimeMillis()
- && ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime()
- >= time);
-
- // time consuming test for timers, taking about 20 seconds. ping timer will update instance status to failure
- Assertions.assertTrue(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRate() <= 50);
- long beginTime = System.currentTimeMillis();
- long rate = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRequests();
- while (rate <= 20 &&
- System.currentTimeMillis() - beginTime <= 30000) {
- Thread.sleep(2000);
- rate = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRequests();
- System.out.println("failedRequests: " + rate);
- }
-
- Assertions.assertTrue(System.currentTimeMillis() - beginTime < 30000);
- Assertions
- .assertTrue(
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRequests()
- > 20);
- }
-}
diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServerStats.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServerStats.java
deleted file mode 100644
index b8c0c1c27..000000000
--- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServerStats.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance;
-
-import java.util.Optional;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.foundation.test.scaffolding.time.MockClock;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.jupiter.api.Assertions;
-
-public class TestServiceCombServerStats {
- @Before
- public void before() {
- releaseTryingChance();
- }
-
- @After
- public void after() {
- releaseTryingChance();
- }
-
- @Test
- public void testSimpleThread() {
- long time = System.currentTimeMillis();
- ServiceCombServerStats stats = new ServiceCombServerStats(null);
- stats.markFailure();
- stats.markFailure();
- Assertions.assertEquals(2, stats.getContinuousFailureCount());
- stats.markSuccess();
- Assertions.assertEquals(0, stats.getContinuousFailureCount());
- stats.markSuccess();
- Assertions.assertEquals(4, stats.getTotalRequests());
- Assertions.assertEquals(50, stats.getFailedRate());
- Assertions.assertEquals(50, stats.getSuccessRate());
- Assertions.assertTrue(stats.getLastVisitTime() <= System.currentTimeMillis() && stats.getLastVisitTime() >= time);
- Assertions.assertTrue(stats.getLastActiveTime() <= System.currentTimeMillis() && stats.getLastActiveTime() >= time);
- }
-
- @Test
- public void testMiltiThread() throws Exception {
- long time = System.currentTimeMillis();
- ServiceCombServerStats stats = new ServiceCombServerStats(null);
- CountDownLatch latch = new CountDownLatch(10);
- for (int i = 0; i < 10; i++) {
- new Thread(() -> {
- stats.markFailure();
- stats.markFailure();
- stats.markSuccess();
- stats.markSuccess();
- latch.countDown();
- }).start();
- }
- latch.await(30, TimeUnit.SECONDS);
- Assertions.assertEquals(4 * 10, stats.getTotalRequests());
- Assertions.assertEquals(50, stats.getFailedRate());
- Assertions.assertEquals(50, stats.getSuccessRate());
- Assertions.assertTrue(stats.getLastVisitTime() <= System.currentTimeMillis() && stats.getLastVisitTime() >= time);
- Assertions.assertTrue(stats.getLastActiveTime() <= System.currentTimeMillis() && stats.getLastActiveTime() >= time);
- }
-
- @Test
- public void testTimeWindow() {
- ServiceCombServerStats stats = new ServiceCombServerStats(null, new MockClock(1000L));
- Assertions.assertEquals(1000, stats.getLastVisitTime());
- stats.markSuccess();
- stats.markFailure();
- Assertions.assertEquals(2, stats.getTotalRequests());
- Assertions.assertEquals(50, stats.getFailedRate());
- Assertions.assertEquals(50, stats.getSuccessRate());
- stats.clock = new MockClock(60000L + 2000L);
- stats.markSuccess();
- Assertions.assertEquals(1, stats.getTotalRequests());
- Assertions.assertEquals(0, stats.getFailedRate());
- Assertions.assertEquals(100, stats.getSuccessRate());
- }
-
- @Test
- public void testGlobalAllowIsolatedServerTryingFlag_apply_with_null_precondition() {
- Invocation invocation = new Invocation();
- Assertions.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation));
- Assertions.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation());
- }
-
- @Test
- public void testGlobalAllowIsolatedServerTryingFlag_apply_with_chance_occupied() {
- Invocation invocation = new Invocation();
- Assertions.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation));
- Assertions.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation());
-
- Invocation otherInvocation = new Invocation();
- Assertions.assertFalse(ServiceCombServerStats.applyForTryingChance(otherInvocation));
- Assertions.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation());
- }
-
- @Test
- public void testGlobalAllowIsolatedServerTryingFlag_apply_with_flag_outdated() {
- Invocation invocation = new Invocation();
- Assertions.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation));
- Assertions.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation());
- ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().clock = new MockClock(
- ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().startTryingTimestamp + 60000
- );
-
- Invocation otherInvocation = new Invocation();
- Assertions.assertTrue(ServiceCombServerStats.applyForTryingChance(otherInvocation));
- Assertions
- .assertSame(otherInvocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation());
- }
-
- public static void releaseTryingChance() {
- ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.set(null);
- }
-
- public static Invocation getTryingIsolatedServerInvocation() {
- return Optional.ofNullable(ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get())
- .map(TryingIsolatedServerMarker::getInvocation)
- .orElse(null);
- }
-}
diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilterTest.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilterTest.java
deleted file mode 100644
index 78b4d0cfd..000000000
--- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilterTest.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * 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 org.apache.servicecomb.loadbalance.filter;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.core.Transport;
-import org.apache.servicecomb.loadbalance.Configuration;
-import org.apache.servicecomb.loadbalance.ServiceCombLoadBalancerStats;
-import org.apache.servicecomb.loadbalance.ServiceCombServer;
-import org.apache.servicecomb.loadbalance.ServiceCombServerStats;
-import org.apache.servicecomb.loadbalance.TestServiceCombServerStats;
-import org.apache.servicecomb.loadbalance.filterext.IsolationDiscoveryFilter;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.registry.cache.CacheEndpoint;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
-import org.mockito.Mockito;
-
-import mockit.Deencapsulation;
-import mockit.Mocked;
-
-@TestInstance(TestInstance.Lifecycle.PER_CLASS)
-public class IsolationDiscoveryFilterTest {
-
- private IsolationDiscoveryFilter filter;
-
- private List<ServiceCombServer> servers;
-
- @Mocked
- private Transport transport = Mockito.mock(Transport.class);
-
- private Invocation invocation = new Invocation() {
- @Override
- public String getMicroserviceName() {
- return "testMicroserviceName";
- }
- };
-
- @BeforeEach
- public void before() {
- Mockito.doAnswer(a -> a.getArguments()[0]).when(transport).parseAddress(Mockito.anyString());
- servers = new ArrayList<>();
- for (int i = 0; i < 3; ++i) {
- MicroserviceInstance instance = new MicroserviceInstance();
- instance.setInstanceId("i" + i);
- String endpoint = "rest://127.0.0.1:" + i;
- instance.setEndpoints(Collections.singletonList(endpoint));
- ServiceCombServer serviceCombServer = new ServiceCombServer(invocation.getMicroserviceName(), transport,
- new CacheEndpoint(endpoint, instance));
- servers.add(serviceCombServer);
- ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer);
- }
-
- filter = new IsolationDiscoveryFilter();
- TestServiceCombServerStats.releaseTryingChance();
- }
-
- @AfterEach
- public void after() {
- ServiceCombLoadBalancerStats.INSTANCE.init();
- TestServiceCombServerStats.releaseTryingChance();
- }
-
- @Test
- public void discoveryNoInstanceReachErrorThreshold() {
- List<ServiceCombServer> filteredServers = filter.getFilteredListOfServers(servers, invocation);
-
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
- }
-
- @Test
- public void discoveryIsolateErrorInstance() {
- ServiceCombServer server0 = servers.get(0);
- for (int i = 0; i < 4; ++i) {
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server0);
- }
- List<ServiceCombServer> filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
-
- // by default 5 times continuous failure will cause isolation
- ServiceCombLoadBalancerStats.INSTANCE.markFailure(server0);
- Assertions.assertFalse(ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server0).isIsolated());
-
- filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 2);
- Assertions.assertEquals(servers.get(1), filteredServers.get(0));
- Assertions.assertEquals(servers.get(2), filteredServers.get(1));
- Assertions.assertTrue(ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server0).isIsolated());
- }
-
- @Test
- public void discoveryTryIsolatedInstanceAfterSingleTestTime() {
- ServiceCombServer server0 = servers.get(0);
- ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE
- .getServiceCombServerStats(server0);
- for (int i = 0; i < 5; ++i) {
- serviceCombServerStats.markFailure();
- }
- letIsolatedInstancePassSingleTestTime(serviceCombServerStats);
- ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true);
-
- Assertions.assertTrue(ServiceCombServerStats.isolatedServerCanTry());
- Assertions.assertNull(TestServiceCombServerStats.getTryingIsolatedServerInvocation());
- List<ServiceCombServer> filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
- Assertions.assertTrue(serviceCombServerStats.isIsolated());
- Assertions.assertFalse(ServiceCombServerStats.isolatedServerCanTry());
- Assertions.assertSame(invocation, TestServiceCombServerStats.getTryingIsolatedServerInvocation());
- }
-
- @Test
- public void discoveryNotTryIsolatedInstanceConcurrently() {
- ServiceCombServer server0 = servers.get(0);
- ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE
- .getServiceCombServerStats(server0);
- for (int i = 0; i < 5; ++i) {
- serviceCombServerStats.markFailure();
- }
- ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true);
- letIsolatedInstancePassSingleTestTime(serviceCombServerStats);
-
- Assertions.assertTrue(ServiceCombServerStats.isolatedServerCanTry());
-
- // The first invocation can occupy the trying chance
- List<ServiceCombServer> filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
- Assertions.assertFalse(ServiceCombServerStats.isolatedServerCanTry());
-
- // Other invocation cannot get trying chance concurrently
- filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 2);
- Assertions.assertEquals(servers.get(1), filteredServers.get(0));
- Assertions.assertEquals(servers.get(2), filteredServers.get(1));
-
- ServiceCombServerStats
- .checkAndReleaseTryingChance(invocation); // after the first invocation releases the trying chance
-
- // Other invocation can get the trying chance
- filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
- Assertions.assertFalse(ServiceCombServerStats.isolatedServerCanTry());
- }
-
- private ServiceCombServerStats letIsolatedInstancePassSingleTestTime(ServiceCombServerStats serviceCombServerStats) {
- Deencapsulation.setField(serviceCombServerStats, "lastActiveTime",
- System.currentTimeMillis() - 1 - Configuration.INSTANCE.getSingleTestTime(invocation.getMicroserviceName()));
- Deencapsulation.setField(serviceCombServerStats, "lastVisitTime",
- System.currentTimeMillis() - 1 - Configuration.INSTANCE.getSingleTestTime(invocation.getMicroserviceName()));
- return serviceCombServerStats;
- }
-
- @Test
- public void discoveryKeepMinIsolationTime() {
- ServiceCombServer server0 = servers.get(0);
- ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server0);
-
- List<ServiceCombServer> filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 2);
- Assertions.assertEquals(servers.get(1), filteredServers.get(0));
- Assertions.assertEquals(servers.get(2), filteredServers.get(1));
-
- ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE
- .getServiceCombServerStats(server0);
- Deencapsulation.setField(serviceCombServerStats, "isolatedTime",
- System.currentTimeMillis() - Configuration.INSTANCE.getMinIsolationTime(invocation.getMicroserviceName()) - 1);
- filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
- }
-
- @Test
- public void discoveryRecoverInstance() {
- ServiceCombServer server0 = servers.get(0);
- ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server0);
- ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE
- .getServiceCombServerStats(server0);
-
- ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true);
- Deencapsulation.setField(serviceCombServerStats, "isolatedTime",
- System.currentTimeMillis() - Configuration.INSTANCE.getMinIsolationTime(invocation.getMicroserviceName()) - 1);
-
- List<ServiceCombServer> filteredServers = filter.getFilteredListOfServers(servers, invocation);
- Assertions.assertEquals(filteredServers.size(), 3);
- Assertions.assertEquals(servers.get(0), filteredServers.get(0));
- Assertions.assertEquals(servers.get(1), filteredServers.get(1));
- Assertions.assertEquals(servers.get(2), filteredServers.get(2));
- Assertions.assertFalse(ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server0).isIsolated());
- }
-}