You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/12/04 01:16:59 UTC

[servicecomb-java-chassis] branch master updated: [SCB-1061]Provide a way to using handlers(e.g. LoabalanceHanler) outside handler chain

This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 3dd0fd8  [SCB-1061]Provide a way to using handlers(e.g. LoabalanceHanler) outside handler chain
3dd0fd8 is described below

commit 3dd0fd8be98257fa2b0b3ac6445f2f88186482c9
Author: liubao <ba...@huawei.com>
AuthorDate: Mon Dec 3 17:38:33 2018 +0800

    [SCB-1061]Provide a way to using handlers(e.g. LoabalanceHanler) outside handler chain
---
 .../org/apache/servicecomb/core/Invocation.java    |   4 +
 .../servicecomb/core/NonSwaggerInvocation.java     |  77 +++++++++++
 .../loadbalance/LoadbalanceHandler.java            |   8 +-
 .../loadbalance/TestLoadBalanceHandler2.java       | 153 +++++++++++++++++++++
 .../transport/rest/vertx/RestServerVerticle.java   |   8 +-
 5 files changed, 247 insertions(+), 3 deletions(-)

diff --git a/core/src/main/java/org/apache/servicecomb/core/Invocation.java b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
index 32fa68b..46c3c4a 100644
--- a/core/src/main/java/org/apache/servicecomb/core/Invocation.java
+++ b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
@@ -109,6 +109,10 @@ public class Invocation extends SwaggerInvocation {
     return invocationStageTrace.getStartExecution();
   }
 
