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/incubator-servicecomb-java-chassis.git
commit 1878b4b3d0b79963e6892592be0ce32fa537da78 Author: liubao <[email protected]> AuthorDate: Fri Aug 24 21:40:40 2018 +0800 [SBC-870]refractor to using custom RuleExt, not using Robin IRule. --- .../common/rest/codec/RestObjectMapper.java | 2 + .../jaxrs/client/CodeFirstRestTemplateJaxrs.java | 2 +- .../client/CustomLoadbalanceExtensionsFactory.java | 6 +- .../src/main/resources/microservice.yaml | 4 +- .../demo/springmvc/client/SpringmvcClient.java | 12 ++ .../src/main/resources/microservice.yaml | 3 +- .../servicecomb/loadbalance/Configuration.java | 10 -- .../servicecomb/loadbalance/ExtensionsFactory.java | 2 +- .../servicecomb/loadbalance/ExtensionsManager.java | 14 +- .../servicecomb/loadbalance/LoadBalancer.java | 78 +++------- .../loadbalance/LoadBalancerCreator.java | 44 +----- .../loadbalance/LoadbalanceHandler.java | 48 +++---- .../servicecomb/loadbalance/RandomRuleExt.java} | 20 +-- .../loadbalance/RoundRobinRuleExt.java} | 20 +-- .../RuleClassNameExtentionsFactory.java | 62 -------- .../apache/servicecomb/loadbalance/RuleExt.java} | 17 +-- .../loadbalance/RuleNameExtentionsFactory.java | 12 +- .../loadbalance/ServerListFilterExt.java | 12 +- .../loadbalance/ServiceCombLoadBalancerStats.java | 23 ++- .../servicecomb/loadbalance/ServiceCombServer.java | 16 +++ .../loadbalance/ServiceCombServerStats.java | 19 ++- .../loadbalance/SessionStickinessRule.java | 70 ++++----- .../loadbalance/WeightedResponseTimeRuleExt.java | 65 +++++++++ .../loadbalance/MyServerListFilterExt.java | 2 +- .../servicecomb/loadbalance/TestConfiguration.java | 2 - .../loadbalance/TestExtensionsManager.java | 31 +--- .../loadbalance/TestLoadBalanceCreator.java | 159 ++++++++++++--------- .../loadbalance/TestLoadBalanceHandler2.java | 38 ++--- .../servicecomb/loadbalance/TestLoadBalancer.java | 110 ++------------ .../loadbalance/TestLoadbalanceHandler.java | 3 +- .../TestServiceCombLoadBalancerStats.java | 20 +-- .../loadbalance/TestServiceCombServerStats.java | 22 +-- .../loadbalance/TestSessionSticknessRule.java | 91 ++++++------ .../filter/TestServerDiscoveryFilter.java | 1 + .../swagger/engine/SwaggerProducerOperation.java | 8 ++ 35 files changed, 455 insertions(+), 593 deletions(-) diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java index f94ec2c..327175b 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapper.java @@ -65,6 +65,8 @@ public class RestObjectMapper extends AbstractRestObjectMapper { disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + // If required=true, need to fail, while required=false, default values is given. + enable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES); SimpleModule module = new SimpleModule(); // custom types diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java index 38ae6e9..2481e52 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java @@ -110,7 +110,7 @@ public class CodeFirstRestTemplateJaxrs extends CodeFirstRestTemplate { private void test404(RestTemplate template) { HttpClientErrorException exception = null; try { - template.getForEntity("http://127.0.0.1:8080/aPathNotExist", String.class); + template.getForEntity("http://127.0.0.1:8086/aPathNotExist", String.class); } catch (RestClientException e) { if (e instanceof HttpClientErrorException) { exception = (HttpClientErrorException) e; diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java index cb0eef6..c015165 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java @@ -18,6 +18,8 @@ package org.apache.servicecomb.demo.jaxrs.client; import org.apache.servicecomb.loadbalance.Configuration; import org.apache.servicecomb.loadbalance.ExtensionsFactory; +import org.apache.servicecomb.loadbalance.RoundRobinRuleExt; +import org.apache.servicecomb.loadbalance.RuleExt; import org.springframework.stereotype.Component; import com.netflix.client.DefaultLoadBalancerRetryHandler; @@ -29,7 +31,7 @@ import com.netflix.loadbalancer.RoundRobinRule; @Component public class CustomLoadbalanceExtensionsFactory implements ExtensionsFactory { - class MyCustomRule extends RoundRobinRule { + class MyCustomRule extends RoundRobinRuleExt { } @@ -56,7 +58,7 @@ public class CustomLoadbalanceExtensionsFactory implements ExtensionsFactory { } @Override - public IRule createLoadBalancerRule(String ruleName) { + public RuleExt createLoadBalancerRule(String ruleName) { return new MyCustomRule(); } diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml b/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml index 89f324c..c4bbcdd 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml +++ b/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml @@ -24,9 +24,9 @@ servicecomb: registry: address: http://127.0.0.1:30100 rest: - address: 0.0.0.0:8080 + address: 0.0.0.0:8086 highway: - address: 0.0.0.0:7070 + address: 0.0.0.0:7076 handler: chain: Provider: diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java index 3e5aa1c..2a41e0a 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java @@ -167,6 +167,18 @@ public class SpringmvcClient { private static void testController(RestTemplate template, String microserviceName) { String prefix = "cse://" + microserviceName; + TestMgr.check(7, + template.getForObject(prefix + "/controller/add?a=3&b=4", + Integer.class)); + + try { + template.getForObject(prefix + "/controller/add", + Integer.class); + TestMgr.check("failed", "success"); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 400); + } + TestMgr.check("hi world [world]", template.getForObject(prefix + "/controller/sayhi?name=world", String.class)); diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml index 2290b6f..03b137c 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml +++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml @@ -56,7 +56,8 @@ servicecomb: enabled: true samplingRate: 0.5 loadbalance: - NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule + strategy: + name: WeightedResponse retryEnabled: true retryOnSame: 1 retryOnNext: 1 diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java index f2f8f62..2268855 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java @@ -35,8 +35,6 @@ public final class Configuration { public static final String RPOP_TIMER_INTERVAL_IN_MINIS = "servicecomb.loadbalance.stats.timerIntervalInMilis"; - public static final String PROP_POLICY = "NFLoadBalancerRuleClassName"; - public static final String PROP_RULE_STRATEGY_NAME = "strategy.name"; // 2.0 configuration items @@ -91,14 +89,6 @@ public final class Configuration { private Configuration() { } - public String getPolicy(String microservice) { - return getStringProperty(null, - PROP_ROOT + microservice + "." + PROP_POLICY, - PROP_ROOT_20 + microservice + "." + PROP_POLICY, - PROP_ROOT + PROP_POLICY, - PROP_ROOT_20 + PROP_POLICY); - } - public String getRuleStrategyName(String microservice) { return getStringProperty(null, PROP_ROOT + microservice + "." + PROP_RULE_STRATEGY_NAME, diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java index fa97372..9077575 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java @@ -25,7 +25,7 @@ import com.netflix.loadbalancer.IRule; public interface ExtensionsFactory { boolean isSupport(String key, String value); - default IRule createLoadBalancerRule(String ruleName) { + default RuleExt createLoadBalancerRule(String ruleName) { return null; } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java index 15edefe..2df0395 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java @@ -23,8 +23,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.client.RetryHandler; -import com.netflix.loadbalancer.IRule; -import com.netflix.loadbalancer.RoundRobinRule; public class ExtensionsManager { private static final Logger LOGGER = LoggerFactory.getLogger(ExtensionsManager.class); @@ -35,15 +33,11 @@ public class ExtensionsManager { extentionFactories.add(factory); } - public static IRule createLoadBalancerRule(String microservice) { - IRule rule = null; + public static RuleExt createLoadBalancerRule(String microservice) { + RuleExt rule = null; for (ExtensionsFactory factory : extentionFactories) { - if (factory.isSupport(Configuration.PROP_POLICY, Configuration.INSTANCE.getPolicy(microservice))) { - rule = factory.createLoadBalancerRule( - Configuration.INSTANCE.getPolicy(microservice)); - break; - } else if (factory.isSupport(Configuration.PROP_RULE_STRATEGY_NAME, + if (factory.isSupport(Configuration.PROP_RULE_STRATEGY_NAME, Configuration.INSTANCE.getRuleStrategyName(microservice))) { rule = factory.createLoadBalancerRule( Configuration.INSTANCE.getRuleStrategyName(microservice)); @@ -52,7 +46,7 @@ public class ExtensionsManager { } if (rule == null) { - rule = new RoundRobinRule(); + rule = new RoundRobinRuleExt(); } LOGGER.info("Using load balance rule {} for microservice {}.", rule.getClass().getName(), microservice); 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 56db6ff..3a96b59 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 @@ -17,83 +17,45 @@ package org.apache.servicecomb.loadbalance; -import java.util.Collections; import java.util.List; -import com.netflix.loadbalancer.AbstractLoadBalancer; -import com.netflix.loadbalancer.IRule; +import org.apache.servicecomb.core.Invocation; + import com.netflix.loadbalancer.LoadBalancerStats; -import com.netflix.loadbalancer.Server; /** - * Robbin LoadBalancer implementation. Only support IRule and basic operations. + * A load balancer with RuleExt and ServerListFilterExt */ -public class LoadBalancer extends AbstractLoadBalancer { - private List<Server> serverList = Collections.emptyList(); - - private IRule rule; +public class LoadBalancer { + private RuleExt rule; private LoadBalancerStats lbStats; private String microServiceName; - public LoadBalancer(IRule rule, String microServiceName, - LoadBalancerStats stats) { + private List<ServerListFilterExt> filters; + + private List<ServiceCombServer> servers; + + public LoadBalancer(RuleExt rule, String microServiceName, + LoadBalancerStats stats, List<ServerListFilterExt> filters, List<ServiceCombServer> servers) { this.microServiceName = microServiceName; this.rule = rule; this.lbStats = stats; - } - - public void setServerList(List<Server> serverList) { - this.serverList = Collections.unmodifiableList(serverList); - } - - @Override - public void addServers(List<Server> newServers) { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - public Server chooseServer(Object key) { - // rule is shared across loadbalancers, so it will get concurrent access problems that it's owned loadbalancer is - // not 'this', but this is fine to use other loadbalancer instances only when serverList is correctly set + this.filters = filters; + this.servers = servers; this.rule.setLoadBalancer(this); - return rule.choose(key); - } - - @Override - public void markServerDown(Server server) { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - @Deprecated - public List<Server> getServerList(boolean availableOnly) { - return getAllServers(); - } - - @Override - public List<Server> getReachableServers() { - return getAllServers(); - } - - @Override - // Different types of Robin Component Rule have different usages for server status and list. - // e.g. RoundRobinRule using getAllServers & alive & readyToServe - // RandomRule using getReachableServers & alive - // WeightedResponseTimeRule using getAllServers & alive - // To make all rules work only on "how to choose a server from alive servers", we do not rely on Robbin getReachableServers. - // We ensure getReachableServers & getAllServers work in the same way. - public List<Server> getAllServers() { - return serverList; + this.filters.forEach((item) -> item.setLoadBalancer(this)); } - @Override - public List<Server> getServerList(ServerGroup serverGroup) { - throw new UnsupportedOperationException("Not implemented."); + public ServiceCombServer chooseServer(Invocation invocation) { + List<ServiceCombServer> temp = this.servers; + for (ServerListFilterExt filterExt : filters) { + temp = filterExt.getFilteredListOfServers(temp, invocation); + } + return rule.choose(temp, invocation); } - @Override public LoadBalancerStats getLoadBalancerStats() { return lbStats; } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java index eedbb9c..5cb18dc 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancerCreator.java @@ -17,19 +17,12 @@ package org.apache.servicecomb.loadbalance; -import java.util.Collections; import java.util.List; -import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; -import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.LoadBalancerStats; -import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.WeightedResponseTimeRule; /** * Create a suitable load balancer for each invocation. @@ -45,11 +38,7 @@ import com.netflix.loadbalancer.WeightedResponseTimeRule; * on the result of ServerListFilter, they should not contain operation level state information in instance fields. */ public class LoadBalancerCreator { - private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalancerCreator.class); - - private List<Server> serverList = Collections.emptyList(); - - private IRule rule; + private RuleExt rule; private LoadBalancerStats lbStats; @@ -57,7 +46,7 @@ public class LoadBalancerCreator { private String microServiceName; - public LoadBalancerCreator(IRule rule, String microServiceName) { + public LoadBalancerCreator(RuleExt rule, String microServiceName) { this.rule = rule; this.microServiceName = microServiceName; this.lbStats = new LoadBalancerStats(null); @@ -66,20 +55,7 @@ public class LoadBalancerCreator { } public void shutdown() { - // netflix components does not have a proper way to shutdown laodbalancers so we do it in a not quite elegant way. - if (this.rule instanceof WeightedResponseTimeRule) { - ((WeightedResponseTimeRule) this.rule).shutdown(); - } - } - - // every filter group has a loadBalancer instance - // serverList almost not changed for different invocation - // so every invocation will call setServerList, this is no problem - public void setServerList(List<Server> serverList) { - if (serverList.isEmpty()) { - LOGGER.warn("Set empty server list."); - } - this.serverList = Collections.unmodifiableList(serverList); + // nothing to do now } @VisibleForTesting @@ -87,17 +63,7 @@ public class LoadBalancerCreator { this.filters = filters; } - public LoadBalancer createLoadBalancer(Invocation invocation) { - LoadBalancer loadBalancer = new LoadBalancer(rule, microServiceName, lbStats); - List<Server> servers = this.serverList; - for (ServerListFilterExt filter : this.filters) { - filter.setLoadBalancer(loadBalancer); - servers = filter.getFilteredListOfServers(servers, invocation); - if (servers.isEmpty()) { - LOGGER.warn("Filter {} get empty list.", filter.getClass().getName()); - } - } - loadBalancer.setServerList(servers); - return loadBalancer; + public LoadBalancer createLoadBalancer(List<ServiceCombServer> servers) { + return new LoadBalancer(rule, microServiceName, lbStats, filters, servers); } } 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 7d6394a..06f4b10 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 @@ -45,7 +45,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.netflix.loadbalancer.ILoadBalancer; -import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.reactive.ExecutionContext; import com.netflix.loadbalancer.reactive.ExecutionInfo; @@ -56,8 +55,7 @@ import com.netflix.loadbalancer.reactive.ServerOperation; import rx.Observable; /** - * 负载均衡处理链 - * + * Load balance handler. */ public class LoadbalanceHandler implements Handler { // just a wrapper to make sure in retry mode to choose a different server. @@ -67,21 +65,23 @@ public class LoadbalanceHandler implements Handler { Server lastServer = null; - ILoadBalancer delegate; + LoadBalancer delegate; + + Invocation invocation; - RetryLoadBalancer(ILoadBalancer delegate) { + RetryLoadBalancer(LoadBalancer delegate, Invocation invocation) { this.delegate = delegate; } @Override public void addServers(List<Server> newServers) { - delegate.addServers(newServers); + throw new UnsupportedOperationException("Not implemented."); } @Override public Server chooseServer(Object key) { for (int i = 0; i < COUNT; i++) { - Server s = delegate.chooseServer(key); + Server s = delegate.chooseServer(invocation); if (s != null && !s.equals(lastServer)) { lastServer = s; break; @@ -94,23 +94,23 @@ public class LoadbalanceHandler implements Handler { @Override public void markServerDown(Server server) { - delegate.markServerDown(server); + throw new UnsupportedOperationException("Not implemented."); } @Override @Deprecated public List<Server> getServerList(boolean availableOnly) { - return delegate.getServerList(availableOnly); + throw new UnsupportedOperationException("Not implemented."); } @Override public List<Server> getReachableServers() { - return delegate.getReachableServers(); + throw new UnsupportedOperationException("Not implemented."); } @Override public List<Server> getAllServers() { - return delegate.getAllServers(); + throw new UnsupportedOperationException("Not implemented."); } } @@ -135,8 +135,6 @@ public class LoadbalanceHandler implements Handler { private final Object lock = new Object(); - private String policy = null; - private String strategy = null; @@ -148,16 +146,13 @@ public class LoadbalanceHandler implements Handler { @Override public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - String policy = Configuration.INSTANCE.getPolicy(invocation.getMicroserviceName()); String strategy = Configuration.INSTANCE.getRuleStrategyName(invocation.getMicroserviceName()); - boolean isRuleNotChanged = isEqual(policy, this.policy) && isEqual(strategy, this.strategy); - if (!isRuleNotChanged) { + if (!isEqual(strategy, this.strategy)) { //配置变化,需要重新生成所有的lb实例 synchronized (lock) { clearLoadBalancer(); } } - this.policy = policy; this.strategy = strategy; LoadBalancer loadBalancer = getOrCreateLoadBalancer(invocation); @@ -199,10 +194,10 @@ public class LoadbalanceHandler implements Handler { chosenLB.getLoadBalancerStats().noteResponseTime(server, (System.currentTimeMillis() - time)); if (isFailedResponse(resp)) { chosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(server, System.currentTimeMillis() - time); } else { chosenLB.getLoadBalancerStats().incrementActiveRequestsCount(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server, (System.currentTimeMillis() - time)); } asyncResp.handle(resp); }); @@ -287,7 +282,7 @@ public class LoadbalanceHandler implements Handler { ExecutionContext<Invocation> context = new ExecutionContext<>(invocation, null, null, null); LoadBalancerCommand<Response> command = LoadBalancerCommand.<Response>builder() - .withLoadBalancer(new RetryLoadBalancer(chosenLB)) + .withLoadBalancer(new RetryLoadBalancer(chosenLB, invocation)) .withServerLocator(invocation) .withRetryHandler(ExtensionsManager.createRetryHandler(invocation.getMicroserviceName())) .withListeners(listeners) @@ -309,13 +304,13 @@ public class LoadbalanceHandler implements Handler { ((Throwable) resp.getResult()).getMessage(), s); chosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(server, System.currentTimeMillis() - time); f.onError(resp.getResult()); } else { chosenLB.getLoadBalancerStats().incrementActiveRequestsCount(s); chosenLB.getLoadBalancerStats().noteResponseTime(s, (System.currentTimeMillis() - time)); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server, (System.currentTimeMillis() - time)); f.onNext(resp); f.onCompleted(); } @@ -359,15 +354,16 @@ public class LoadbalanceHandler implements Handler { LoadBalancerCreator loadBalancerCreator = loadBalancerMap.computeIfAbsent(serversVersionedCache.name(), name -> { return createLoadBalancerCreator(invocation.getMicroserviceName()); }); - loadBalancerCreator.setServerList(serversVersionedCache.data()); - // help users to deal with incompatible changes. + + // Nothing to do just help users to deal with incompatible changes. setTransactionControlFilter(invocation.getMicroserviceName()); loadServerListFilters(); - return loadBalancerCreator.createLoadBalancer(invocation); + + return loadBalancerCreator.createLoadBalancer(serversVersionedCache.data()); } private LoadBalancerCreator createLoadBalancerCreator(String microserviceName) { - IRule rule = ExtensionsManager.createLoadBalancerRule(microserviceName); + RuleExt rule = ExtensionsManager.createLoadBalancerRule(microserviceName); LoadBalancerCreator creator = new LoadBalancerCreator(rule, microserviceName); return creator; } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java similarity index 72% copy from handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java copy to handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java index ed08789..60eedac 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java @@ -17,23 +17,23 @@ package org.apache.servicecomb.loadbalance; -import java.util.ArrayList; import java.util.List; +import java.util.Random; import org.apache.servicecomb.core.Invocation; -import com.netflix.loadbalancer.Server; - /** - * @author l00168639 - * + * A random rule. */ -public class MyServerListFilterExt implements ServerListFilterExt { +public class RandomRuleExt implements RuleExt { + private Random random = new Random(); + @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { - if (invocation.getAppId().equals("test")) { - return new ArrayList<>(); + public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation invocation) { + if (servers.size() == 0) { + return null; } - return serverList; + int index = Math.abs(random.nextInt()) % servers.size(); + return servers.get(index); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java similarity index 69% copy from handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java copy to handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java index ed08789..c3a887d 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java @@ -17,23 +17,23 @@ package org.apache.servicecomb.loadbalance; -import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.core.Invocation; -import com.netflix.loadbalancer.Server; - /** - * @author l00168639 - * + * A round robin rule */ -public class MyServerListFilterExt implements ServerListFilterExt { +public class RoundRobinRuleExt implements RuleExt { + private AtomicInteger counter = new AtomicInteger(0); + @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { - if (invocation.getAppId().equals("test")) { - return new ArrayList<>(); + public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation invocation) { + if (servers.size() == 0) { + return null; } - return serverList; + int index = Math.abs(counter.getAndIncrement()) % servers.size(); + return servers.get(index); } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleClassNameExtentionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleClassNameExtentionsFactory.java deleted file mode 100644 index b6df5ef..0000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleClassNameExtentionsFactory.java +++ /dev/null @@ -1,62 +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.Collection; - -import org.apache.commons.lang.StringUtils; -import org.apache.servicecomb.foundation.common.utils.JvmUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import com.google.common.collect.Lists; -import com.netflix.loadbalancer.IRule; -import com.netflix.loadbalancer.RoundRobinRule; - -/** - * 兼容老版本的Rule相关的配置项 - */ -@Component -public class RuleClassNameExtentionsFactory implements ExtensionsFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(RuleClassNameExtentionsFactory.class); - - private static final Collection<String> ACCEPT_KEYS = Lists.newArrayList( - Configuration.PROP_POLICY); - - // possible values - // "com.netflix.loadbalancer.RoundRobinRule" - // "com.netflix.loadbalancer.WeightedResponseTimeRule" - // "com.netflix.loadbalancer.RandomRule" - // "org.apache.servicecomb.loadbalance.SessionStickinessRule" - @Override - public boolean isSupport(String key, String value) { - return ACCEPT_KEYS.contains(key) && StringUtils.isNotEmpty(value); - } - - @Override - public IRule createLoadBalancerRule(String ruleName) { - IRule rule; - try { - rule = (IRule) Class.forName(ruleName, true, JvmUtils.findClassLoader()).newInstance(); - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { - LOGGER.warn("Loadbalance rule [{}] is incorrect, using default RoundRobinRule.", ruleName); - rule = new RoundRobinRule(); - } - return rule; - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleExt.java similarity index 71% copy from handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java copy to handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleExt.java index ed08789..a95ccbc 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleExt.java @@ -17,23 +17,16 @@ package org.apache.servicecomb.loadbalance; -import java.util.ArrayList; import java.util.List; import org.apache.servicecomb.core.Invocation; -import com.netflix.loadbalancer.Server; - /** - * @author l00168639 - * + * Load balance rule to support invocation based filters. */ -public class MyServerListFilterExt implements ServerListFilterExt { - @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { - if (invocation.getAppId().equals("test")) { - return new ArrayList<>(); - } - return serverList; +public interface RuleExt { + default void setLoadBalancer(LoadBalancer loadBalancer) { } + + ServiceCombServer choose(List<ServiceCombServer> servers, Invocation invocation); } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java index 92d5be2..5ab7cfb 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java @@ -21,10 +21,6 @@ import java.util.Collection; import org.springframework.stereotype.Component; import com.google.common.collect.Lists; -import com.netflix.loadbalancer.IRule; -import com.netflix.loadbalancer.RandomRule; -import com.netflix.loadbalancer.RoundRobinRule; -import com.netflix.loadbalancer.WeightedResponseTimeRule; @Component public class RuleNameExtentionsFactory implements ExtensionsFactory { @@ -51,13 +47,13 @@ public class RuleNameExtentionsFactory implements ExtensionsFactory { } @Override - public IRule createLoadBalancerRule(String ruleName) { + public RuleExt createLoadBalancerRule(String ruleName) { if (RULE_RoundRobin.equals(ruleName)) { - return new RoundRobinRule(); + return new RoundRobinRuleExt(); } else if (RULE_Random.equals(ruleName)) { - return new RandomRule(); + return new RandomRuleExt(); } else if (RULE_WeightedResponse.equals(ruleName)) { - return new WeightedResponseTimeRule(); + return new WeightedResponseTimeRuleExt(); } else if (RULE_SessionStickiness.equals(ruleName)) { return new SessionStickinessRule(); } else { diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java index 7695a68..9dba004 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java @@ -21,27 +21,23 @@ import java.util.List; import org.apache.servicecomb.core.Invocation; -import com.netflix.loadbalancer.Server; - /** * Base interface for server list filters. * - * LoadBalancer.getAllServers ServerListFilterExt.getFilteredListOfServers IRule.choose - * * Robin ServerListFilter can not support invocation based filter strategies, so we create a new one to * support this. */ public interface ServerListFilterExt { - public default int getOrder() { + default int getOrder() { return 0; } - public default boolean enabled() { + default boolean enabled() { return true; } - public default void setLoadBalancer(LoadBalancer loadBalancer) { + default void setLoadBalancer(LoadBalancer loadBalancer) { } - public List<Server> getFilteredListOfServers(List<Server> servers, Invocation invocation); + List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> servers, Invocation invocation); } 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 index 1b7be1d..ac01152 100644 --- 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 @@ -57,6 +57,8 @@ public class ServiceCombLoadBalancerStats { public static final ServiceCombLoadBalancerStats INSTANCE; + private Timer timer; + static { INSTANCE = new ServiceCombLoadBalancerStats(); INSTANCE.init(); @@ -76,17 +78,17 @@ public class ServiceCombLoadBalancerStats { } } - public void markSuccess(ServiceCombServer server) { + public void markSuccess(ServiceCombServer server, long execTime) { try { - serverStatsCache.get(server).markSuccess(); + serverStatsCache.get(server).markSuccess(execTime); } catch (ExecutionException e) { LOGGER.error("Not expected to happen, maybe a bug.", e); } } - public void markFailure(ServiceCombServer server) { + public void markFailure(ServiceCombServer server, long execTime) { try { - serverStatsCache.get(server).markFailure(); + serverStatsCache.get(server).markFailure(execTime); } catch (ExecutionException e) { LOGGER.error("Not expected to happen, maybe a bug.", e); } @@ -126,6 +128,14 @@ public class ServiceCombLoadBalancerStats { } void init() { + // for testing + if (timer != null) { + timer.cancel(); + } + if (serverStatsCache != null) { + serverStatsCache.cleanUp(); + } + serverStatsCache = CacheBuilder.newBuilder() .expireAfterAccess(serverExpireInSeconds, TimeUnit.SECONDS) @@ -145,7 +155,7 @@ public class ServiceCombLoadBalancerStats { } }); - Timer timer = new Timer("LoadBalancerStatsTimer", true); + timer = new Timer("LoadBalancerStatsTimer", true); timer.schedule(new TimerTask() { private MicroserviceInstancePing ping = SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class); @@ -157,10 +167,11 @@ public class ServiceCombLoadBalancerStats { while (instances.hasNext()) { ServiceCombServer server = instances.next(); ServiceCombServerStats stats = allServers.get(server); + long startTime = System.currentTimeMillis(); if ((System.currentTimeMillis() - stats.getLastVisitTime() > timerIntervalInMilis) && !ping .ping(server.getInstance())) { LOGGER.info("ping mark server {} failure.", server.getInstance().getInstanceId()); - stats.markFailure(); + stats.markFailure(System.currentTimeMillis() - startTime); } } serverStatsCache.cleanUp(); diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java index 1d4edf3..800e2ae 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java @@ -22,6 +22,7 @@ import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; import org.apache.servicecomb.serviceregistry.cache.CacheEndpoint; +import com.google.common.annotations.VisibleForTesting; import com.netflix.loadbalancer.Server; /** @@ -35,6 +36,21 @@ public class ServiceCombServer extends Server { // 所属服务实例 private final MicroserviceInstance instance; + @VisibleForTesting + ServiceCombServer(Endpoint endpoint, MicroserviceInstance instance) { + super(null); + this.endpoint = endpoint; + this.instance = instance; + + // Different types of Robin Component Rule have different usages for server status and list. + // e.g. RoundRobinRule using getAllServers & alive & readyToServe + // RandomRule using getReachableServers & alive + // WeightedResponseTimeRule using getAllServers & alive + // To make all rules work only on "how to choose a server from alive servers", we do not rely on Robbin defined status + this.setAlive(true); + this.setReadyToServe(true); + } + public ServiceCombServer(Transport transport, CacheEndpoint cacheEndpoint) { super(null); 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 index b33771b..03b458e 100644 --- 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 @@ -45,33 +45,47 @@ public class ServiceCombServerStats { private boolean isolated = false; + private long averageResponseTime = 0; + + public long getAverageResponseTime() { + return averageResponseTime; + } + public void markIsolated(boolean isolated) { this.isolated = isolated; } - public void markSuccess() { + public void markSuccess(long execTime) { long time = System.currentTimeMillis(); ensureWindow(time); lastVisitTime = time; lastActiveTime = time; + updateAvgTime(execTime); totalRequests.incrementAndGet(); successRequests.incrementAndGet(); continuousFailureCount.set(0); } - public void markFailure() { + public void markFailure(long execTime) { long time = System.currentTimeMillis(); ensureWindow(time); lastVisitTime = time; // when isolated, do not update any failure statistics, or we can not recover from failure very quickly if (!isolated) { + updateAvgTime(execTime); totalRequests.incrementAndGet(); failedRequests.incrementAndGet(); continuousFailureCount.incrementAndGet(); } } + private void updateAvgTime(long execTime) { + // There maybe concurrent problems. But we do not care. + long total = totalRequests.get(); + averageResponseTime = (averageResponseTime * total + execTime) / (total + 1); + } + private void ensureWindow(long time) { if (time - lastWindow > TIME_WINDOW_IN_MILLISECONDS) { synchronized (lock) { @@ -81,6 +95,7 @@ public class ServiceCombServerStats { totalRequests.set(0); successRequests.set(0); failedRequests.set(0); + averageResponseTime = 0; } lastWindow = time; } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java index d589b4d..a489860 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java @@ -17,15 +17,13 @@ package org.apache.servicecomb.loadbalance; +import java.util.List; + +import org.apache.servicecomb.core.Invocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.loadbalancer.AbstractLoadBalancer; -import com.netflix.loadbalancer.ILoadBalancer; -import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.LoadBalancerStats; -import com.netflix.loadbalancer.RoundRobinRule; -import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerStats; /** @@ -33,17 +31,17 @@ import com.netflix.loadbalancer.ServerStats; * 提供当会话过期或者失败次数超过限制后,轮询选择其他服务器的能力。 * */ -public class SessionStickinessRule implements IRule { +public class SessionStickinessRule implements RuleExt { private static final Logger LOG = LoggerFactory.getLogger(SessionStickinessRule.class); private final Object lock = new Object(); - private ILoadBalancer lb; + private LoadBalancer loadBalancer; // use random rule as the trigger rule, to prevent consumer instance select the same producer instance. - private IRule triggerRule; + private RuleExt triggerRule; - private volatile Server lastServer = null; + private volatile ServiceCombServer lastServer = null; private long lastAccessedTime = 0; @@ -54,39 +52,41 @@ public class SessionStickinessRule implements IRule { private String microserviceName; public SessionStickinessRule() { - triggerRule = new RoundRobinRule(); + triggerRule = new RoundRobinRuleExt(); + } + + public void setLoadBalancer(LoadBalancer loadBalancer) { + this.loadBalancer = loadBalancer; } - private Server chooseNextServer(Object key) { - AbstractLoadBalancer lb = (AbstractLoadBalancer) getLoadBalancer(); - triggerRule.setLoadBalancer(lb); - lastServer = triggerRule.choose(key); + private ServiceCombServer chooseNextServer(List<ServiceCombServer> servers, Invocation invocation) { + lastServer = triggerRule.choose(servers, invocation); lastAccessedTime = System.currentTimeMillis(); return lastServer; } - private Server chooseInitialServer(Object key) { + private ServiceCombServer chooseInitialServer(List<ServiceCombServer> servers, Invocation invocation) { synchronized (lock) { if (lastServer == null) { - chooseNextServer(key); + chooseNextServer(servers, invocation); } } return lastServer; } - private Server chooseServerWhenTimeout(Object key) { + private ServiceCombServer chooseServerWhenTimeout(List<ServiceCombServer> servers, Invocation invocation) { synchronized (lock) { if (isTimeOut()) { - chooseNextServer(key); + chooseNextServer(servers, invocation); } } return lastServer; } - private Server chooseServerErrorThresholdMet(Object key) { + private ServiceCombServer chooseServerErrorThresholdMet(List<ServiceCombServer> servers, Invocation invocation) { synchronized (lock) { if (errorThresholdMet) { - chooseNextServer(key); + chooseNextServer(servers, invocation); errorThresholdMet = false; } } @@ -101,8 +101,7 @@ public class SessionStickinessRule implements IRule { } private boolean isErrorThresholdMet() { - AbstractLoadBalancer lb = (AbstractLoadBalancer) getLoadBalancer(); - LoadBalancerStats stats = lb.getLoadBalancerStats(); + LoadBalancerStats stats = loadBalancer.getLoadBalancerStats(); if (stats != null && stats.getServerStats() != null && stats.getServerStats().size() > 0) { ServerStats serverStats = stats.getSingleServerStat(lastServer); @@ -117,14 +116,14 @@ public class SessionStickinessRule implements IRule { } @Override - public Server choose(Object key) { + public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation invocation) { if (lastServer == null) { - return chooseInitialServer(key); + return chooseInitialServer(servers, invocation); } if (isTimeOut()) { LOG.warn("session timeout. choose another server."); - return chooseServerWhenTimeout(key); + return chooseServerWhenTimeout(servers, invocation); } else { this.lastAccessedTime = System.currentTimeMillis(); } @@ -132,28 +131,13 @@ public class SessionStickinessRule implements IRule { if (isErrorThresholdMet()) { LOG.warn("reached max error. choose another server."); errorThresholdMet = true; - return chooseServerErrorThresholdMet(key); + return chooseServerErrorThresholdMet(servers, invocation); } - if (!isLastServerExists(lastServer)) { - return chooseNextServer(key); + if (!servers.contains(lastServer)) { + return chooseNextServer(servers, invocation); } return lastServer; } - - private boolean isLastServerExists(Server lastServer2) { - return this.lb.getReachableServers().contains(lastServer2); - } - - @Override - public void setLoadBalancer(ILoadBalancer lb) { - this.lb = lb; - this.microserviceName = ((LoadBalancer) lb).getMicroServiceName(); - } - - @Override - public ILoadBalancer getLoadBalancer() { - return this.lb; - } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java new file mode 100644 index 0000000..06aba4f --- /dev/null +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java @@ -0,0 +1,65 @@ +/* + * 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.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.servicecomb.core.Invocation; + +/** + * Rule based on response time. + */ +public class WeightedResponseTimeRuleExt extends RoundRobinRuleExt { + // 10ms + private static final int MIN_GAP = 10; + + private Random random = new Random(); + + @Override + public ServiceCombServer choose(List<ServiceCombServer> servers, Invocation invocation) { + List<AtomicInteger> stats = new ArrayList<>(servers.size()); + int totalWeights = 0; + boolean needRandom = false; + for (ServiceCombServer server : servers) { + ServiceCombServerStats serverStats = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server); + int avgTime = (int) serverStats.getAverageResponseTime(); + if (!needRandom && avgTime > MIN_GAP) { + needRandom = true; + } + totalWeights += avgTime; + stats.add(new AtomicInteger(avgTime)); + } + + if (needRandom) { + int finalTotal = totalWeights; + stats.forEach(item -> item.set(finalTotal - item.get())); + int ran = random + .nextInt(Math.max(totalWeights * stats.size() - totalWeights, 1)); + for (int i = 0; i < stats.size(); i++) { + ran -= stats.get(i).get(); + if (ran < 0) { + return servers.get(i); + } + } + } + return super.choose(servers, invocation); + } +} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java index ed08789..6f93b44 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/MyServerListFilterExt.java @@ -30,7 +30,7 @@ import com.netflix.loadbalancer.Server; */ public class MyServerListFilterExt implements ServerListFilterExt { @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { + public List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> serverList, Invocation invocation) { if (invocation.getAppId().equals("test")) { return new ArrayList<>(); } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java index 08d498d..6ef2160 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java @@ -35,7 +35,6 @@ public class TestConfiguration { public void testConstants() { assertEquals("servicecomb.loadbalance.", Configuration.PROP_ROOT); - assertEquals("NFLoadBalancerRuleClassName", Configuration.PROP_POLICY); assertEquals("ribbon.", Configuration.PROP_ROOT_20); assertEquals("retryEnabled", Configuration.PROP_RETRY_ENABLED); assertEquals("retryOnNext", Configuration.PROP_RETRY_ONNEXT); @@ -47,7 +46,6 @@ public class TestConfiguration { @Test public void testFullConfigurationWithArgsString() { - assertNull(Configuration.INSTANCE.getPolicy("test")); assertNotNull(Configuration.INSTANCE.getRetryOnNext("test")); assertNotNull(Configuration.INSTANCE.getRetryOnSame("test")); assertNotNull(Configuration.INSTANCE.isRetryEnabled("test")); diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java index 69c4a1e..169e91a 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java @@ -60,17 +60,16 @@ public class TestExtensionsManager { BeansHolder holder = new BeansHolder(); List<ExtensionsFactory> extensionsFactories = new ArrayList<>(); - extensionsFactories.add(new RuleClassNameExtentionsFactory()); extensionsFactories.add(new RuleNameExtentionsFactory()); extensionsFactories.add(new DefaultRetryExtensionsFactory()); Deencapsulation.setField(holder, "extentionsFactories", extensionsFactories); holder.init(); - Assert.assertEquals(RoundRobinRule.class.getName(), + Assert.assertEquals(RoundRobinRuleExt.class.getName(), ExtensionsManager.createLoadBalancerRule("mytest1").getClass().getName()); - Assert.assertEquals(RandomRule.class.getName(), + Assert.assertEquals(RandomRuleExt.class.getName(), ExtensionsManager.createLoadBalancerRule("mytest2").getClass().getName()); - Assert.assertEquals(WeightedResponseTimeRule.class.getName(), + Assert.assertEquals(WeightedResponseTimeRuleExt.class.getName(), ExtensionsManager.createLoadBalancerRule("mytest3").getClass().getName()); Assert.assertEquals(SessionStickinessRule.class.getName(), ExtensionsManager.createLoadBalancerRule("mytest4").getClass().getName()); @@ -84,36 +83,12 @@ public class TestExtensionsManager { @Test public void testRuleClassName() { - System.setProperty("servicecomb.loadbalance.mytest1.NFLoadBalancerRuleClassName", - "com.netflix.loadbalancer.RoundRobinRule"); - System.setProperty("servicecomb.loadbalance.mytest2.NFLoadBalancerRuleClassName", - "com.netflix.loadbalancer.WeightedResponseTimeRule"); - System.setProperty("servicecomb.loadbalance.mytest3.NFLoadBalancerRuleClassName", "com.netflix.loadbalancer.RandomRule"); - System.setProperty("servicecomb.loadbalance.mytest4.NFLoadBalancerRuleClassName", - "org.apache.servicecomb.loadbalance.SessionStickinessRule"); - BeansHolder holder = new BeansHolder(); List<ExtensionsFactory> extensionsFactories = new ArrayList<>(); - extensionsFactories.add(new RuleClassNameExtentionsFactory()); extensionsFactories.add(new RuleNameExtentionsFactory()); extensionsFactories.add(new DefaultRetryExtensionsFactory()); Deencapsulation.setField(holder, "extentionsFactories", extensionsFactories); holder.init(); - - Assert.assertEquals(RoundRobinRule.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest1").getClass().getName()); - Assert.assertEquals(WeightedResponseTimeRule.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest2").getClass().getName()); - Assert.assertEquals(RandomRule.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest3").getClass().getName()); - Assert.assertEquals(SessionStickinessRule.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest4").getClass().getName()); - - System.getProperties().remove("servicecomb.loadbalance.mytest1.NFLoadBalancerRuleClassName"); - System.getProperties().remove("servicecomb.loadbalance.mytest2.NFLoadBalancerRuleClassName"); - System.getProperties().remove("servicecomb.loadbalance.mytest3.NFLoadBalancerRuleClassName"); - System.getProperties().remove("servicecomb.loadbalance.mytest4.NFLoadBalancerRuleClassName"); - RetryHandler retryHandler = ExtensionsManager.createRetryHandler("mytest1"); Assert.assertTrue(DefaultLoadBalancerRetryHandler.class.isInstance(retryHandler)); Assert.assertFalse(retryHandler.isRetriableException(new InvocationException(400, "", ""), false)); diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java index f088e71..4c5373a 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java @@ -20,15 +20,15 @@ package org.apache.servicecomb.loadbalance; import java.util.ArrayList; import java.util.List; +import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; import org.junit.Assert; import org.junit.Test; -import com.netflix.loadbalancer.RandomRule; -import com.netflix.loadbalancer.RoundRobinRule; import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.WeightedResponseTimeRule; import mockit.Deencapsulation; import mockit.Expectations; @@ -37,14 +37,21 @@ import mockit.Mocked; public class TestLoadBalanceCreator { @Test - public void testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable Invocation invocation) { + public void testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable Invocation invocation, + @Injectable Transport transport) { // Robin components implementations require getReachableServers & getServerList have the same size, we add a test case for this. - RoundRobinRule rule = new RoundRobinRule(); - List<Server> servers = new ArrayList<>(); - Server server = new Server("host1", 80); - server.setAlive(true); - Server server2 = new Server("host2", 80); - server2.setAlive(true); + RoundRobinRuleExt rule = new RoundRobinRuleExt(); + List<ServiceCombServer> servers = new ArrayList<>(); + Endpoint host1 = new Endpoint(transport, "host1"); + MicroserviceInstance instance1 = new MicroserviceInstance(); + instance1.setInstanceId("instance1"); + ServiceCombServer server = new ServiceCombServer(host1, instance1); + + Endpoint host2 = new Endpoint(transport, "host2"); + MicroserviceInstance instance2 = new MicroserviceInstance(); + instance2.setInstanceId("instance2"); + ServiceCombServer server2 = new ServiceCombServer(host2, instance2); + servers.add(server); servers.add(server2); LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "test"); @@ -53,9 +60,10 @@ public class TestLoadBalanceCreator { filters.add(new ServerListFilterExt() { @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { - List<Server> filteredServers = new ArrayList<>(); - for (Server server : servers) { + public List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> serverList, + Invocation invocation) { + List<ServiceCombServer> filteredServers = new ArrayList<>(); + for (ServiceCombServer server : servers) { if (server.getHost().equals("host1")) { continue; } @@ -66,35 +74,43 @@ public class TestLoadBalanceCreator { }); lbCreator.setFilters(filters); - LoadBalancer lb = lbCreator.createLoadBalancer(invocation); - Server s = lb.chooseServer("test"); + LoadBalancer lb = lbCreator.createLoadBalancer(servers); + Server s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); + s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); + s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); } @Test - public void testLoadBalanceWithRandomRuleAndFilter(@Injectable Invocation invocation) { + public void testLoadBalanceWithRandomRuleAndFilter(@Injectable Invocation invocation, + @Injectable Transport transport) { // Robin components implementations require getReachableServers & getServerList have the same size, we add a test case for this. - RandomRule rule = new RandomRule(); + RandomRuleExt rule = new RandomRuleExt(); LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "service"); - List<Server> servers = new ArrayList<>(); - Server server = new Server("host1", 80); - server.setAlive(true); - Server server2 = new Server("host2", 80); - server2.setAlive(true); + List<ServiceCombServer> servers = new ArrayList<>(); + Endpoint host1 = new Endpoint(transport, "host1"); + MicroserviceInstance instance1 = new MicroserviceInstance(); + instance1.setInstanceId("instance1"); + ServiceCombServer server = new ServiceCombServer(host1, instance1); + + Endpoint host2 = new Endpoint(transport, "host2"); + MicroserviceInstance instance2 = new MicroserviceInstance(); + instance2.setInstanceId("instance2"); + ServiceCombServer server2 = new ServiceCombServer(host2, instance2); + servers.add(server); servers.add(server2); - lbCreator.setServerList(servers); + List<ServerListFilterExt> filters = new ArrayList<>(); filters.add(new ServerListFilterExt() { @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { - List<Server> filteredServers = new ArrayList<>(); - for (Server server : servers) { + public List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> serverList, + Invocation invocation) { + List<ServiceCombServer> filteredServers = new ArrayList<>(); + for (ServiceCombServer server : servers) { if (server.getHost().equals("host1")) { continue; } @@ -104,46 +120,48 @@ public class TestLoadBalanceCreator { } }); lbCreator.setFilters(filters); - LoadBalancer lb = lbCreator.createLoadBalancer(invocation); - Server s = lb.chooseServer("test"); + LoadBalancer lb = lbCreator.createLoadBalancer(servers); + Server s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); + s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); + s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); } @Test - public void testLoadBalanceWithWeightedResponseTimeRuleAndFilter(@Mocked ServiceCombServer server, - @Mocked ServiceCombServer server2, @Injectable Invocation invocation) { + public void testLoadBalanceWithWeightedResponseTimeRuleAndFilter(@Injectable Endpoint endpoint1, @Injectable Endpoint endpoint2, @Injectable Invocation invocation) { // Robin components implementations require getReachableServers & getServerList have the same size, we add a test case for this. - WeightedResponseTimeRule rule = new WeightedResponseTimeRule(); + WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt(); LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "service"); - List<Server> servers = new ArrayList<>(); + + + List<ServiceCombServer> servers = new ArrayList<>(); + MicroserviceInstance instance1 = new MicroserviceInstance(); + instance1.setInstanceId("ii01"); + MicroserviceInstance instance2 = new MicroserviceInstance(); + instance2.setInstanceId("ii02"); + ServiceCombServer server = new ServiceCombServer(endpoint1, instance1); + ServiceCombServer server2 = new ServiceCombServer(endpoint2, instance2); new Expectations() { { - server.getHost(); + endpoint1.getEndpoint(); result = "host1"; - - server2.isReadyToServe(); - result = true; - server2.isAlive(); - result = true; - server2.getHost(); + endpoint2.getEndpoint(); result = "host2"; } }; servers.add(server); servers.add(server2); - lbCreator.setServerList(servers); List<ServerListFilterExt> filters = new ArrayList<>(); filters.add(new ServerListFilterExt() { @Override - public List<Server> getFilteredListOfServers(List<Server> serverList, Invocation invocation) { - List<Server> filteredServers = new ArrayList<>(); - for (Server server : servers) { + public List<ServiceCombServer> getFilteredListOfServers(List<ServiceCombServer> serverList, + Invocation invocation) { + List<ServiceCombServer> filteredServers = new ArrayList<>(); + for (ServiceCombServer server : servers) { if (server.getHost().equals("host1")) { continue; } @@ -153,40 +171,47 @@ public class TestLoadBalanceCreator { } }); lbCreator.setFilters(filters); - LoadBalancer lb = lbCreator.createLoadBalancer(invocation); - Server s = lb.chooseServer("test"); + LoadBalancer lb = lbCreator.createLoadBalancer(servers); + Server s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); + s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); + s = lb.chooseServer(invocation); Assert.assertEquals(server2, s); } @Test - public void testLoadBalanceWithSessionSticknessRule(@Injectable Invocation invocation) { + public void testLoadBalanceWithSessionSticknessRule(@Injectable Invocation invocation, + @Injectable Transport transport) { SessionStickinessRule rule = new SessionStickinessRule(); LoadBalancerCreator lbCreator = new LoadBalancerCreator(rule, "service"); - List<Server> servers = new ArrayList<>(); - Server server = new Server("host1", 80); - server.setAlive(true); - Server server2 = new Server("host2", 80); - server2.setAlive(true); + List<ServiceCombServer> servers = new ArrayList<>(); + Endpoint host1 = new Endpoint(transport, "host1"); + MicroserviceInstance instance1 = new MicroserviceInstance(); + ServiceCombServer server = new ServiceCombServer(host1, instance1); + instance1.setInstanceId("instance1"); + + Endpoint host2 = new Endpoint(transport, "host2"); + MicroserviceInstance instance2 = new MicroserviceInstance(); + ServiceCombServer server2 = new ServiceCombServer(host2, instance2); + instance2.setInstanceId("instance2"); + servers.add(server); servers.add(server2); - lbCreator.setServerList(servers); + lbCreator.setFilters(new ArrayList<>()); - LoadBalancer lb = lbCreator.createLoadBalancer(invocation); - Server s = lb.chooseServer("test"); - Assert.assertEquals(server2, s); - s = lb.chooseServer("test"); - Assert.assertEquals(server2, s); + LoadBalancer lb = lbCreator.createLoadBalancer(servers); + Server s = lb.chooseServer(invocation); + Assert.assertEquals(server, s); + s = lb.chooseServer(invocation); + Assert.assertEquals(server, s); long time = Deencapsulation.getField(rule, "lastAccessedTime"); Deencapsulation.setField(rule, "lastAccessedTime", time - 1000 * 300); ArchaiusUtils.setProperty("cse.loadbalance.service.SessionStickinessRule.sessionTimeoutInSeconds", 9); - s = lb.chooseServer("test"); - Assert.assertEquals(server, s); + s = lb.chooseServer(invocation); + Assert.assertEquals(server2, s); ArchaiusUtils.setProperty("cse.loadbalance.service.SessionStickinessRule.successiveFailedTimes", 5); lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); @@ -194,7 +219,7 @@ public class TestLoadBalanceCreator { lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - s = lb.chooseServer("test"); - Assert.assertEquals(server2, s); + s = lb.chooseServer(invocation); + Assert.assertEquals(server, s); } } 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 b5262b5..906529f 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 @@ -35,6 +35,7 @@ import org.apache.servicecomb.serviceregistry.cache.InstanceCacheManager; import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTreeNode; import org.junit.After; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mockito; @@ -43,6 +44,11 @@ import org.mockito.Mockito; * */ public class TestLoadBalanceHandler2 { + @BeforeClass + public static void beforeClass() { + // avoid mock + ServiceCombLoadBalancerStats.INSTANCE.init(); + } @After public void teardown() { @@ -122,54 +128,54 @@ public class TestLoadBalanceHandler2 { handler = new LoadbalanceHandler(); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server, null); data.put("noneMatchInstance", noneMatchInstance); parent.cacheVersion(1); handler = new LoadbalanceHandler(); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9092"); data.put("regionMatchInstance", regionMatchInstance); parent.cacheVersion(parent.cacheVersion() + 1); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9091"); data.put("allmatchInstance", allmatchInstance); parent.cacheVersion(parent.cacheVersion() + 1); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9090"); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server, 0); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server, 0); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server, 0); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server, 0); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(server, 0); //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9090"); //if errorThresholdPercentage greater than 0, it will activate. ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); ServiceCombServer server2 = server; loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9091"); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2, 0); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9090"); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2, 0); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2, 0); loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = (ServiceCombServer) loadBalancer.chooseServer(); + server = (ServiceCombServer) loadBalancer.chooseServer(invocation); Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:9091"); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java index a61fa4f..7b26368 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java @@ -17,117 +17,31 @@ package org.apache.servicecomb.loadbalance; -import static org.junit.Assert.assertNotNull; - import java.util.ArrayList; import java.util.List; +import org.apache.servicecomb.core.Invocation; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; -import com.netflix.loadbalancer.AbstractLoadBalancer.ServerGroup; -import com.netflix.loadbalancer.IRule; -import com.netflix.loadbalancer.Server; - public class TestLoadBalancer { - private IRule rule = Mockito.mock(IRule.class); + private RuleExt rule = Mockito.mock(RuleExt.class); - @SuppressWarnings("deprecation") @Test public void testLoadBalancerFullOperationWithoutException() { - List<Server> newServers = new ArrayList<>(); - Server server = Mockito.mock(Server.class); + List<ServiceCombServer> newServers = new ArrayList<>(); + ServiceCombServer server = Mockito.mock(ServiceCombServer.class); + Invocation invocation = Mockito.mock(Invocation.class); newServers.add(server); - LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null); - loadBalancer.setServerList(newServers); - loadBalancer.chooseServer(); - - Object key = Mockito.mock(Object.class); + List<ServerListFilterExt> filterExts = new ArrayList<>(); + LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null, filterExts, newServers); + loadBalancer.chooseServer(invocation); - loadBalancer.chooseServer(key); - loadBalancer.getAllServers(); - loadBalancer.getServerList(true); - loadBalancer.getServerList(false); - loadBalancer.getLoadBalancerStats(); - loadBalancer.getReachableServers(); - - assertNotNull(loadBalancer.getAllServers()); - } - - @Test - public void testAddServerException() { - boolean status = true; - List<Server> newServers = new ArrayList<>(); - Server server = Mockito.mock(Server.class); - - newServers.add(server); - LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null); - loadBalancer.setServerList(newServers); - try { + Mockito.when(rule.choose(newServers, invocation)).thenReturn(server); - loadBalancer.addServers(newServers); - } catch (Exception e) { - - status = false; - - Assert.assertEquals("Not implemented.", e.getMessage()); - } - - Assert.assertFalse(status); - } - - @Test - public void testServerListException() { - boolean status = true; - List<Server> newServers = new ArrayList<>(); - Server server = Mockito.mock(Server.class); - - newServers.add(server); - LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null); - loadBalancer.setServerList(newServers); - try { - - loadBalancer.getServerList(ServerGroup.ALL); - } catch (Exception e) { - - status = false; - - Assert.assertEquals("Not implemented.", e.getMessage()); - } - - Assert.assertFalse(status); - } - - @Test - public void testMarkServerDownException() { - boolean status = true; - List<Server> newServers = new ArrayList<>(); - Server server = Mockito.mock(Server.class); - - newServers.add(server); - LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null); - loadBalancer.setServerList(newServers); - try { - - loadBalancer.markServerDown(server); - } catch (Exception e) { - - status = false; - - Assert.assertEquals("Not implemented.", e.getMessage()); - } - - Assert.assertFalse(status); - } - - @Test - public void testGetAllServers() { - List<Server> servers = new ArrayList<>(); - Server server = Mockito.mock(Server.class); - servers.add(server); - LoadBalancer loadBalancer = new LoadBalancer(rule, "test", null); - loadBalancer.setServerList(servers); - Assert.assertEquals(servers, loadBalancer.getAllServers()); + Assert.assertEquals(server, loadBalancer.chooseServer(invocation)); + Assert.assertEquals(null, loadBalancer.getLoadBalancerStats()); + Assert.assertEquals("test", loadBalancer.getMicroServiceName()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java index faa86f9..468e482 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java @@ -137,7 +137,6 @@ public class TestLoadbalanceHandler { BeansHolder holder = new BeansHolder(); List<ExtensionsFactory> extensionsFactories = new ArrayList<>(); - extensionsFactories.add(new RuleClassNameExtentionsFactory()); extensionsFactories.add(new RuleNameExtentionsFactory()); extensionsFactories.add(new DefaultRetryExtensionsFactory()); Deencapsulation.setField(holder, "extentionsFactories", extensionsFactories); @@ -179,7 +178,7 @@ public class TestLoadbalanceHandler { LoadBalancer lb = handler.getOrCreateLoadBalancer(invocation); - Assert.assertEquals("[rest://localhost:8080]", Deencapsulation.getField(lb, "serverList").toString()); + Assert.assertEquals("[rest://localhost:8080]", Deencapsulation.getField(lb, "servers").toString()); } @Test 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 index 11dfe77..23352c8 100644 --- 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 @@ -39,7 +39,7 @@ public class TestServiceCombLoadBalancerStats { @BeforeClass public static void beforeClass() { // avoid mock - ServiceCombLoadBalancerStats.INSTANCE.getClass(); + ServiceCombLoadBalancerStats.INSTANCE.init(); } @Test @@ -64,7 +64,7 @@ public class TestServiceCombLoadBalancerStats { ServiceCombServer serviceCombServer = new ServiceCombServer(transport, new CacheEndpoint("rest://localhost:8080", instance)); - serviceCombLoadBalancerStats.markSuccess(serviceCombServer); + serviceCombLoadBalancerStats.markSuccess(serviceCombServer, 0); ServiceCombServerStats stats = serviceCombLoadBalancerStats.getServiceCombServerStats(serviceCombServer); Assert.assertEquals(serviceCombLoadBalancerStats.getPingView().size(), 1); await().atMost(5, TimeUnit.SECONDS) @@ -83,16 +83,16 @@ public class TestServiceCombLoadBalancerStats { instance.setInstanceId("instance1"); ServiceCombServer serviceCombServer = new ServiceCombServer(transport, new CacheEndpoint("rest://localhost:8080", instance)); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer, 0); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer, 0); Assert.assertEquals( ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getCountinuousFailureCount(), 2); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer, 0); Assert.assertEquals( ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getCountinuousFailureCount(), 0); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer, 0); Assert .assertEquals( ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getTotalRequests(), 4); @@ -119,10 +119,10 @@ public class TestServiceCombLoadBalancerStats { for (int i = 0; i < 10; i++) { new Thread() { public void run() { - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer, 0); + ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer, 0); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer, 0); + ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer, 0); latch.countDown(); } }.start(); 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 index 3010368..3fda339 100644 --- 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 @@ -31,12 +31,12 @@ public class TestServiceCombServerStats { public void testSimpleThread() { long time = System.currentTimeMillis(); ServiceCombServerStats stats = new ServiceCombServerStats(); - stats.markFailure(); - stats.markFailure(); + stats.markFailure(0); + stats.markFailure(0); Assert.assertEquals(stats.getCountinuousFailureCount(), 2); - stats.markSuccess(); + stats.markSuccess(0); Assert.assertEquals(stats.getCountinuousFailureCount(), 0); - stats.markSuccess(); + stats.markSuccess(0); Assert.assertEquals(stats.getTotalRequests(), 4); Assert.assertEquals(stats.getFailedRate(), 50); Assert.assertEquals(stats.getSuccessRate(), 50); @@ -52,10 +52,10 @@ public class TestServiceCombServerStats { for (int i = 0; i < 10; i++) { new Thread() { public void run() { - stats.markFailure(); - stats.markFailure(); - stats.markSuccess(); - stats.markSuccess(); + stats.markFailure(0); + stats.markFailure(0); + stats.markSuccess(0); + stats.markSuccess(0); latch.countDown(); } }.start(); @@ -78,8 +78,8 @@ public class TestServiceCombServerStats { }; ServiceCombServerStats stats = new ServiceCombServerStats(); Assert.assertEquals(stats.getLastVisitTime(), 1000); - stats.markSuccess(); - stats.markFailure(); + stats.markSuccess(0); + stats.markFailure(0); Assert.assertEquals(stats.getTotalRequests(), 2); Assert.assertEquals(stats.getFailedRate(), 50); Assert.assertEquals(stats.getSuccessRate(), 50); @@ -89,7 +89,7 @@ public class TestServiceCombServerStats { return 60000 + 2000; } }; - stats.markSuccess(); + stats.markSuccess(0); Assert.assertEquals(stats.getTotalRequests(), 1); Assert.assertEquals(stats.getFailedRate(), 0); Assert.assertEquals(stats.getSuccessRate(), 100); diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java index 6ebead2..dd2319e 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java @@ -20,9 +20,11 @@ package org.apache.servicecomb.loadbalance; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance; import org.apache.servicecomb.serviceregistry.cache.CacheEndpoint; @@ -49,22 +51,20 @@ public class TestSessionSticknessRule { instance1.setInstanceId("1234"); ServiceCombServer mockedServer = new ServiceCombServer(transport, new CacheEndpoint("rest:127.0.0.1:8889", instance1)); - Object key = Mockito.mock(Object.class); + Invocation invocation = mock(Invocation.class); LoadBalancerStats stats = mock(LoadBalancerStats.class); Mockito.when(mockedLb.getLoadBalancerStats()).thenReturn(stats); - Deencapsulation.invoke(rule, "chooseServerWhenTimeout", key); + Deencapsulation.invoke(rule, "chooseServerWhenTimeout", Arrays.asList(mockedServer), invocation); mockedServer.setAlive(true); mockedServer.setReadyToServe(true); - List<Server> allServers = Arrays.asList(mockedServer); - when(mockedLb.getReachableServers()).thenReturn(allServers); - when(mockedLb.getAllServers()).thenReturn(allServers); - + List<ServiceCombServer> allServers = Arrays.asList(mockedServer); rule.setLoadBalancer(mockedLb); - Assert.assertEquals(rule.getLoadBalancer(), mockedLb); - Server s = rule.choose("default"); + + + Server s = rule.choose(allServers, invocation); Assert.assertEquals(s, mockedServer); - s = rule.choose("default"); + s = rule.choose(allServers, invocation); Assert.assertEquals(s, mockedServer); } @@ -77,9 +77,12 @@ public class TestSessionSticknessRule { Object key = new Object(); - Server s = new Server("test"); + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List<ServiceCombServer> servers = new ArrayList<>(); + servers.add(server); - Deencapsulation.setField(ss, "lastServer", s); + Deencapsulation.setField(ss, "lastServer", server); new MockUp<SessionStickinessRule>() { @@ -98,7 +101,7 @@ public class TestSessionSticknessRule { }; try { - ss.choose(key); + ss.choose(servers, invocation); } catch (Exception e) { status = false; } @@ -112,11 +115,12 @@ public class TestSessionSticknessRule { SessionStickinessRule ss = new SessionStickinessRule(); - Object key = new Object(); - - Server s = new Server("test"); + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List<ServiceCombServer> servers = new ArrayList<>(); + servers.add(server); - Deencapsulation.setField(ss, "lastServer", s); + Deencapsulation.setField(ss, "lastServer", server); new MockUp<SessionStickinessRule>() { @@ -127,7 +131,7 @@ public class TestSessionSticknessRule { }; try { - ss.choose(key); + ss.choose(servers, invocation); } catch (Exception e) { status = false; } @@ -144,9 +148,12 @@ public class TestSessionSticknessRule { Object key = new Object(); - Server s = new Server("test"); + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List<ServiceCombServer> servers = new ArrayList<>(); + servers.add(server); - Deencapsulation.setField(ss, "lastServer", s); + Deencapsulation.setField(ss, "lastServer", server); new MockUp<SessionStickinessRule>() { @@ -157,7 +164,7 @@ public class TestSessionSticknessRule { }; try { - ss.choose(key); + ss.choose(servers, invocation); } catch (Exception e) { status = false; } @@ -173,9 +180,12 @@ public class TestSessionSticknessRule { Object key = new Object(); - Server s = new Server("test"); + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List<ServiceCombServer> servers = new ArrayList<>(); + servers.add(server); - Deencapsulation.setField(ss, "lastServer", s); + Deencapsulation.setField(ss, "lastServer", server); new MockUp<SessionStickinessRule>() { @@ -202,7 +212,7 @@ public class TestSessionSticknessRule { }; try { - ss.choose(key); + ss.choose(servers, invocation); } catch (Exception e) { status = false; } @@ -217,26 +227,14 @@ public class TestSessionSticknessRule { Object key = new Object(); - Server s = new Server("test"); + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List<ServiceCombServer> servers = new ArrayList<>(); + servers.add(server); - Deencapsulation.setField(ss, "lastServer", s); - try { - ss.choose(key); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - } - - @Test - public void testServerWithKey() { - - boolean status = true; - SessionStickinessRule ss = new SessionStickinessRule(); - - Object key = new Object(); + Deencapsulation.setField(ss, "lastServer", server); try { - ss.choose(key); + ss.choose(servers, invocation); } catch (Exception e) { status = false; } @@ -248,6 +246,7 @@ public class TestSessionSticknessRule { SessionStickinessRule rule = new SessionStickinessRule(); Transport transport = mock(Transport.class); + Invocation invocation = mock(Invocation.class); MicroserviceInstance instance1 = new MicroserviceInstance(); instance1.setInstanceId("1234"); ServiceCombServer mockedServer = @@ -255,13 +254,11 @@ public class TestSessionSticknessRule { mockedServer.setAlive(true); mockedServer.setReadyToServe(true); mockedServer.setId("mockedServer"); - List<Server> allServers = Arrays.asList(mockedServer); - LoadBalancer lb = new LoadBalancer(rule, "mockedServer", null); - lb.setServerList(allServers); + List<ServiceCombServer> allServers = Arrays.asList(mockedServer); + LoadBalancer lb = new LoadBalancer(rule, "mockedServer", null, new ArrayList<>(), allServers); rule.setLoadBalancer(lb); - Assert.assertEquals(lb, rule.getLoadBalancer()); - Server server = new Server("test"); + ServiceCombServer server = new ServiceCombServer(transport, new CacheEndpoint("rest:127.0.0.1:8890", instance1)); Deencapsulation.setField(rule, "lastServer", server); new MockUp<SessionStickinessRule>(rule) { @@ -276,7 +273,7 @@ public class TestSessionSticknessRule { } }; Object key = Mockito.mock(Object.class); - Server s = rule.choose(key); + Server s = rule.choose(allServers, invocation); Assert.assertEquals(mockedServer, s); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java index 3a5e8b9..5dbd6a4 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java @@ -72,6 +72,7 @@ public class TestServerDiscoveryFilter { } }; MicroserviceInstance instance = new MicroserviceInstance(); + instance.setInstanceId("0000001"); ServiceCombServer server = (ServiceCombServer) filter.createEndpoint(Const.RESTFUL, "rest://localhost:8080", instance); Assert.assertSame(instance, server.getInstance()); diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java index 5c3caf0..30e812f 100644 --- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java +++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java @@ -21,13 +21,17 @@ import java.lang.reflect.Method; import java.util.List; import java.util.concurrent.CompletableFuture; +import javax.ws.rs.core.Response.Status; + import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.swagger.invocation.AsyncResponse; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; import org.apache.servicecomb.swagger.invocation.arguments.producer.ProducerArgumentsMapper; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension; import org.apache.servicecomb.swagger.invocation.response.producer.ProducerResponseMapper; @@ -159,6 +163,10 @@ public class SwaggerProducerOperation { } Object result = producerMethod.invoke(producerInstance, args); response = responseMapper.mapResponse(invocation.getStatus(), result); + } catch (IllegalArgumentException ae) { + response = processException(invocation, + new InvocationException(Status.BAD_REQUEST.getStatusCode(), "", + new CommonExceptionData(ae.getMessage()), ae)); } catch (Throwable e) { response = processException(invocation, e); }
