You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by GitBox <gi...@apache.org> on 2018/06/20 08:44:41 UTC

[GitHub] liubao68 closed pull request #678: [SCB-506]服务治理相关的需要事件上报

liubao68 closed pull request #678: [SCB-506]服务治理相关的需要事件上报
URL: https://github.com/apache/incubator-servicecomb-java-chassis/pull/678
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java
new file mode 100644
index 000000000..1f100c148
--- /dev/null
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java
@@ -0,0 +1,35 @@
+/*
+ * 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.foundation.common.event;
+
+public class AlarmEvent {
+
+  Type type;
+
+  public AlarmEvent(Type type) {
+    this.type = type;
+  }
+
+  public Type getType() {
+    return this.type;
+  }
+
+  public enum Type {
+    OPEN,
+    CLOSE
+  };
+}
diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java
index a4e0aa428..22a2cfcdc 100644
--- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java
+++ b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java
@@ -31,8 +31,8 @@ private CommandKey() {
   }
 
   public static HystrixCommandGroupKey toHystrixCommandGroupKey(String type, Invocation invocation) {
-    return HystrixCommandGroupKey.Factory
-        .asKey(type + "." + invocation.getOperationMeta().getMicroserviceQualifiedName());
+    return CustomizeCommandGroupKey.asKey(type + "." + invocation.getOperationMeta().getMicroserviceQualifiedName(),
+        invocation);
   }
 
   public static HystrixCommandKey toHystrixCommandKey(String type, Invocation invocation) {
diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CustomizeCommandGroupKey.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CustomizeCommandGroupKey.java
new file mode 100644
index 000000000..c80e926f1
--- /dev/null
+++ b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CustomizeCommandGroupKey.java
@@ -0,0 +1,58 @@
+/*
+ * 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.bizkeeper;
+
+import org.apache.servicecomb.core.Invocation;
+
+import com.netflix.hystrix.HystrixCommandGroupKey;
+import com.netflix.hystrix.HystrixKey;
+import com.netflix.hystrix.util.InternMap;
+
+/**
+ * ͨ������CommandGroupKey��Ŀ����Я��Invocation���־�̬��Ϣ������CircutBreakerEvent��ȡ��
+ */
+public class CustomizeCommandGroupKey extends HystrixKey.HystrixKeyDefault implements HystrixCommandGroupKey {
+
+  private Invocation instance;
+
+  public CustomizeCommandGroupKey(String key) {
+    super(key);
+  }
+
+  private static final InternMap<String, CustomizeCommandGroupKey> intern = new InternMap<String, CustomizeCommandGroupKey>(
+      new InternMap.ValueConstructor<String, CustomizeCommandGroupKey>() {
+        @Override
+        public CustomizeCommandGroupKey create(String key) {
+          return new CustomizeCommandGroupKey(key);
+        }
+      });
+
+  public static HystrixCommandGroupKey asKey(String key, Invocation invocation) {
+    CustomizeCommandGroupKey result = intern.interned(key);
+    result.setInvocation(invocation);
+    return result;
+  }
+
+  public void setInvocation(Invocation invocation) {
+    this.instance = invocation;
+  }
+
+  public Invocation getInstance() {
+    return instance;
+  }
+}
diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEvent.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEvent.java
new file mode 100644
index 000000000..c9f7a8ed8
--- /dev/null
+++ b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEvent.java
@@ -0,0 +1,113 @@
+/*
+ * 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.bizkeeper.event;
+
+
+import org.apache.servicecomb.bizkeeper.CustomizeCommandGroupKey;
+import org.apache.servicecomb.foundation.common.event.AlarmEvent;
+
+import com.netflix.hystrix.HystrixCommandKey;
+import com.netflix.hystrix.HystrixCommandMetrics;
+
+public class CircutBreakerEvent extends AlarmEvent {
+
+  private String role;
+
+  private String microservice;
+
+  private String schema;
+
+  private String operation;
+
+  //当前总请求数
+  private long currentTotalRequest;
+
+  //当前请求出错计数
+  private long currentErrorCount;
+
+  //当前请求出错百分比
+  private long currentErrorPercentage;
+
+  private int requestVolumeThreshold;
+
+  private int sleepWindowInMilliseconds;
+
+  private int errorThresholdPercentage;
+
+  public CircutBreakerEvent(HystrixCommandKey commandKey, Type type) {
+    super(type);
+    HystrixCommandMetrics hystrixCommandMetrics = HystrixCommandMetrics.getInstance(commandKey);
+    if (hystrixCommandMetrics != null) {
+      if (hystrixCommandMetrics.getCommandGroup() instanceof CustomizeCommandGroupKey) {
+        CustomizeCommandGroupKey customCommandGroupKey =
+            (CustomizeCommandGroupKey) hystrixCommandMetrics.getCommandGroup();
+        this.microservice = customCommandGroupKey.getInstance().getMicroserviceName();
+        this.role = customCommandGroupKey.getInstance().getInvocationType().name();
+        this.schema = customCommandGroupKey.getInstance().getSchemaId();
+        this.operation = customCommandGroupKey.getInstance().getOperationName();
+      }
+      this.currentTotalRequest = hystrixCommandMetrics.getHealthCounts().getTotalRequests();
+      this.currentErrorPercentage = hystrixCommandMetrics.getHealthCounts().getErrorCount();
+      this.currentErrorCount = hystrixCommandMetrics.getHealthCounts().getErrorPercentage();
+      this.requestVolumeThreshold = hystrixCommandMetrics.getProperties().circuitBreakerRequestVolumeThreshold().get();
+      this.sleepWindowInMilliseconds =
+          hystrixCommandMetrics.getProperties().circuitBreakerSleepWindowInMilliseconds().get();
+      this.errorThresholdPercentage =
+          hystrixCommandMetrics.getProperties().circuitBreakerErrorThresholdPercentage().get();
+    }
+  }
+
+  public String getRole() {
+    return role;
+  }
+
+  public String getMicroservice() {
+    return microservice;
+  }
+
+  public String getSchema() {
+    return schema;
+  }
+
+  public String getOperation() {
+    return operation;
+  }
+
+  public long getCurrentTotalRequest() {
+    return currentTotalRequest;
+  }
+
+  public long getCurrentErrorCount() {
+    return currentErrorCount;
+  }
+
+  public long getCurrentErrorPercentage() {
+    return currentErrorPercentage;
+  }
+
+  public int getRequestVolumeThreshold() {
+    return requestVolumeThreshold;
+  }
+
+  public int getSleepWindowInMilliseconds() {
+    return sleepWindowInMilliseconds;
+  }
+
+  public int getErrorThresholdPercentage() {
+    return errorThresholdPercentage;
+  }
+}
diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEventNotifier.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEventNotifier.java
new file mode 100644
index 000000000..3b47b5f20
--- /dev/null
+++ b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEventNotifier.java
@@ -0,0 +1,61 @@
+/*
+ * 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.bizkeeper.event;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.apache.servicecomb.foundation.common.event.AlarmEvent.Type;
+
+import com.google.common.eventbus.EventBus;
+import com.netflix.hystrix.HystrixCommandKey;
+import com.netflix.hystrix.HystrixEventType;
+import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
+
+public class CircutBreakerEventNotifier extends HystrixEventNotifier {
+
+  /**
+   * 使用circuitFlag来记录被熔断的接口
+   */
+  private ConcurrentHashMapEx<String, AtomicBoolean> circuitFlag = new ConcurrentHashMapEx<>();
+
+  EventBus eventBus = EventManager.getEventBus();
+
+  @Override
+  public void markEvent(HystrixEventType eventType, HystrixCommandKey key) {
+    String keyName = key.name();
+    AtomicBoolean flag = circuitFlag.computeIfAbsent(keyName, k -> new AtomicBoolean());
+    switch (eventType) {
+      case SHORT_CIRCUITED:
+        if (flag.compareAndSet(false, true)) {
+          eventBus.post(new CircutBreakerEvent(key, Type.OPEN));
+        }
+        break;
+
+      case SUCCESS:
+        if (flag.compareAndSet(true, false)) {
+          eventBus.post(new CircutBreakerEvent(key, Type.CLOSE));
+        }
+        break;
+
+      default:
+        break;
+    }
+  }
+}
diff --git a/handlers/handler-bizkeeper/src/main/resources/hystrix-plugins.properties b/handlers/handler-bizkeeper/src/main/resources/hystrix-plugins.properties
new file mode 100644
index 000000000..ba987ff21
--- /dev/null
+++ b/handlers/handler-bizkeeper/src/main/resources/hystrix-plugins.properties
@@ -0,0 +1 @@
+hystrix.plugin.HystrixEventNotifier.implementation=org.apache.servicecomb.bizkeeper.event.CircutBreakerEventNotifier
\ No newline at end of file
diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java
index be3e6be59..9629d32c7 100644
--- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java
+++ b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java
@@ -39,7 +39,6 @@ public void testGetCacheKeyProvider() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -72,7 +71,6 @@ public void testResumeWithFallbackProvider() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -93,7 +91,6 @@ public void testConstructProvider() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -114,7 +111,6 @@ public void testGetCacheKeyWithContextInitializedProvider() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -136,7 +132,6 @@ public void testGetCacheKeyConsumer() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -169,7 +164,6 @@ public void testResumeWithFallbackConsumer() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -190,7 +184,6 @@ public void testConstructConsumer() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
@@ -211,7 +204,6 @@ public void testGetCacheKeyWithContextInitializedConsumer() {
     Invocation invocation = Mockito.mock(Invocation.class);
     Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class));
     Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1");
