| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.servicecomb.loadbalance; |
| |
| import static org.mockito.Mockito.when; |
| |
| import java.util.ArrayList; |
| import java.util.EventListener; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.xml.ws.Holder; |
| |
| import org.apache.servicecomb.core.CseContext; |
| import org.apache.servicecomb.core.Endpoint; |
| 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; |
| import org.apache.servicecomb.core.definition.OperationMeta; |
| import org.apache.servicecomb.core.definition.SchemaMeta; |
| import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; |
| import org.apache.servicecomb.core.transport.TransportManager; |
| import org.apache.servicecomb.foundation.common.event.EventManager; |
| import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; |
| import org.apache.servicecomb.loadbalance.event.IsolationServerEvent; |
| import org.apache.servicecomb.loadbalance.filterext.IsolationDiscoveryFilter; |
| import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter; |
| import org.apache.servicecomb.loadbalance.filterext.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.api.registry.MicroserviceInstanceStatus; |
| 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.apache.servicecomb.swagger.invocation.exception.InvocationException; |
| 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 mockit.Mock; |
| import mockit.MockUp; |
| |
| /** |
| * |
| * |
| */ |
| public class TestLoadBalanceHandler2 { |
| private Holder<Long> mockTimeMillis; |
| |
| @Before |
| public void setUp() { |
| // clear up load balance stats |
| //prepare for defineEndpointAndHandle |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", "true"); |
| // avoid mock |
| ServiceCombLoadBalancerStats.INSTANCE.init(); |
| TestServiceCombServerStats.releaseTryingChance(); |
| |
| mockTimeMillis = new Holder<>(1L); |
| new MockUp<System>() { |
| @Mock |
| long currentTimeMillis() { |
| return mockTimeMillis.value; |
| } |
| }; |
| } |
| |
| @After |
| public void teardown() { |
| CseContext.getInstance().setTransportManager(null); |
| ArchaiusUtils.resetConfig(); |
| TestServiceCombServerStats.releaseTryingChance(); |
| } |
| |
| @Test |
| public void testZoneAwareAndIsolationFilterWorks() throws Exception { |
| ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); |
| OperationMeta operationMeta = Mockito.mock(OperationMeta.class); |
| SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); |
| when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); |
| MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); |
| when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); |
| when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); |
| when(microserviceMeta.getAppId()).thenReturn("testApp"); |
| when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); |
| when(referenceConfig.getTransport()).thenReturn("rest"); |
| Invocation invocation = new Invocation(referenceConfig, operationMeta, new Object[0]); |
| |
| 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:9090"); |
| 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:9091"); |
| 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:9092"); |
| 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; |
| |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals(null, server); |
| |
| data.put("noneMatchInstance", noneMatchInstance); |
| parent.cacheVersion(1); |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9092", server.getEndpoint().getEndpoint()); |
| |
| data.put("regionMatchInstance", regionMatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| |
| data.put("allmatchInstance", allmatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); |
| |
| //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| |
| //if errorThresholdPercentage greater than 0, it will activate. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10"); |
| ServiceCombServer server2 = server; |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| mockDelayMillis(20); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| } |
| |
| @Test |
| public void testIsolationEventWithEndpoint() throws Exception { |
| ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); |
| OperationMeta operationMeta = Mockito.mock(OperationMeta.class); |
| SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); |
| when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); |
| MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); |
| when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); |
| when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); |
| when(microserviceMeta.getAppId()).thenReturn("testApp"); |
| when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); |
| when(referenceConfig.getTransport()).thenReturn("rest"); |
| Invocation invocation = new Invocation(referenceConfig, operationMeta, new Object[0]); |
| |
| 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"); |
| info.setAvailableZone("test"); |
| myself.setDataCenterInfo(info); |
| |
| MicroserviceInstance instance = new MicroserviceInstance(); |
| info = new DataCenterInfo(); |
| info.setName("test"); |
| info.setRegion("test"); |
| info.setAvailableZone("test"); |
| List<String> allMatchEndpoint = new ArrayList<>(); |
| allMatchEndpoint.add("rest://localhost:9090"); |
| instance.setEndpoints(allMatchEndpoint); |
| instance.setDataCenterInfo(info); |
| instance.setInstanceId("instance"); |
| |
| 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; |
| |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertNull(server); |
| |
| data.put("instance", instance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); |
| |
| //if errorThresholdPercentage greater than 0, it will activate. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "10"); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10"); |
| |
| Holder<Integer> count = new Holder<>(0); |
| EventListener isolationEndpointListener = new EventListener() { |
| @Subscribe |
| public void listener(IsolationServerEvent event) { |
| count.value++; |
| Assert.assertSame("Isolation Endpoint", "rest://localhost:9090", event.getEndpoint().getEndpoint()); |
| } |
| }; |
| EventManager.getEventBus().register(isolationEndpointListener); |
| Assert.assertEquals(0, count.value.intValue()); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| // no server is available |
| Assert.assertNull(server); |
| Assert.assertEquals(1, count.value.intValue()); |
| EventManager.unregister(isolationEndpointListener); |
| } |
| |
| @Test |
| public void testZoneAwareAndIsolationFilterWorksEmptyInstanceProtectionEnabled() throws Exception { |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.emptyInstanceProtectionEnabled", "true"); |
| ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); |
| OperationMeta operationMeta = Mockito.mock(OperationMeta.class); |
| SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); |
| when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); |
| MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); |
| when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); |
| when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); |
| when(microserviceMeta.getAppId()).thenReturn("testApp"); |
| when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); |
| when(referenceConfig.getTransport()).thenReturn("rest"); |
| Invocation invocation = new Invocation(referenceConfig, operationMeta, new Object[0]); |
| |
| 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:9090"); |
| 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:9091"); |
| 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:9092"); |
| 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; |
| |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals(null, server); |
| |
| data.put("noneMatchInstance", noneMatchInstance); |
| parent.cacheVersion(1); |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9092", server.getEndpoint().getEndpoint()); |
| |
| data.put("regionMatchInstance", regionMatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| |
| data.put("allmatchInstance", allmatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); |
| |
| //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| |
| //if errorThresholdPercentage greater than 0, it will activate. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "30"); |
| ServiceCombServer server2 = server; |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| mockDelayMillis(31); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); |
| } |
| |
| @Test |
| public void testZoneAwareAndIsolationFilterUsingMockedInvocationWorks() throws Exception { |
| Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> { |
| aysnc.success("OK"); |
| }); |
| |
| 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 ServerDiscoveryFilter()); |
| discoveryTree.sort(); |
| handler = new LoadbalanceHandler(discoveryTree); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals(null, server); |
| |
| data.put("noneMatchInstance", noneMatchInstance); |
| parent.cacheVersion(1); |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7092", server.getEndpoint().getEndpoint()); |
| handler.handle(invocation, (response) -> { |
| Assert.assertEquals("OK", response.getResult()); |
| }); |
| |
| data.put("regionMatchInstance", regionMatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| handler.handle(invocation, (response) -> { |
| Assert.assertEquals("OK", response.getResult()); |
| }); |
| |
| data.put("allmatchInstance", allmatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); |
| |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); |
| |
| //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); |
| |
| //if errorThresholdPercentage greater than 0, it will activate. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "30"); |
| ServiceCombServer server2 = server; |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| mockDelayMillis(31); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| handler.handle(invocation, (response) -> { |
| Assert.assertEquals("OK", response.getResult()); |
| }); |
| } |
| |
| @Test |
| public void testStatusFilterUsingMockedInvocationWorks() throws Exception { |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.status.enabled", "false"); |
| |
| Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> { |
| aysnc.success("OK"); |
| }); |
| |
| 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"); |
| allmatchInstance.setStatus(MicroserviceInstanceStatus.TESTING); |
| |
| 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 ServerDiscoveryFilter()); |
| discoveryTree.sort(); |
| handler = new LoadbalanceHandler(discoveryTree); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals(null, server); |
| |
| data.put("noneMatchInstance", noneMatchInstance); |
| parent.cacheVersion(1); |
| handler = new LoadbalanceHandler(); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7092", server.getEndpoint().getEndpoint()); |
| handler.handle(invocation, (response) -> { |
| Assert.assertEquals("OK", response.getResult()); |
| }); |
| |
| data.put("regionMatchInstance", regionMatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| handler.handle(invocation, (response) -> { |
| Assert.assertEquals("OK", response.getResult()); |
| }); |
| |
| data.put("allmatchInstance", allmatchInstance); |
| parent.cacheVersion(parent.cacheVersion() + 1); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); |
| |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); |
| |
| //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); |
| |
| //if errorThresholdPercentage greater than 0, it will activate. |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10"); |
| ServiceCombServer server2 = server; |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| mockDelayMillis(20); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); |
| loadBalancer = handler.getOrCreateLoadBalancer(invocation); |
| server = loadBalancer.chooseServer(invocation); |
| Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); |
| handler.handle(invocation, (response) -> { |
| Assert.assertEquals("OK", response.getResult()); |
| }); |
| } |
| |
| @Test |
| public void testConfigEndpoint() { |
| ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); |
| OperationMeta operationMeta = Mockito.mock(OperationMeta.class); |
| SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); |
| when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); |
| MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); |
| when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); |
| when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); |
| when(microserviceMeta.getAppId()).thenReturn("testApp"); |
| when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); |
| when(referenceConfig.getTransport()).thenReturn("rest"); |
| Invocation invocation = new Invocation(referenceConfig, operationMeta, new Object[0]); |
| AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class); |
| |
| 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(); |
| |
| MicroserviceInstance findInstance = new MicroserviceInstance(); |
| List<String> findEndpoint = new ArrayList<>(); |
| findEndpoint.add("rest://localhost:9092"); |
| findInstance.setEndpoints(findEndpoint); |
| findInstance.setInstanceId("findInstance"); |
| |
| Map<String, MicroserviceInstance> data = new HashMap<>(); |
| DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); |
| CseContext.getInstance().setTransportManager(transportManager); |
| SCBEngine.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; |
| |
| handler = new LoadbalanceHandler(); |
| data.put("findInstance", findInstance); |
| parent.cacheVersion(1); |
| handler = new LoadbalanceHandler(); |
| try { |
| handler.handle(invocation, asyncResp); |
| } catch (Exception e) { |
| |
| } |
| Assert.assertEquals("rest://localhost:9092", invocation.getEndpoint().getEndpoint()); |
| |
| //success |
| invocation.addLocalContext("scb-endpoint", "rest://127.0.0.1:8080?sslEnabled=true&protocol=http2"); |
| try { |
| handler.handle(invocation, asyncResp); |
| } catch (Exception e) { |
| |
| } |
| Assert.assertEquals("rest://127.0.0.1:8080?sslEnabled=true&protocol=http2", invocation.getEndpoint().getEndpoint()); |
| |
| //endpoint format is not correct |
| invocation.addLocalContext("scb-endpoint", "127.0.0.1:8080"); |
| try { |
| handler.handle(invocation, asyncResp); |
| Assert.assertEquals("endpoint's format is not correct, throw exception", " but not throw exception"); |
| } catch (Exception e) { |
| Assert.assertTrue(e.getMessage() |
| .contains("Illegal character in scheme name")); |
| } |
| |
| //transport is not find |
| invocation.addLocalContext("scb-endpoint", "my://127.0.0.1:8080?sslEnabled=true&protocol=http2"); |
| try { |
| handler.handle(invocation, asyncResp); |
| Assert.assertEquals("endpoint's transport not found, throw exception", "but not throw exception"); |
| } catch (Exception e) { |
| Assert.assertTrue(e.getMessage().contains("the endpoint's transport is not found.")); |
| } |
| } |
| |
| @Test |
| public void trying_chance_should_be_released() { |
| List<ServiceCombServer> servers = new ArrayList<>(); |
| ServiceCombServer serviceCombServer = createMockedServer("instanceId", "rest://127.0.0.1:8080"); |
| servers.add(serviceCombServer); |
| |
| DiscoveryTree discoveryTree = createMockedDiscoveryTree(servers); |
| LoadbalanceHandler handler = new LoadbalanceHandler(discoveryTree); |
| |
| // mock the process of the isolated server selected and changed to TRYING status |
| ServiceCombServerStats serviceCombServerStats = |
| mockServiceCombServerStats(serviceCombServer, 5, true); |
| |
| Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", |
| (inv, aysnc) -> { |
| Assert.assertEquals("rest://127.0.0.1:8080", inv.getEndpoint().getEndpoint()); |
| Assert.assertTrue(serviceCombServerStats.isIsolated()); |
| Assert.assertEquals(5, serviceCombServerStats.getContinuousFailureCount()); |
| Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); |
| aysnc.success("OK"); |
| }); |
| |
| Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.enabled", "false"); |
| try { |
| handler.handle(invocation, (response) -> Assert.assertEquals("OK", response.getResult())); |
| } catch (Exception e) { |
| Assert.fail("unexpected exception " + e.getMessage()); |
| } |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.enabled", "true"); |
| Assert.assertEquals("rest://127.0.0.1:8080", invocation.getEndpoint().getEndpoint()); |
| Assert.assertTrue(serviceCombServerStats.isIsolated()); |
| Assert.assertEquals(0, serviceCombServerStats.getContinuousFailureCount()); |
| Assert.assertTrue(ServiceCombServerStats.isolatedServerCanTry()); |
| } |
| |
| /** |
| * Two available instances, first time the normal instance is selected and failed. Then retry to the TRYING status |
| * instance. In the whole procedure, the TRYING status instance should keep the TRYING status. |
| */ |
| @Test |
| public void first_normal_instance_then_trying_instance() { |
| ExtensionsManager.addExtentionsFactory(new DefaultRetryExtensionsFactory()); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.retryEnabled", true); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.retryOnNext", 1); |
| |
| ArrayList<ServiceCombServer> servers = new ArrayList<>(); |
| ServiceCombServer server0 = createMockedServer("instanceId0", "rest://127.0.0.1:8080"); |
| ServiceCombServer server1 = createMockedServer("instanceId1", "rest://127.0.0.1:8081"); |
| servers.add(server0); |
| servers.add(server1); |
| |
| ServiceCombServerStats stats0 = mockServiceCombServerStats(server0, 0, false); |
| ServiceCombServerStats stats1 = mockServiceCombServerStats(server1, 5, true); |
| |
| DiscoveryTree discoveryTree = createMockedDiscoveryTree(servers); |
| LoadbalanceHandler handler = new LoadbalanceHandler(discoveryTree); |
| |
| Holder<Integer> counter = new Holder<>(0); |
| Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", |
| (inv, aysnc) -> { |
| Assert.assertFalse(stats0.isIsolated()); |
| Assert.assertTrue(stats1.isIsolated()); |
| Assert.assertEquals(5, stats1.getContinuousFailureCount()); |
| Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); |
| if (counter.value == 0) { |
| Assert.assertEquals("rest://127.0.0.1:8080", inv.getEndpoint().getEndpoint()); |
| Assert.assertEquals(0, stats0.getContinuousFailureCount()); |
| counter.value++; |
| aysnc.producerFail(new InvocationException(503, "RETRY", "retry to next instance")); |
| } else if (counter.value == 1) { |
| Assert.assertEquals("rest://127.0.0.1:8081", inv.getEndpoint().getEndpoint()); |
| Assert.assertEquals(1, stats0.getContinuousFailureCount()); |
| counter.value++; |
| aysnc.success("OK"); |
| } else { |
| aysnc.producerFail(new InvocationException(400, "UNEXPECTED", "Unexpected Counter Value")); |
| } |
| }); |
| |
| Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.enabled", "false"); |
| try { |
| handler.handle(invocation, (response) -> Assert.assertEquals("OK", response.getResult())); |
| } catch (Exception e) { |
| Assert.fail("unexpected exception " + e.getMessage()); |
| } |
| ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.enabled", "true"); |
| Assert.assertEquals("rest://127.0.0.1:8081", invocation.getEndpoint().getEndpoint()); |
| Assert.assertFalse(stats0.isIsolated()); |
| Assert.assertEquals(1, stats0.getContinuousFailureCount()); |
| Assert.assertTrue(stats1.isIsolated()); |
| Assert.assertEquals(0, stats1.getContinuousFailureCount()); |
| Assert.assertTrue(ServiceCombServerStats.isolatedServerCanTry()); |
| } |
| |
| /** |
| * Mock the statistics of the specified {@code serviceCombServer}, set the failureCount and status. |
| * @return the ServiceCombServerStats object corresponding to the param {@code serviceCombServer} |
| */ |
| private ServiceCombServerStats mockServiceCombServerStats(ServiceCombServer serviceCombServer, int failureCount, |
| boolean isIsolatedStatus) { |
| ServiceCombServerStats serviceCombServerStats = |
| ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer); |
| for (int i = 0; i < failureCount; ++i) { |
| serviceCombServerStats.markFailure(); |
| } |
| serviceCombServerStats.markIsolated(isIsolatedStatus); |
| return serviceCombServerStats; |
| } |
| |
| /** |
| * Create a mocked ServiceCombServer with specified microserviceInstanceId and endpoint. |
| */ |
| private ServiceCombServer createMockedServer(String microserviceInstanceId, String endpoint) { |
| MicroserviceInstance microserviceInstance = new MicroserviceInstance(); |
| microserviceInstance.setInstanceId(microserviceInstanceId); |
| return new ServiceCombServer(null, |
| new Endpoint(Mockito.mock(Transport.class), endpoint), |
| microserviceInstance); |
| } |
| |
| /** |
| * Create a mocked DiscoveryTree that always returns {@code servers} as the versionedCache result. |
| */ |
| private DiscoveryTree createMockedDiscoveryTree(List<ServiceCombServer> servers) { |
| DiscoveryTree discoveryTree = Mockito.mock(DiscoveryTree.class); |
| DiscoveryTreeNode versionedCache = new DiscoveryTreeNode() |
| .name("testVersionedCacheName") |
| .data(servers); |
| Mockito.when(discoveryTree.discovery(Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) |
| .thenReturn(versionedCache); |
| return discoveryTree; |
| } |
| |
| private void mockDelayMillis(long delay) { |
| mockTimeMillis.value += delay; |
| } |
| } |