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/06/20 08:44:42 UTC

[incubator-servicecomb-java-chassis] branch master updated: [SCB-506]服务治理相关的事件需要上报 (#678)

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


The following commit(s) were added to refs/heads/master by this push:
     new 861e198  [SCB-506]服务治理相关的事件需要上报 (#678)
861e198 is described below

commit 861e198e6880deafe1092097ae1f935f7c1b9de7
Author: xuyiyun0929 <32...@users.noreply.github.com>
AuthorDate: Wed Jun 20 16:44:38 2018 +0800

    [SCB-506]服务治理相关的事件需要上报 (#678)
    
    * [SCB-506]服务治理相关的需要事件上报
    
    * [SCB-506] Use ConcurrentHashMap instead of HashMap
    
    * [SCB-506] Use ConcurrentHashMap instead of HashMap
    
    * [SCB-506] Get CircutBreakerEvent via HystrixEventNotifier
    
    * [SCB-506] Optimize for suggestions
    
    * [SCB-506] Optimize for suggestions
    
    * [SCB-506] Customize HystrixCommandGroupKey to avoid always split string.
    
    * [SCB-506] Customize HystrixCommandGroupKey to avoid always split string.
    
    * [SCB-506] Repair OOM problem and add a OOM test case
    
    * [SCB-506] check getCommandGroup() if instance of CustomizeCommandGroupKey
---
 .../foundation/common/event/AlarmEvent.java        |  29 ++----
 .../apache/servicecomb/bizkeeper/CommandKey.java   |   4 +-
 .../bizkeeper/CustomizeCommandGroupKey.java        |  58 +++++++++++
 .../bizkeeper/event/CircutBreakerEvent.java        | 113 +++++++++++++++++++++
 .../event/CircutBreakerEventNotifier.java          |  61 +++++++++++
 .../src/main/resources/hystrix-plugins.properties  |   1 +
 .../bizkeeper/TestBizkeeperCommand.java            |   8 --
 .../bizkeeper/TestCustomCommandGroupKey.java       |  44 ++++++++
 .../event/TestCircutBreakerEventNotifier.java      |  79 ++++++++++++++
 .../loadbalance/event/IsolationServerEvent.java    |  87 ++++++++++++++++
 .../filter/IsolationServerListFilter.java          |  23 ++++-
 .../filter/TestIsolationServerListFilter.java      |  72 +++++++------
 12 files changed, 516 insertions(+), 63 deletions(-)

diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java
similarity index 52%
copy from handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java
copy to foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java
index a4e0aa4..1f100c1 100644
--- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java
@@ -14,29 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.servicecomb.foundation.common.event;
 
-package org.apache.servicecomb.bizkeeper;
+public class AlarmEvent {
 
-import org.apache.servicecomb.core.Invocation;
+  Type type;
 
-import com.netflix.hystrix.HystrixCommandGroupKey;
-import com.netflix.hystrix.HystrixCommandKey;
-
-/**
- * 创建对应的Key值
- *
- */
-public final class CommandKey {
-  private CommandKey() {
+  public AlarmEvent(Type type) {
+    this.type = type;
   }
 
-  public static HystrixCommandGroupKey toHystrixCommandGroupKey(String type, Invocation invocation) {
-    return HystrixCommandGroupKey.Factory
-        .asKey(type + "." + invocation.getOperationMeta().getMicroserviceQualifiedName());
+  public Type getType() {
+    return this.type;
   }
 
-  public static HystrixCommandKey toHystrixCommandKey(String type, Invocation invocation) {
-    return HystrixCommandKey.Factory
-        .asKey(type + "." + invocation.getOperationMeta().getMicroserviceQualifiedName());
-  }
+  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 a4e0aa4..22a2cfc 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 @@ public final class 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 0000000..c80e926
--- /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 0000000..c9f7a8e
--- /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 0000000..3b47b5f
--- /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 0000000..ba987ff
--- /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 be3e6be..9629d32 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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 class TestBizkeeperCommand {
     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 0000000..9bcf64e
--- /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 0000000..3f58ca7
--- /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 0000000..93218c9
--- /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 5d263e0..91724d9 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 @@ package org.apache.servicecomb.loadbalance.filter;
 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 @@ public final class IsolationServerListFilter implements ServerListFilterExt {
 
   private LoadBalancerStats stats;
 
+  public EventBus eventBus = EventManager.getEventBus();
+
   public void setLoadBalancerStats(LoadBalancerStats stats) {
     this.stats = stats;
   }
@@ -91,19 +97,22 @@ public final class IsolationServerListFilter implements ServerListFilterExt {
     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 @@ public final class IsolationServerListFilter implements ServerListFilterExt {
       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 e7a25ec..be767f7 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 java.util.List;
 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.BeforeClass;
 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 class TestIsolationServerListFilter {
 
   @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 class TestIsolationServerListFilter {
 
   @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 class TestIsolationServerListFilter {
 
     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 class TestIsolationServerListFilter {
 
     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 class TestIsolationServerListFilter {
 
     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());
   }
 }