-
     HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
         .withRequestCacheEnabled(true)
         .withRequestLogEnabled(false);
diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCustomCommandGroupKey.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCustomCommandGroupKey.java
new file mode 100644
index 000000000..9bcf64eaa
--- /dev/null
+++ b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCustomCommandGroupKey.java
@@ -0,0 +1,44 @@
+/*
+ * 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.bizkeeper;
+
+import org.apache.servicecomb.core.Invocation;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestCustomCommandGroupKey {
+  @Test
+  public void testToHystrixCommandGroupKey() {
+    Invocation invocation = Mockito.mock(Invocation.class);
+    CustomizeCommandGroupKey customizeCommandGroupKey =
+        (CustomizeCommandGroupKey) CustomizeCommandGroupKey.asKey("key", invocation);
+    Assert.assertEquals(invocation, customizeCommandGroupKey.getInstance());
+  }
+
+  @Test
+  public void testOOM() {
+    Invocation invocation1 = Mockito.mock(Invocation.class);
+    Invocation invocation2 = Mockito.mock(Invocation.class);
+    CustomizeCommandGroupKey customizeCommandGroupKey1 =
+        (CustomizeCommandGroupKey) CustomizeCommandGroupKey.asKey("key", invocation1);
+    CustomizeCommandGroupKey customizeCommandGroupKey2 =
+        (CustomizeCommandGroupKey) CustomizeCommandGroupKey.asKey("key", invocation2);
+    Assert.assertEquals(customizeCommandGroupKey1, customizeCommandGroupKey2);
+  }
+}
diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/event/TestCircutBreakerEventNotifier.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/event/TestCircutBreakerEventNotifier.java
new file mode 100644
index 000000000..3f58ca75c
--- /dev/null
+++ b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/event/TestCircutBreakerEventNotifier.java
@@ -0,0 +1,79 @@
+/*
+ * 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.bizkeeper.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.foundation.common.event.AlarmEvent;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.google.common.eventbus.Subscribe;
+import com.netflix.hystrix.HystrixCommandKey;
+import com.netflix.hystrix.HystrixCommandMetrics;
+import com.netflix.hystrix.HystrixEventType;
+
+import mockit.Expectations;
+
+public class TestCircutBreakerEventNotifier {
+  private List<AlarmEvent> taskList = null;
+
+  CircutBreakerEventNotifier circutBreakerEventNotifier;
+
+  HystrixCommandKey commandKey = null;
+
+  Object receiveEvent = null;
+
+  @Before
+  public void setUp() throws Exception {
+    taskList = new ArrayList<>();
+    circutBreakerEventNotifier = new CircutBreakerEventNotifier();
+    commandKey = Mockito.mock(HystrixCommandKey.class);
+    receiveEvent = new Object() {
+      @Subscribe
+      public void onEvent(AlarmEvent circutBreakerEvent) {
+        taskList.add(circutBreakerEvent);
+      }
+    };
+    circutBreakerEventNotifier.eventBus.register(receiveEvent);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    circutBreakerEventNotifier.eventBus.unregister(receiveEvent);
+  }
+
+  @Test
+  public void testMarkEvent() {
+    Mockito.when(commandKey.name()).thenReturn("Consumer.springmvc.springmvcHello.sayHi");
+    new Expectations(HystrixCommandMetrics.class) {
+      {
+        HystrixCommandMetrics.getInstance(commandKey);
+        result = null;
+      }
+    };
+    circutBreakerEventNotifier.markEvent(HystrixEventType.SHORT_CIRCUITED, commandKey);
+    Assert.assertEquals(1, taskList.size());
+    circutBreakerEventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey);
+    Assert.assertEquals(2, taskList.size());
+  }
+}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java
new file mode 100644
index 000000000..93218c967
--- /dev/null
+++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicecomb.loadbalance.event;
+
+import org.apache.servicecomb.foundation.common.event.AlarmEvent;
+
+public class IsolationServerEvent extends AlarmEvent {
+
+  private String microserviceName;
+
+  //当前实例总请求数
+  private long currentTotalRequest;
+
+  //当前实例连续出错次数
+  private int currentCountinuousFailureCount;
+
+  //当前实例出错百分比
+  private double currentErrorPercentage;
+
+  private long enableRequestThreshold;
+
+  private int continuousFailureThreshold;
+
+  private int errorThresholdPercentage;
+
+  private long singleTestTime;
+
+  public IsolationServerEvent(String microserviceName, long totalRequest, int currentCountinuousFailureCount,
+      double currentErrorPercentage, int continuousFailureThreshold,
+      int errorThresholdPercentage, long enableRequestThreshold, long singleTestTime, Type type) {
+    super(type);
+    this.microserviceName = microserviceName;
+    this.currentTotalRequest = totalRequest;
+    this.currentCountinuousFailureCount = currentCountinuousFailureCount;
+    this.currentErrorPercentage = currentErrorPercentage;
+    this.enableRequestThreshold = enableRequestThreshold;
+    this.continuousFailureThreshold = continuousFailureThreshold;
+    this.errorThresholdPercentage = errorThresholdPercentage;
+    this.singleTestTime = singleTestTime;
+  }
+
+  public String getMicroserviceName() {
+    return microserviceName;
+  }
+
+  public long getCurrentTotalRequest() {
+    return currentTotalRequest;
+  }
+
+  public int getCurrentCountinuousFailureCount() {
+    return currentCountinuousFailureCount;
+  }
+
+  public double getCurrentErrorPercentage() {
+    return currentErrorPercentage;
+  }
+
+  public long getEnableRequestThreshold() {
+    return enableRequestThreshold;
+  }
+
+  public int getContinuousFailureThreshold() {
+    return continuousFailureThreshold;
+  }
+
+  public int getErrorThresholdPercentage() {
+    return errorThresholdPercentage;
+  }
+
+  public long getSingleTestTime() {
+    return singleTestTime;
+  }
+}
diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationServerListFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationServerListFilter.java
index 5d263e059..91724d9fd 100644
--- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationServerListFilter.java
+++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationServerListFilter.java
@@ -20,12 +20,16 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.servicecomb.foundation.common.event.AlarmEvent.Type;
+import org.apache.servicecomb.foundation.common.event.EventManager;
 import org.apache.servicecomb.loadbalance.Configuration;
 import org.apache.servicecomb.loadbalance.CseServer;
 import org.apache.servicecomb.loadbalance.ServerListFilterExt;
+import org.apache.servicecomb.loadbalance.event.IsolationServerEvent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.eventbus.EventBus;
 import com.netflix.loadbalancer.LoadBalancerStats;
 import com.netflix.loadbalancer.Server;
 import com.netflix.loadbalancer.ServerStats;
@@ -48,6 +52,8 @@
 
   private LoadBalancerStats stats;
 
+  public EventBus eventBus = EventManager.getEventBus();
+
   public void setLoadBalancerStats(LoadBalancerStats stats) {
     this.stats = stats;
   }
@@ -91,19 +97,22 @@ private boolean allowVisit(Server server) {
     ServerStats serverStats = stats.getSingleServerStat(server);
     long totalRequest = serverStats.getTotalRequestsCount();
     long failureRequest = serverStats.getSuccessiveConnectionFailureCount();
-
+    int currentCountinuousFailureCount = 0;
+    double currentErrorThresholdPercentage = 0;
     if (totalRequest < enableRequestThreshold) {
       return true;
     }
 
     if (continuousFailureThreshold > 0) {
       // continuousFailureThreshold has higher priority to decide the result
-      if (((CseServer) server).getCountinuousFailureCount() < continuousFailureThreshold) {
+      currentCountinuousFailureCount = ((CseServer) server).getCountinuousFailureCount();
+      if (currentCountinuousFailureCount < continuousFailureThreshold) {
         return true;
       }
     } else {
       // if continuousFailureThreshold, then check error percentage
-      if ((failureRequest / (double) totalRequest) * PERCENT < errorThresholdPercentage) {
+      currentErrorThresholdPercentage = (failureRequest / (double) totalRequest) * PERCENT;
+      if (currentErrorThresholdPercentage < errorThresholdPercentage) {
         return true;
       }
     }
@@ -112,10 +121,18 @@ private boolean allowVisit(Server server) {
       LOGGER.info("The Service {}'s instance {} has been break, will give a single test opportunity.",
           microserviceName,
           server);
+      eventBus.post(new IsolationServerEvent(microserviceName, totalRequest, currentCountinuousFailureCount,
+          currentErrorThresholdPercentage,
+          continuousFailureThreshold, errorThresholdPercentage, enableRequestThreshold,
+          singleTestTime, Type.CLOSE));
       return true;
     }
 
     LOGGER.warn("The Service {}'s instance {} has been break!", microserviceName, server);
+    eventBus.post(new IsolationServerEvent(microserviceName, totalRequest, currentCountinuousFailureCount,
+        currentErrorThresholdPercentage,
+        continuousFailureThreshold, errorThresholdPercentage, enableRequestThreshold,
+        singleTestTime, Type.OPEN));
     return false;
   }
 }
diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestIsolationServerListFilter.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestIsolationServerListFilter.java
index e7a25ec34..be767f7a7 100644
--- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestIsolationServerListFilter.java
+++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestIsolationServerListFilter.java
@@ -23,6 +23,8 @@
 import org.apache.commons.configuration.AbstractConfiguration;
 import org.apache.servicecomb.config.ConfigUtil;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.common.event.AlarmEvent;
+import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils;
 import org.apache.servicecomb.loadbalance.CseServer;
 import org.junit.After;
 import org.junit.AfterClass;
@@ -32,19 +34,21 @@
 import org.junit.Test;
 import org.mockito.Mockito;
 
-import com.netflix.config.ConfigurationManager;
+import com.google.common.eventbus.Subscribe;
 import com.netflix.config.DynamicPropertyFactory;
 import com.netflix.loadbalancer.LoadBalancerStats;
 import com.netflix.loadbalancer.Server;
 
-import mockit.Deencapsulation;
-
 public class TestIsolationServerListFilter {
 
-  IsolationServerListFilter IsolationServerListFilter = null;
+  IsolationServerListFilter isolationServerListFilter = null;
 
   LoadBalancerStats loadBalancerStats = null;
 
+  private List<AlarmEvent> taskList = null;
+
+  Object receiveEvent = null;
+
   @BeforeClass
   public static void initConfig() throws Exception {
     ConfigUtil.installDynamicConfig();
@@ -52,29 +56,32 @@ public static void initConfig() throws Exception {
 
   @AfterClass
   public static void classTeardown() {
-    Deencapsulation.setField(ConfigurationManager.class, "instance", null);
-    Deencapsulation.setField(ConfigurationManager.class, "customConfigurationInstalled", false);
-    Deencapsulation.setField(DynamicPropertyFactory.class, "config", null);
+    ArchaiusUtils.resetConfig();
   }
 
   @Before
   public void setUp() throws Exception {
-    IsolationServerListFilter = new IsolationServerListFilter();
+    isolationServerListFilter = new IsolationServerListFilter();
     loadBalancerStats = new LoadBalancerStats("loadBalancer");
-
-    AbstractConfiguration configuration =
-        (AbstractConfiguration) DynamicPropertyFactory.getBackingConfigurationSource();
-    configuration.clearProperty("cse.loadbalance.isolation.enabled");
-    configuration.addProperty("cse.loadbalance.isolation.enabled",
+    ArchaiusUtils.setProperty("cse.loadbalance.isolation.enabled",
         "true");
-    configuration.clearProperty("cse.loadbalance.isolation.enableRequestThreshold");
-    configuration.addProperty("cse.loadbalance.isolation.enableRequestThreshold",
+    ArchaiusUtils.setProperty("cse.loadbalance.isolation.enableRequestThreshold",
         "3");
+
+    taskList = new ArrayList<>();
+    receiveEvent = new Object() {
+      @Subscribe
+      public void onEvent(AlarmEvent isolationServerEvent) {
+        taskList.add(isolationServerEvent);
+      }
+    };
+    isolationServerListFilter.eventBus.register(receiveEvent);
   }
 
   @After
   public void tearDown() throws Exception {
-    IsolationServerListFilter = null;
+    isolationServerListFilter.eventBus.unregister(receiveEvent);
+    isolationServerListFilter = null;
     loadBalancerStats = null;
 
     AbstractConfiguration configuration =
@@ -84,16 +91,16 @@ public void tearDown() throws Exception {
 
   @Test
   public void testSetLoadBalancerStats() {
-    IsolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
-    Assert.assertNotNull(IsolationServerListFilter.getLoadBalancerStats());
-    Assert.assertEquals(loadBalancerStats, IsolationServerListFilter.getLoadBalancerStats());
+    isolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
+    Assert.assertNotNull(isolationServerListFilter.getLoadBalancerStats());
+    Assert.assertEquals(loadBalancerStats, isolationServerListFilter.getLoadBalancerStats());
   }
 
   @Test
   public void testSetMicroserviceName() {
-    IsolationServerListFilter.setMicroserviceName("microserviceName");
-    Assert.assertNotNull(IsolationServerListFilter.getMicroserviceName());
-    Assert.assertEquals("microserviceName", IsolationServerListFilter.getMicroserviceName());
+    isolationServerListFilter.setMicroserviceName("microserviceName");
+    Assert.assertNotNull(isolationServerListFilter.getMicroserviceName());
+    Assert.assertEquals("microserviceName", isolationServerListFilter.getMicroserviceName());
   }
 
   @Test
@@ -105,16 +112,16 @@ public void testGetFilteredListOfServers() {
 
     List<Server> serverList = new ArrayList<>();
     serverList.add(testServer);
-    IsolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
-    IsolationServerListFilter.setInvocation(invocation);
-    List<Server> returnedServerList = IsolationServerListFilter.getFilteredListOfServers(serverList);
+    isolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
+    isolationServerListFilter.setInvocation(invocation);
+    List<Server> returnedServerList = isolationServerListFilter.getFilteredListOfServers(serverList);
     Assert.assertEquals(returnedServerList.size(), 1);
 
     loadBalancerStats.incrementNumRequests(testServer);
     loadBalancerStats.incrementNumRequests(testServer);
     loadBalancerStats.incrementNumRequests(testServer);
     loadBalancerStats.incrementSuccessiveConnectionFailureCount(testServer);
-    returnedServerList = IsolationServerListFilter.getFilteredListOfServers(serverList);
+    returnedServerList = isolationServerListFilter.getFilteredListOfServers(serverList);
     Assert.assertEquals(returnedServerList.size(), 0);
   }
 
@@ -135,10 +142,11 @@ public void testGetFilteredListOfServersOnContinuousFailureReachesThreshold() {
 
     List<Server> serverList = new ArrayList<>();
     serverList.add(testServer);
-    IsolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
-    IsolationServerListFilter.setInvocation(invocation);
-    List<Server> returnedServerList = IsolationServerListFilter.getFilteredListOfServers(serverList);
+    isolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
+    isolationServerListFilter.setInvocation(invocation);
+    List<Server> returnedServerList = isolationServerListFilter.getFilteredListOfServers(serverList);
     Assert.assertEquals(0, returnedServerList.size());
+    Assert.assertEquals(1, taskList.size());
   }
 
   @Test
@@ -158,9 +166,9 @@ public void testGetFilteredListOfServersOnContinuousFailureIsBelowThreshold() {
 
     List<Server> serverList = new ArrayList<>();
     serverList.add(testServer);
-    IsolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
-    IsolationServerListFilter.setInvocation(invocation);
-    List<Server> returnedServerList = IsolationServerListFilter.getFilteredListOfServers(serverList);
+    isolationServerListFilter.setLoadBalancerStats(loadBalancerStats);
+    isolationServerListFilter.setInvocation(invocation);
+    List<Server> returnedServerList = isolationServerListFilter.getFilteredListOfServers(serverList);
     Assert.assertEquals(1, returnedServerList.size());
   }
 }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services