+  public Invocation() {
+    // An empty invocation, used to mock or some other scenario do not need operation information.
+  }
+
   public Invocation(ReferenceConfig referenceConfig, OperationMeta operationMeta, Object[] swaggerArguments) {
     this.invocationType = InvocationType.CONSUMER;
     this.referenceConfig = referenceConfig;
diff --git a/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java b/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java
new file mode 100644
index 0000000..785c90c
--- /dev/null
+++ b/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java
@@ -0,0 +1,77 @@
+/*
+ * 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.core;
+
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+
+public class NonSwaggerInvocation extends Invocation {
+  private String appId;
+
+  private String microserviceName;
+
+  private String versionRule;
+
+  private Handler nextHandler;
+
+  public NonSwaggerInvocation(String appId, String microserviceName, String versionRule, Handler nextHandler) {
+    this.appId = appId;
+    this.microserviceName = microserviceName;
+    this.versionRule = versionRule;
+    this.nextHandler = nextHandler;
+  }
+
+  @Override
+  public String getSchemaId() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String getOperationName() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String getInvocationQualifiedName() {
+    return microserviceName;
+  }
+
+  @Override
+  public String getConfigTransportName() {
+    return Const.RESTFUL;
+  }
+
+  @Override
+  public String getMicroserviceName() {
+    return microserviceName;
+  }
+
+  @Override
+  public String getAppId() {
+    return appId;
+  }
+
+  @Override
+  public String getMicroserviceVersionRule() {
+    return versionRule;
+  }
+
+  @Override
+  public void next(AsyncResponse asyncResp) throws Exception {
+    nextHandler.handle(this, asyncResp);
+  }
+}
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 8547af5..20d31a4 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
@@ -150,6 +150,9 @@ public class LoadbalanceHandler implements Handler {
 
   private String strategy = null;
 
+  public LoadbalanceHandler(DiscoveryTree discoveryTree) {
+    this.discoveryTree = discoveryTree;
+  }
 
   public LoadbalanceHandler() {
     preCheck();
@@ -317,7 +320,8 @@ public class LoadbalanceHandler implements Handler {
       public void onExecutionFailed(ExecutionContext<Invocation> context, Throwable finalException,
           ExecutionInfo info) {
         LOGGER.error("Invoke all server failed. Operation {}, e={}",
-            context.getRequest().getInvocationQualifiedName(), ExceptionUtils.getExceptionMessageWithoutTrace(finalException));
+            context.getRequest().getInvocationQualifiedName(),
+            ExceptionUtils.getExceptionMessageWithoutTrace(finalException));
         if (orginExecutor != null) {
           orginExecutor.execute(() -> {
             fail(finalException);
@@ -379,7 +383,7 @@ public class LoadbalanceHandler implements Handler {
               }
             });
           } catch (Exception e) {
-            LOGGER.error("execution error, msg is " + e.getMessage());
+            LOGGER.error("execution error, msg is {}", ExceptionUtils.getExceptionMessageWithoutTrace(e));
             f.onError(e);
           }
         });
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 339c522..d98d672 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
@@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.core.CseContext;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.NonSwaggerInvocation;
 import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.core.Transport;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
@@ -35,15 +36,20 @@ import org.apache.servicecomb.core.definition.SchemaMeta;
 import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
 import org.apache.servicecomb.core.transport.TransportManager;
 import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
+import org.apache.servicecomb.loadbalance.filter.IsolationDiscoveryFilter;
+import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter;
+import org.apache.servicecomb.loadbalance.filter.ZoneAwareDiscoveryFilter;
 import org.apache.servicecomb.serviceregistry.RegistryUtils;
 import org.apache.servicecomb.serviceregistry.ServiceRegistry;
 import org.apache.servicecomb.serviceregistry.api.registry.DataCenterInfo;
 import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
 import org.apache.servicecomb.serviceregistry.cache.InstanceCacheManager;
+import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTree;
 import org.apache.servicecomb.serviceregistry.discovery.DiscoveryTreeNode;
 import org.apache.servicecomb.swagger.invocation.AsyncResponse;
 import org.junit.After;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
@@ -58,6 +64,12 @@ public class TestLoadBalanceHandler2 {
     //prepare for defineEndpointAndHandle
     ArchaiusUtils.setProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", "true");
     // avoid mock
+
+  }
+
+  @Before
+  public void setUp() {
+    // clear up load balance stats
     ServiceCombLoadBalancerStats.INSTANCE.init();
   }
 
@@ -203,6 +215,147 @@ public class TestLoadBalanceHandler2 {
   }
 
   @Test
+  public void testZoneAwareAndIsolationFilterUsingMockedInvocationWorks() throws Exception {
+    Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> {
+      aysnc.success("OK");
+    });
+
+    InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class);
+    ServiceRegistry serviceRegistry = Mockito.mock(ServiceRegistry.class);
+    TransportManager transportManager = Mockito.mock(TransportManager.class);
+    Transport transport = Mockito.mock(Transport.class);
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false");
+
+    // set up data
+    MicroserviceInstance myself = new MicroserviceInstance();
+    DataCenterInfo info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region");
+    info.setAvailableZone("test-zone");
+    myself.setDataCenterInfo(info);
+
+    MicroserviceInstance allmatchInstance = new MicroserviceInstance();
+    info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region");
+    info.setAvailableZone("test-zone");
+    List<String> allMatchEndpoint = new ArrayList<>();
+    allMatchEndpoint.add("rest://localhost:7090");
+    allmatchInstance.setEndpoints(allMatchEndpoint);
+    allmatchInstance.setDataCenterInfo(info);
+    allmatchInstance.setInstanceId("allmatchInstance");
+
+    MicroserviceInstance regionMatchInstance = new MicroserviceInstance();
+    info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region");
+    info.setAvailableZone("test-zone2");
+    List<String> regionMatchEndpoint = new ArrayList<>();
+    regionMatchEndpoint.add("rest://localhost:7091");
+    regionMatchInstance.setEndpoints(regionMatchEndpoint);
+    regionMatchInstance.setDataCenterInfo(info);
+    regionMatchInstance.setInstanceId("regionMatchInstance");
+
+    MicroserviceInstance noneMatchInstance = new MicroserviceInstance();
+    info = new DataCenterInfo();
+    info.setName("test");
+    info.setRegion("test-Region2");
+    info.setAvailableZone("test-zone2");
+    List<String> noMatchEndpoint = new ArrayList<>();
+    noMatchEndpoint.add("rest://localhost:7092");
+    noneMatchInstance.setEndpoints(noMatchEndpoint);
+    noneMatchInstance.setDataCenterInfo(info);
+    noneMatchInstance.setInstanceId("noneMatchInstance");
+
+    Map<String, MicroserviceInstance> data = new HashMap<>();
+    DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data);
+    CseContext.getInstance().setTransportManager(transportManager);
+
+    RegistryUtils.setServiceRegistry(serviceRegistry);
+
+    when(serviceRegistry.getMicroserviceInstance()).thenReturn(myself);
+    when(serviceRegistry.getInstanceCacheManager()).thenReturn(instanceCacheManager);
+    when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+"))
+        .thenReturn(parent);
+    when(transportManager.findTransport("rest")).thenReturn(transport);
+
+    LoadbalanceHandler handler = null;
+    LoadBalancer loadBalancer = null;
+    ServiceCombServer server = null;
+
+    DiscoveryTree discoveryTree = new DiscoveryTree();
+    discoveryTree.addFilter(new IsolationDiscoveryFilter());
+    discoveryTree.addFilter(new ZoneAwareDiscoveryFilter());
+    discoveryTree.addFilter(new ServerDiscoveryFilter());
+    discoveryTree.sort();
+    handler = new LoadbalanceHandler(discoveryTree);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server, null);
+
+    data.put("noneMatchInstance", noneMatchInstance);
+    parent.cacheVersion(1);
+    handler = new LoadbalanceHandler();
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7092");
+    handler.handle(invocation, (response) -> {
+      Assert.assertEquals(response.getResult(), "OK");
+    });
+
+    data.put("regionMatchInstance", regionMatchInstance);
+    parent.cacheVersion(parent.cacheVersion() + 1);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    handler.handle(invocation, (response) -> {
+      Assert.assertEquals(response.getResult(), "OK");
+    });
+
+    data.put("allmatchInstance", allmatchInstance);
+    parent.cacheVersion(parent.cacheVersion() + 1);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7090");
+
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server);
+    ServiceCombLoadBalancerStats.INSTANCE.markFailure(server);
+
+    //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active.
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0");
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7090");
+
+    //if errorThresholdPercentage greater than 0, it will activate.
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20");
+    ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10");
+    ServiceCombServer server2 = server;
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    TimeUnit.MILLISECONDS.sleep(20);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7090");
+    ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
+    ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2);
+    loadBalancer = handler.getOrCreateLoadBalancer(invocation);
+    server = loadBalancer.chooseServer(invocation);
+    Assert.assertEquals(server.getEndpoint().getEndpoint(), "rest://localhost:7091");
+    handler.handle(invocation, (response) -> {
+      Assert.assertEquals(response.getResult(), "OK");
+    });
+  }
+
+  @Test
   public void testConfigEndpoint() {
     ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class);
     OperationMeta operationMeta = Mockito.mock(OperationMeta.class);
diff --git a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
index a17f287..3ac2ee7 100644
--- a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
+++ b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.transport.rest.vertx;
 
+import java.nio.channels.ClosedChannelException;
 import java.util.List;
 import java.util.Set;
 
@@ -104,7 +105,12 @@ public class RestServerVerticle extends AbstractVerticle {
         }
       });
       httpServer.exceptionHandler(e -> {
-        LOGGER.error("Unexpected error in server.{}", ExceptionUtils.getExceptionMessageWithoutTrace(e));
+        if(e instanceof ClosedChannelException) {
+          // This is quite normal in between browser and ege, so do not print out.
+          LOGGER.debug("Unexpected error in server.{}", ExceptionUtils.getExceptionMessageWithoutTrace(e));
+        } else {
+          LOGGER.error("Unexpected error in server.{}", ExceptionUtils.getExceptionMessageWithoutTrace(e));
+        }
       });
       startListen(httpServer, startFuture);
     } catch (Throwable e) {