[SCB-2361] Support SC dual cluster multi active mode (#2691)
diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
index 28772d4..b939657 100644
--- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
+++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
@@ -17,46 +17,28 @@
package org.apache.servicecomb.config.center.client;
-import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.lang.StringUtils;
-import org.apache.servicecomb.http.client.common.HttpUtils;
+import org.apache.servicecomb.http.client.common.AbstractAddressManager;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
-public class AddressManager {
- public static final String DEFAULT_PROJECT = "default";
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
- private final String projectName;
+public class AddressManager extends AbstractAddressManager {
- private final List<String> addresses;
-
- private int index = 0;
-
- public AddressManager(String projectName, List<String> addresses) {
- this.projectName = StringUtils.isEmpty(projectName) ? DEFAULT_PROJECT : projectName;
- this.addresses = new ArrayList<>(addresses.size());
- addresses.forEach((address -> this.addresses.add(formatAddress(address))));
+ public AddressManager(String projectName, List<String> addresses, EventBus eventBus) {
+ super(projectName, addresses);
+ eventBus.register(this);
}
- private String formatAddress(String address) {
- try {
- return address + "/v3/" + HttpUtils.encodeURLParam(this.projectName);
- } catch (Exception e) {
- throw new IllegalStateException("not possible");
- }
+ @Override
+ public String joinProject(String address) {
+ return formatAddress(address);
}
- public String address() {
- synchronized (this) {
- this.index++;
- if (this.index >= addresses.size()) {
- this.index = 0;
- }
- return addresses.get(index);
- }
+ @Subscribe
+ public void onRefreshEndpointEvent(RefreshEndpointEvent event) {
+ refreshEndpoint(event, RefreshEndpointEvent.CONFIG_CENTER_NAME);
}
-
- public boolean sslEnabled() {
- return address().startsWith("https://");
- }
-}
+}
\ No newline at end of file
diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java
index 132fe20..50d1ce5 100644
--- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java
+++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java
@@ -65,8 +65,9 @@
Map<String, Object> configurations = new HashMap<>();
String uri = null;
+ String address = addressManager.address();
try {
- uri = addressManager.address() + "/configuration/items?dimensionsInfo="
+ uri = address + "/configuration/items?dimensionsInfo="
+ HttpUtils.encodeURLParam(dimensionsInfo) + "&revision=" + request.getRevision();
Map<String, String> headers = new HashMap<>();
@@ -102,13 +103,16 @@
}
queryConfigurationsResponse.setConfigurations(configurations);
queryConfigurationsResponse.setChanged(true);
+ addressManager.recordSuccessState(address);
return queryConfigurationsResponse;
} else if (httpResponse.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
queryConfigurationsResponse.setChanged(false);
+ addressManager.recordSuccessState(address);
return queryConfigurationsResponse;
} else if (httpResponse.getStatusCode() == HttpStatus.SC_BAD_REQUEST) {
throw new OperationException("Bad request for query configurations.");
} else {
+ addressManager.recordFailState(address);
throw new OperationException(
"read response failed. status:"
+ httpResponse.getStatusCode()
@@ -118,6 +122,7 @@
+ httpResponse.getContent());
}
} catch (IOException e) {
+ addressManager.recordFailState(address);
LOGGER.error("query configuration from {} failed, message={}", uri, e.getMessage());
throw new OperationException("", e);
}
diff --git a/clients/config-kie-client/pom.xml b/clients/config-kie-client/pom.xml
index 198e306..b81d518 100644
--- a/clients/config-kie-client/pom.xml
+++ b/clients/config-kie-client/pom.xml
@@ -42,6 +42,12 @@
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>failureaccess</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
index 5b64f2d..6a54aa6 100644
--- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java
@@ -66,8 +66,8 @@
@Override
public ConfigurationsResponse queryConfigurations(ConfigurationsRequest request) {
- String url = buildUrl(request);
-
+ String address = addressManager.address();
+ String url = buildUrl(request, address);
try {
if (kieConfiguration.isEnableLongPolling()) {
url += "&wait=" + kieConfiguration.getPollingWaitInSeconds() + "s";
@@ -83,6 +83,7 @@
configurationsResponse.setConfigurations(configurations);
configurationsResponse.setChanged(true);
configurationsResponse.setRevision(revision);
+ addressManager.recordSuccessState(address);
return configurationsResponse;
}
if (httpResponse.getStatusCode() == HttpStatus.SC_BAD_REQUEST) {
@@ -90,8 +91,10 @@
}
if (httpResponse.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
configurationsResponse.setChanged(false);
+ addressManager.recordSuccessState(address);
return configurationsResponse;
}
+ addressManager.recordFailState(address);
throw new OperationException(
"read response failed. status:" + httpResponse.getStatusCode() + "; message:" +
httpResponse.getMessage() + "; content:" + httpResponse.getContent());
@@ -101,9 +104,9 @@
}
}
- private String buildUrl(ConfigurationsRequest request) {
+ private String buildUrl(ConfigurationsRequest request, String currentAddress) {
StringBuilder sb = new StringBuilder();
- sb.append(addressManager.address());
+ sb.append(currentAddress);
sb.append("/");
sb.append(DEFAULT_KIE_API_VERSION);
sb.append("/");
diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java
index dde884f..0742c11 100644
--- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java
+++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java
@@ -17,30 +17,23 @@
package org.apache.servicecomb.config.kie.client.model;
-import java.util.ArrayList;
import java.util.List;
-public class KieAddressManager {
- private final List<String> addresses;
+import org.apache.servicecomb.http.client.common.AbstractAddressManager;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
- private int index = 0;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
- public KieAddressManager(List<String> addresses) {
- this.addresses = new ArrayList<>(addresses.size());
- this.addresses.addAll(addresses);
- }
-
- public String address() {
- synchronized (this) {
- this.index++;
- if (this.index >= addresses.size()) {
- this.index = 0;
- }
- return addresses.get(index);
- }
+public class KieAddressManager extends AbstractAddressManager {
+
+ public KieAddressManager(List<String> addresses, EventBus eventBus) {
+ super(addresses);
+ eventBus.register(this);
}
- public boolean sslEnabled() {
- return address().startsWith("https://");
+ @Subscribe
+ public void onRefreshEndpointEvent(RefreshEndpointEvent event) {
+ refreshEndpoint(event, RefreshEndpointEvent.KIE_NAME);
}
}
diff --git a/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/KieAddressManagerTest.java b/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/KieAddressManagerTest.java
new file mode 100644
index 0000000..2269f6d
--- /dev/null
+++ b/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/KieAddressManagerTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.config.kie.client.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.eventbus.EventBus;
+
+import mockit.Deencapsulation;
+
+class KieAddressManagerTest {
+
+ private static List<String> addresses = new ArrayList<>();
+
+ private static KieAddressManager addressManager1;
+
+ @Test
+ public void kieAddressManagerTest() {
+ addresses.add("http://127.0.0.1:30103");
+ addresses.add("https://127.0.0.2:30103");
+ addressManager1 = new KieAddressManager(addresses, new EventBus());
+
+ Assert.assertNotNull(addressManager1);
+
+ List<String> addresses = Deencapsulation.getField(addressManager1, "addresses");
+ Assert.assertEquals(2, addresses.size());
+ Assert.assertEquals("http://127.0.0.1:30103", addresses.get(0));
+
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+ }
+
+
+ @Test
+ public void onRefreshEndpointEvent() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.3:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("http://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ addressManager1 = new KieAddressManager(addresses, new EventBus());
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "KIE");
+ addressManager1.refreshEndpoint(event, "KIE");
+
+ List<String> availableZone = Deencapsulation.getField(addressManager1, "availableZone");
+ Assert.assertEquals("http://127.0.0.3:30100", availableZone.get(0));
+
+ List<String> availableRegion = Deencapsulation.getField(addressManager1, "availableRegion");
+ Assert.assertEquals("http://127.0.0.4:30100", availableRegion.get(0));
+ }
+}
\ No newline at end of file
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/AbstractAddressManager.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/AbstractAddressManager.java
new file mode 100644
index 0000000..971fc42
--- /dev/null
+++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/AbstractAddressManager.java
@@ -0,0 +1,309 @@
+/*
+ * 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.http.client.common;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+public class AbstractAddressManager {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAddressManager.class);
+
+ public static final String DEFAULT_PROJECT = "default";
+
+ public static final String V4_PREFIX = "/v4/";
+
+ private static final String V3_PREFIX = "/v3/";
+
+ private static final int DEFAULT_METRICS_WINDOW_TIME = 1;
+
+ private List<String> addresses = new ArrayList<>();
+
+ private int index = 0;
+
+ private String projectName;
+
+ private Map<String, Boolean> categoryMap = new HashMap<>();
+
+ private Map<String, Integer> recodeStatus = new ConcurrentHashMap<>();
+
+ private Map<String, Boolean> history = new ConcurrentHashMap<>();
+
+ private volatile List<String> availableZone = new ArrayList<>();
+
+ private volatile List<String> availableRegion = new ArrayList<>();
+
+ private volatile List<String> defaultAddress = new ArrayList<>();
+
+ private boolean isAddressRefresh = false;
+
+ private final Object lock = new Object();
+
+ private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1,
+ new ThreadFactoryBuilder()
+ .setNameFormat("check-available-address-%d")
+ .build());
+
+ private Cache<String, Boolean> cacheAddress = CacheBuilder.newBuilder()
+ .maximumSize(100)
+ .expireAfterWrite(10, TimeUnit.MINUTES)
+ .build();
+
+ public AbstractAddressManager(List<String> addresses) {
+ this.addresses.addAll(addresses);
+ }
+
+ public AbstractAddressManager(String projectName, List<String> addresses) {
+ this.projectName = StringUtils.isEmpty(projectName) ? DEFAULT_PROJECT : projectName;
+ this.addresses = this.transformAddress(addresses);
+ this.defaultAddress = this.addresses;
+ }
+
+ @VisibleForTesting
+ protected void setAddressRefresh(boolean addressRefresh) {
+ isAddressRefresh = addressRefresh;
+ }
+
+ private void startCheck() {
+ executorService.scheduleAtFixedRate(this::checkHistory,
+ 0,
+ DEFAULT_METRICS_WINDOW_TIME,
+ TimeUnit.MINUTES);
+ }
+
+ public String formatUrl(String url, boolean absoluteUrl, String address) {
+ return absoluteUrl ? address + url : formatAddress(address) + url;
+ }
+
+ // if isAddressRefresh is false, polling with available initial addresses.
+ public String address() {
+ if (!isAddressRefresh) {
+ return getDefaultAddress();
+ } else {
+ return getAvailableZoneAddress();
+ }
+ }
+
+ public boolean sslEnabled() {
+ return address().startsWith("https://");
+ }
+
+ protected List<String> transformAddress(List<String> addresses) {
+ return addresses.stream().map(this::formatAddress).collect(Collectors.toList());
+ }
+
+ protected String getUrlPrefix(String address) {
+ return address + V3_PREFIX;
+ }
+
+ protected String formatAddress(String address) {
+ try {
+ return getUrlPrefix(address) + HttpUtils.encodeURLParam(this.projectName);
+ } catch (Exception e) {
+ throw new IllegalStateException("not possible");
+ }
+ }
+
+ private String getDefaultAddress() {
+ List<String> addresses = getAvailableAddress(defaultAddress);
+ if (!addresses.isEmpty()) {
+ return getCurrentAddress(addresses);
+ }
+ return getInitAddress();
+ }
+
+ private String getAvailableZoneAddress() {
+ List<String> addresses = getAvailableZoneIpPorts();
+ if (!addresses.isEmpty()) {
+ return joinProject(getCurrentAddress(addresses));
+ }
+ return getInitAddress();
+ }
+
+ // when all available address is fail, it will use all the initial addresses for polling.
+ private String getInitAddress() {
+ if (addresses.isEmpty()) {
+ return null;
+ }
+ return getCurrentAddress(addresses);
+ }
+
+ private String getCurrentAddress(List<String> addresses) {
+ synchronized (this) {
+ this.index++;
+ if (this.index >= addresses.size()) {
+ this.index = 0;
+ }
+ return addresses.get(index);
+ }
+ }
+
+ protected String joinProject(String address) {
+ return address;
+ }
+
+ private List<String> getAvailableZoneIpPorts() {
+ List<String> results = new ArrayList<>();
+ if (!availableZone.isEmpty()) {
+ results.addAll(getAvailableAddress(availableZone));
+ } else {
+ results.addAll(getAvailableAddress(availableRegion));
+ }
+ return results;
+ }
+
+ private List<String> getAvailableAddress(List<String> endpoints) {
+ List<String> list = endpoints.stream().filter(uri -> !history.containsKey(uri))
+ .collect(Collectors.toList());
+ return list;
+ }
+
+ protected String normalizeUri(String endpoint) {
+ if (endpoint.contains("sslEnabled=true")) {
+ return StringUtils.replace(endpoint, "rest", "https");
+ }
+ return StringUtils.replace(endpoint, "rest", "http");
+ }
+
+ public void refreshEndpoint(RefreshEndpointEvent event, String key) {
+ this.setAddressRefresh(true);
+ if (null == event || !event.getName().equals(key)) {
+ return;
+ }
+ availableZone = event.getSameZone().stream().map(this::normalizeUri).collect(Collectors.toList());
+ availableRegion = event.getSameRegion().stream().map(this::normalizeUri).collect(Collectors.toList());
+ availableZone.forEach(address -> categoryMap.put(address, true));
+ availableRegion.forEach(address -> categoryMap.put(address, false));
+ startCheck();
+ }
+
+ public void recordFailState(String address) {
+ if (!recodeStatus.containsKey(address)) {
+ recodeStatus.put(address, 1);
+ return;
+ }
+ synchronized (lock) {
+ int number = recodeStatus.get(address) + 1;
+ if (number < 3) {
+ recodeStatus.put(address, number);
+ } else {
+ removeAddress(address);
+ }
+ }
+ }
+
+ public void recordSuccessState(String address) {
+ recodeStatus.put(address, 0);
+ }
+
+ @VisibleForTesting
+ protected void checkHistory() {
+ history.keySet().stream().filter(this::judgeIsolation).forEach(s -> {
+ if (telnetTest(s)) {
+ rejoinAddress(s);
+ } else {
+ cacheAddress.put(s, false);
+ }
+ });
+ }
+
+ private Boolean judgeIsolation(String address) {
+ try {
+ return cacheAddress.get(address, () -> true);
+ } catch (ExecutionException e) {
+ return true;
+ }
+ }
+
+ private boolean telnetTest(String address) {
+ URI ipPort = parseIpPortFromURI(address);
+ try (Socket s = new Socket()) {
+ s.connect(new InetSocketAddress(ipPort.getHost(), ipPort.getPort()), 3000);
+ return true;
+ } catch (IOException e) {
+ LOGGER.warn("ping endpoint {} failed, It will be quarantined again.", address);
+ }
+ return false;
+ }
+
+ private URI parseIpPortFromURI(String uri) {
+ try {
+ return new URI(uri);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+
+ //Query whether the current address belongs to the same AZ or region through azmap,
+ // add it to the sequence of, and delete the record in history
+ @VisibleForTesting
+ void rejoinAddress(String address) {
+ if (!isAddressRefresh) {
+ defaultAddress.add(address);
+ } else {
+ if (categoryMap.get(address)) {
+ availableZone.add(address);
+ } else {
+ availableRegion.add(address);
+ }
+ }
+ recodeStatus.put(address, 0);
+ history.remove(address);
+ }
+
+ //Query whether the current address belongs to the same AZ or the same region through AZMap,
+ // and delete it from the record. At the same time, add records in history and cache
+ @VisibleForTesting
+ void removeAddress(String address) {
+ if (!isAddressRefresh) {
+ defaultAddress.remove(address);
+ history.put(address, false);
+ } else {
+ if (categoryMap.get(address)) {
+ availableZone.remove(address);
+ } else {
+ availableRegion.remove(address);
+ }
+ history.put(address, categoryMap.get(address));
+ }
+ recodeStatus.put(address, 0);
+ cacheAddress.put(address, false);
+ }
+}
diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/RefreshEndpointEvent.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/RefreshEndpointEvent.java
new file mode 100644
index 0000000..4e4f1be
--- /dev/null
+++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/RefreshEndpointEvent.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.http.client.event;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RefreshEndpointEvent {
+
+ public static final String SERVICE_CENTER_NAME = "SERVICECENTER";
+
+ public static final String KIE_NAME = "KIE";
+
+ public static final String CONFIG_CENTER_NAME = "CseConfigCenter";
+
+ public static final String CSE_MONITORING_NAME = "CseMonitoring";
+
+ private static final String SAME_ZONE = "sameZone";
+
+ private static final String SAME_REGION = "sameRegion";
+
+ private Map<String, List<String>> zoneAndRegion = new HashMap<>();
+
+ private String name;
+
+ public RefreshEndpointEvent(Map<String, List<String>> zoneAndRegion, String name) {
+ this.zoneAndRegion = zoneAndRegion;
+ this.name = name;
+ }
+
+ public List<String> getSameZone() {
+ if (zoneAndRegion.get(SAME_ZONE).isEmpty()) {
+ return new ArrayList<>();
+ }
+ return zoneAndRegion.get(SAME_ZONE);
+ }
+
+ public List<String> getSameRegion() {
+ if (zoneAndRegion.get(SAME_REGION).isEmpty()) {
+ return new ArrayList<>();
+ }
+ return zoneAndRegion.get(SAME_REGION);
+ }
+
+ public Map<String, List<String>> getZoneAndRegion() {
+ return zoneAndRegion;
+ }
+
+ public void setZoneAndRegion(Map<String, List<String>> zoneAndRegion) {
+ this.zoneAndRegion = zoneAndRegion;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/AbstractAddressManagerTest.java b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/AbstractAddressManagerTest.java
new file mode 100644
index 0000000..ee38ced
--- /dev/null
+++ b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/AbstractAddressManagerTest.java
@@ -0,0 +1,299 @@
+/*
+ * 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.http.client.common;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.junit.Assert;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+import mockit.Deencapsulation;
+import mockit.Expectations;
+
+public class AbstractAddressManagerTest {
+
+ private static List<String> addresses = new ArrayList<>();
+
+ private static AbstractAddressManager addressManager1;
+
+ private static AbstractAddressManager addressManager2;
+
+ private static AbstractAddressManager addressManager3;
+
+ @BeforeEach
+ public void setUp() {
+ addresses.add("http://127.0.0.1:30103");
+ addresses.add("https://127.0.0.2:30103");
+ addressManager1 = new AbstractAddressManager(addresses);
+ addressManager2 = new AbstractAddressManager("project", addresses);
+ addressManager3 = new AbstractAddressManager(null, addresses);
+ }
+
+ @AfterEach
+ public void tearDown() {
+ addresses.clear();
+ addressManager1 = null;
+ addressManager2 = null;
+ addressManager3 = null;
+ }
+
+ @Test
+ public void abstractAddressManagerTest() {
+ Assert.assertNotNull(addressManager1);
+ Assert.assertNotNull(addressManager2);
+ Assert.assertNotNull(addressManager3);
+
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+ }
+
+ @Test
+ public void recordStateTest() throws ExecutionException {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.3:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("http://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST");
+ AbstractAddressManager addressManager = new AbstractAddressManager(addresses);
+
+ addressManager.refreshEndpoint(event, "TEST");
+
+ String address = "http://127.0.0.3:30100";
+ addressManager.recordFailState(address);
+
+ Assert.assertEquals("http://127.0.0.3:30100", addressManager.address());
+
+ addressManager.recordFailState(address);
+ Assert.assertEquals("http://127.0.0.3:30100", addressManager.address());
+
+ // test fail 2 times ,it will not be isolated
+ addressManager.recordSuccessState(address);
+ Assert.assertEquals("http://127.0.0.3:30100", addressManager.address());
+
+ // test recodeStatus times
+ Map<String, Integer> recodeStatus = Deencapsulation.getField(addressManager, "recodeStatus");
+ Assert.assertEquals(0, (int) recodeStatus.get("http://127.0.0.3:30100"));
+
+ // test fail 3 times ,it will be isolated
+ addressManager.recordFailState(address);
+ addressManager.recordFailState(address);
+ addressManager.recordFailState(address);
+ Assert.assertEquals("http://127.0.0.4:30100", addressManager.address());
+
+ // mock cacheAddress status refresh after 10 minute
+ Cache<String, Boolean> cache = CacheBuilder.newBuilder()
+ .maximumSize(100)
+ .expireAfterWrite(10, TimeUnit.MINUTES)
+ .build();
+ cache.put("http://127.0.0.3:30100", true);
+
+ // mock the address telnetTest is access
+ new Expectations(addressManager) {
+ {
+ Deencapsulation.setField(addressManager, "cacheAddress", cache);
+ Deencapsulation.invoke(addressManager, "telnetTest", "http://127.0.0.3:30100");
+ result = true;
+ }
+ };
+ Cache<String, Boolean> result = Deencapsulation.getField(addressManager, "cacheAddress");
+ Assert.assertEquals(true, result.get("http://127.0.0.3:30100", () -> false));
+
+ // test restore isolation
+ addressManager.checkHistory();
+ addressManager.rejoinAddress("http://127.0.0.3:30100");
+ Assert.assertEquals("http://127.0.0.3:30100", addressManager.address());
+ Assert.assertEquals("http://127.0.0.3:30100", addressManager.address());
+ }
+
+
+ @Test
+ public void testMiltiThread() throws Exception {
+
+ AbstractAddressManager addressManager = new AbstractAddressManager(addresses);
+ String address = "http://127.0.0.3:30100";
+
+ CountDownLatch latch = new CountDownLatch(2);
+ for (int i = 0; i < 2; i++) {
+ new Thread(() -> {
+ addressManager.recordFailState(address);
+ latch.countDown();
+ }).start();
+ }
+ latch.await(30, TimeUnit.SECONDS);
+
+ Map<String, Integer> recodeStatus = Deencapsulation.getField(addressManager, "recodeStatus");
+ Assert.assertEquals(2, (int) recodeStatus.get("http://127.0.0.3:30100"));
+ }
+
+ @Test
+ public void addressForOnlyDefaultTest() {
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+
+ Assert.assertEquals("https://127.0.0.2:30103/v3/project", addressManager2.address());
+ Assert.assertEquals("http://127.0.0.1:30103/v3/project", addressManager2.address());
+
+ Assert.assertEquals("https://127.0.0.2:30103/v3/default", addressManager3.address());
+ Assert.assertEquals("http://127.0.0.1:30103/v3/default", addressManager3.address());
+ }
+
+ @Test
+ public void addressForOnlyAzTest() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.1:30100");
+ addressAZ.add("https://127.0.0.2:30100");
+ addressAZ.add("rest://127.0.0.1:30100?sslEnabled=true");
+ addressAZ.add("rest://127.0.0.2:30100");
+
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", new ArrayList<>());
+ RefreshEndpointEvent event1 = new RefreshEndpointEvent(zoneAndRegion, "TEST");
+ addressManager1.refreshEndpoint(event1, "TEST");
+
+ Assert.assertEquals("https://127.0.0.2:30100", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.1:30100?sslEnabled=true", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.2:30100", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30100", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.2:30100", addressManager1.address());
+ }
+
+ @Test
+ public void addressForOnlyRegionTest() {
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("rest://127.0.0.5:30100?sslEnabled=true");
+ addressRG.add("rest://127.0.0.6:30100");
+ addressRG.add("http://127.0.0.7:30100");
+ addressRG.add("https://127.0.0.8:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", new ArrayList<>());
+ zoneAndRegion.put("sameRegion", addressRG);
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST");
+ addressManager1.refreshEndpoint(event, "TEST");
+
+ Assert.assertEquals("http://127.0.0.6:30100", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.7:30100", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.8:30100", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.5:30100?sslEnabled=true", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.6:30100", addressManager1.address());
+ }
+
+ @Test
+ public void addressForAzAndRegionTest() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("rest://127.0.0.1:30100?sslEnabled=true");
+ addressAZ.add("https://127.0.0.2:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("rest://127.0.0.3:30100?sslEnabled=true");
+ addressRG.add("https://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST");
+ addressManager1.refreshEndpoint(event, "TEST");
+
+ Assert.assertEquals("https://127.0.0.2:30100", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.1:30100?sslEnabled=true", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.2:30100", addressManager1.address());
+
+ addressManager1.removeAddress("https://127.0.0.2:30100");
+ addressManager1.removeAddress("https://127.0.0.1:30100?sslEnabled=true");
+ Assert.assertEquals("https://127.0.0.3:30100?sslEnabled=true", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.4:30100", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.3:30100?sslEnabled=true", addressManager1.address());
+
+ addressManager1.removeAddress("https://127.0.0.4:30100");
+ addressManager1.removeAddress("https://127.0.0.3:30100?sslEnabled=true");
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ }
+
+ @Test
+ public void sslEnabledTest() {
+ Assert.assertEquals(true, addressManager1.sslEnabled());
+ Assert.assertEquals(false, addressManager1.sslEnabled());
+ Assert.assertEquals(true, addressManager1.sslEnabled());
+
+ Assert.assertEquals(true, addressManager2.sslEnabled());
+ Assert.assertEquals(false, addressManager2.sslEnabled());
+ Assert.assertEquals(true, addressManager2.sslEnabled());
+ }
+
+ @Test
+ public void transformAddressTest() {
+ List<String> address = new ArrayList<>();
+ address.add("rest://127.0.0.1:30100?sslEnabled=true");
+ address.add("rest://127.0.0.2:30100");
+ address.add("http://127.0.0.3:30100");
+ address.add("https://127.0.0.4:30100");
+
+ List<String> formAddress = addressManager2.transformAddress(address);
+
+ Assert.assertEquals("rest://127.0.0.1:30100?sslEnabled=true/v3/project", formAddress.get(0));
+ Assert.assertEquals("rest://127.0.0.2:30100/v3/project", formAddress.get(1));
+ Assert.assertEquals("http://127.0.0.3:30100/v3/project", formAddress.get(2));
+ Assert.assertEquals("https://127.0.0.4:30100/v3/project", formAddress.get(3));
+
+ formAddress = addressManager3.transformAddress(address);
+ Assert.assertEquals("rest://127.0.0.1:30100?sslEnabled=true/v3/default", formAddress.get(0));
+ Assert.assertEquals("rest://127.0.0.2:30100/v3/default", formAddress.get(1));
+ Assert.assertEquals("http://127.0.0.3:30100/v3/default", formAddress.get(2));
+ Assert.assertEquals("https://127.0.0.4:30100/v3/default", formAddress.get(3));
+ }
+
+ @Test
+ public void getUrlPrefixTest() {
+ Assert.assertEquals("http://127.0.0.3:30100/v3/", addressManager2.getUrlPrefix("http://127.0.0.3:30100"));
+ Assert.assertEquals("http://127.0.0.3:30100/v3/", addressManager3.getUrlPrefix("http://127.0.0.3:30100"));
+ }
+
+ @Test
+ public void refreshEndpointTest() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("rest://127.0.0.1:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", new ArrayList<>());
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST");
+
+ addressManager1.refreshEndpoint(event, "KIE");
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+
+ addressManager2.refreshEndpoint(event, "TEST");
+ Assert.assertEquals("http://127.0.0.1:30100", addressManager2.address());
+ Assert.assertEquals("http://127.0.0.1:30100", addressManager2.address());
+ }
+}
\ No newline at end of file
diff --git a/clients/service-center-client/pom.xml b/clients/service-center-client/pom.xml
index e2cbea8..ec3696d 100755
--- a/clients/service-center-client/pom.xml
+++ b/clients/service-center-client/pom.xml
@@ -48,5 +48,10 @@
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>failureaccess</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java
index df3e96c..1185fde 100644
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java
@@ -17,47 +17,32 @@
package org.apache.servicecomb.service.center.client;
-import java.util.ArrayList;
import java.util.List;
-import org.apache.servicecomb.http.client.common.HttpUtils;
+import org.apache.servicecomb.http.client.common.AbstractAddressManager;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
-public class AddressManager {
- private final String projectName;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
- private final List<String> addresses;
-
- private int index = 0;
-
- public AddressManager(String projectName, List<String> addresses) {
- this.projectName = projectName;
- this.addresses = new ArrayList<>(addresses.size());
- this.addresses.addAll(addresses);
+public class AddressManager extends AbstractAddressManager {
+ public AddressManager(String projectName, List<String> addresses, EventBus eventBus) {
+ super(projectName, addresses);
+ eventBus.register(this);
}
- private String formatAddress(String address) {
- try {
- return address + "/v4/" + HttpUtils.encodeURLParam(this.projectName);
- } catch (Exception e) {
- throw new IllegalStateException("not possible");
- }
+ @Override
+ protected List<String> transformAddress(List<String> addresses) {
+ return addresses;
}
- public boolean sslEnabled() {
- return address().startsWith("https://");
+ @Override
+ protected String getUrlPrefix(String address) {
+ return address + V4_PREFIX;
}
- public String address() {
- synchronized (this) {
- index++;
- if (index >= addresses.size()) {
- index = 0;
- }
- return addresses.get(index);
- }
- }
-
- public String formatUrl(String url, boolean absoluteUrl) {
- return absoluteUrl ? address() + url : formatAddress(address()) + url;
+ @Subscribe
+ public void onRefreshEndpointEvent(RefreshEndpointEvent event) {
+ refreshEndpoint(event, RefreshEndpointEvent.SERVICE_CENTER_NAME);
}
}
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java
index 3b9a48b..8f49df3 100755
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java
@@ -69,24 +69,28 @@
private HttpResponse doHttpRequest(String url, boolean absoluteUrl, Map<String, String> headers, String content,
String method)
throws IOException {
-
- String address = addressManager.formatUrl(url, absoluteUrl);
+ String address = addressManager.address();
+ String formatUrl = addressManager.formatUrl(url, absoluteUrl, address);
if (headers == null) {
headers = new HashMap<>();
}
headers.put(HEADER_TENANT_NAME, tenantName);
- HttpRequest httpRequest = new HttpRequest(address, headers, content, method);
+ HttpRequest httpRequest = new HttpRequest(formatUrl, headers, content, method);
try {
- return httpTransport.doRequest(httpRequest);
+ HttpResponse httpResponse = httpTransport.doRequest(httpRequest);
+ addressManager.recordSuccessState(address);
+ return httpResponse;
} catch (IOException e) {
- String retryAddress = addressManager.formatUrl(url, absoluteUrl);
- LOGGER.warn("send request to {} failed and retry to {} once. ", address,
- retryAddress, e);
- httpRequest = new HttpRequest(retryAddress, headers, content, method);
+ addressManager.recordFailState(address);
+ String retryAddress = addressManager.address();
+ formatUrl = addressManager.formatUrl(url, absoluteUrl, retryAddress);
+ LOGGER.warn("send request to {} failed and retry to {} once. ", address, retryAddress, e);
+ httpRequest = new HttpRequest(formatUrl, headers, content, method);
try {
return httpTransport.doRequest(httpRequest);
} catch (IOException ioException) {
+ addressManager.recordFailState(retryAddress);
LOGGER.warn("retry to {} failed again. ", retryAddress, e);
throw ioException;
}
diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java
index d8faafa..597f516 100644
--- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java
+++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java
@@ -102,25 +102,26 @@
private void startWatch() {
connector.submit(() -> {
backOff();
-
+ String address = addressManager.address();
try {
Map<String, String> headers = new HashMap<>();
headers.put("x-domain-name", this.tenantName);
headers.putAll(this.extraGlobalHeaders);
headers.putAll(this.requestAuthHeaderProvider.loadAuthHeader(null));
- currentServerUri = convertAddress();
+ currentServerUri = convertAddress(address);
LOGGER.info("start watch to address {}", currentServerUri);
webSocketTransport = new WebSocketTransport(currentServerUri, sslProperties,
headers, this);
webSocketTransport.connectBlocking();
+ addressManager.recordSuccessState(address);
} catch (Exception e) {
+ addressManager.recordFailState(address);
LOGGER.error("start watch failed. ", e);
}
});
}
- private String convertAddress() {
- String address = addressManager.address();
+ private String convertAddress(String address) {
String url = String.format(WATCH, project, serviceId);
if (address.startsWith(HTTP)) {
return WS + address.substring(HTTP.length()) + url;
@@ -129,7 +130,6 @@
if (address.startsWith(HTTPS)) {
return WSS + address.substring(HTTPS.length()) + url;
}
-
return address + url;
}
diff --git a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/AddressManagerTest.java b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/AddressManagerTest.java
new file mode 100644
index 0000000..8dd0906
--- /dev/null
+++ b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/AddressManagerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.service.center.client;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.eventbus.EventBus;
+
+import mockit.Deencapsulation;
+
+class AddressManagerTest {
+
+ private static List<String> addresses = new ArrayList<>();
+
+ private static AddressManager addressManager1;
+
+ private static AddressManager addressManager2;
+
+
+ @Test
+ public void getUrlPrefix() {
+ addresses.add("http://127.0.0.1:30103");
+ addressManager1 = new AddressManager("project", addresses, new EventBus());
+
+ Assert.assertNotNull(addressManager1);
+
+ List<String> addresses = Deencapsulation.getField(addressManager1, "addresses");
+ Assert.assertEquals(1, addresses.size());
+ Assert.assertEquals("http://127.0.0.1:30103", addresses.get(0));
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103/v4/", addressManager1.getUrlPrefix("http://127.0.0.1:30103"));
+ }
+
+ @Test
+ public void formatUrlTest() {
+ addresses.add("http://127.0.0.1:30103");
+ addressManager1 = new AddressManager("project", addresses, new EventBus());
+ Assert.assertNotNull(addressManager1);
+
+ String address = addressManager1.address();
+ Assert.assertEquals("http://127.0.0.1:30103", address);
+ String url = addressManager1.formatUrl("/test/", false, address);
+ Assert.assertEquals("http://127.0.0.1:30103/v4/project/test/", url);
+
+ url = addressManager1.formatUrl("/test/", true, address);
+ Assert.assertEquals("http://127.0.0.1:30103/test/", url);
+ }
+
+ @Test
+ public void onRefreshEndpointEvent() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.3:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("http://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ addressManager1 = new AddressManager("project", addresses, new EventBus());
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "SERVICECENTER");
+ addressManager1.refreshEndpoint(event, "SERVICECENTER");
+
+ List<String> availableZone = Deencapsulation.getField(addressManager1, "availableZone");
+ Assert.assertEquals("http://127.0.0.3:30100", availableZone.get(0));
+
+ List<String> availableRegion = Deencapsulation.getField(addressManager1, "availableRegion");
+ Assert.assertEquals("http://127.0.0.4:30100", availableRegion.get(0));
+ }
+}
\ No newline at end of file
diff --git a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java
index f7a3f7b..0bdf026 100755
--- a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java
+++ b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java
@@ -26,6 +26,8 @@
import org.junit.Test;
import org.mockito.Mockito;
+import com.google.common.eventbus.EventBus;
+
/**
* Created by on 2019/10/16.
*/
@@ -43,8 +45,7 @@
public void TestDefaultParameter() throws IOException {
HttpTransport httpTransport = Mockito.mock(HttpTransport.class);
-
- AddressManager addressManager = new AddressManager(PROJECT_NAME, Arrays.asList("http://127.0.0.1:30100"));
+ AddressManager addressManager = new AddressManager(PROJECT_NAME, Arrays.asList("http://127.0.0.1:30100"), new EventBus());
ServiceCenterRawClient client = new ServiceCenterRawClient.Builder()
.setHttpTransport(httpTransport)
.setAddressManager(addressManager)
diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
index ef523b2..3f54cfe 100644
--- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
+++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java
@@ -65,7 +65,7 @@
@Override
public void testRestTransport() throws Exception {
- AddressManager addressManager = new AddressManager("default", Arrays.asList("http://127.0.0.1:30100"));
+ AddressManager addressManager = new AddressManager("default", Arrays.asList("http://127.0.0.1:30100"), new EventBus());
SSLProperties sslProperties = new SSLProperties();
sslProperties.setEnabled(false);
ServiceCenterClient serviceCenterClient = new ServiceCenterClient(addressManager, sslProperties,
diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
index 91059b8..ee94138 100644
--- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
+++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java
@@ -180,7 +180,8 @@
private AddressManager configKieAddressManager() {
return new AddressManager(ConfigCenterConfig.INSTANCE.getDomainName(),
Deployment
- .getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER).getAccessURL());
+ .getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER).getAccessURL(),
+ EventManager.getEventBus());
}
private void updateConfiguration(WatchedUpdateResult result) {
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImplTest.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImplTest.java
new file mode 100644
index 0000000..c53d41d
--- /dev/null
+++ b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImplTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.config;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.servicecomb.config.center.client.AddressManager;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+class ConfigCenterConfigurationSourceImplTest {
+
+ @Test
+ void configKieAddressManagerTest() {
+ List<String> addresses = new ArrayList<>();
+ addresses.add("http://127.0.0.1:30103");
+ addresses.add("http://127.0.0.2:30103");
+ AddressManager addressManager = new AddressManager("test", addresses, EventManager.getEventBus());
+ Assert.assertNotNull(addressManager);
+
+ String address = addressManager.address();
+ Assert.assertEquals("http://127.0.0.2:30103/v3/test",address);
+ address = addressManager.address();
+ Assert.assertEquals("http://127.0.0.1:30103/v3/test",address);
+
+ addressManager = new AddressManager(null, addresses, EventManager.getEventBus());
+ address = addressManager.address();
+ Assert.assertEquals("http://127.0.0.2:30103/v3/default",address);
+ }
+}
\ No newline at end of file
diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/center/client/AddressManagerTest.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/center/client/AddressManagerTest.java
new file mode 100644
index 0000000..a0c4228
--- /dev/null
+++ b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/center/client/AddressManagerTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.config.center.client;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.eventbus.EventBus;
+
+import mockit.Deencapsulation;
+
+class AddressManagerTest {
+ private static List<String> addresses = new ArrayList<>();
+
+ private static AddressManager addressManager1;
+
+ private static AddressManager addressManager2;
+
+ @Test
+ public void addressManagerTest() {
+ addresses.add("http://127.0.0.1:30103");
+ addresses.add("https://127.0.0.2:30103");
+ addressManager1 = new AddressManager("project", addresses, new EventBus());
+ addressManager2 = new AddressManager(null, addresses, new EventBus());
+
+ Assert.assertNotNull(addressManager1);
+ Assert.assertNotNull(addressManager2);
+
+ List<String> addresses = Deencapsulation.getField(addressManager1, "addresses");
+ Assert.assertEquals(2, addresses.size());
+ Assert.assertEquals("http://127.0.0.1:30103/v3/project", addresses.get(0));
+
+ Assert.assertEquals("https://127.0.0.2:30103/v3/project", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103/v3/project", addressManager1.address());
+ Assert.assertEquals("https://127.0.0.2:30103/v3/default", addressManager2.address());
+ }
+
+ @Test
+ public void onRefreshEndpointEvent() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.3:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("http://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ addressManager1 = new AddressManager("project", addresses, new EventBus());
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "CseConfigCenter");
+ addressManager1.refreshEndpoint(event, "CseConfigCenter");
+
+ List<String> availableZone = Deencapsulation.getField(addressManager1, "availableZone");
+ Assert.assertEquals("http://127.0.0.3:30100", availableZone.get(0));
+
+ List<String> availableRegion = Deencapsulation.getField(addressManager1, "availableRegion");
+ Assert.assertEquals("http://127.0.0.4:30100", availableRegion.get(0));
+ }
+}
\ No newline at end of file
diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
index cd06a82..183bd6a 100644
--- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
+++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java
@@ -131,7 +131,7 @@
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create().
setDefaultRequestConfig(requestConfig);
HttpHost proxy = new HttpHost(KieConfig.INSTANCE.getProxyHost(),
- KieConfig.INSTANCE.getProxyPort(),"http"); // now only support http proxy
+ KieConfig.INSTANCE.getProxyPort(), "http"); // now only support http proxy
httpClientBuilder.setProxy(proxy);
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(new AuthScope(proxy),
@@ -163,7 +163,7 @@
private KieAddressManager configKieAddressManager() {
KieAddressManager kieAddressManager = new KieAddressManager(
- Arrays.asList(KieConfig.INSTANCE.getServerUri().split(",")));
+ Arrays.asList(KieConfig.INSTANCE.getServerUri().split(",")), EventManager.getEventBus());
return kieAddressManager;
}
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java
index 2c23982..47fbd96 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java
@@ -213,17 +213,14 @@
private static void loadDataCenterInfo(MicroserviceInstance microserviceInstance) {
String dataCenterName = DynamicPropertyFactory.getInstance()
- .getStringProperty("servicecomb.datacenter.name", null)
+ .getStringProperty("servicecomb.datacenter.name", "default")
.get();
- if (StringUtils.isNotEmpty(dataCenterName)) {
- DataCenterInfo dataCenterInfo = new DataCenterInfo();
- dataCenterInfo.setName(dataCenterName);
- dataCenterInfo
- .setRegion(
- DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.datacenter.region", null).get());
- dataCenterInfo.setAvailableZone(
- DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.datacenter.availableZone", null).get());
- microserviceInstance.setDataCenterInfo(dataCenterInfo);
- }
+ DataCenterInfo dataCenterInfo = new DataCenterInfo();
+ dataCenterInfo.setName(dataCenterName);
+ dataCenterInfo.setRegion(DynamicPropertyFactory.getInstance().
+ getStringProperty("servicecomb.datacenter.region", "default").get());
+ dataCenterInfo.setAvailableZone(DynamicPropertyFactory.getInstance().
+ getStringProperty("servicecomb.datacenter.availableZone", "default").get());
+ microserviceInstance.setDataCenterInfo(dataCenterInfo);
}
}
diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java
index 99eadcf..d2e3eea 100644
--- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java
+++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java
@@ -18,67 +18,24 @@
package org.apache.servicecomb.huaweicloud.dashboard.monitor;
-import java.util.ArrayList;
import java.util.List;
-import org.apache.servicecomb.deployment.Deployment;
-import org.apache.servicecomb.deployment.SystemBootstrapInfo;
-import org.apache.servicecomb.foundation.common.event.EventManager;
-import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.http.client.common.AbstractAddressManager;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
-public class AddressManager {
- private static final String MONITOR_SERVICE_NAME = "CseMonitoring";
+public class AddressManager extends AbstractAddressManager {
- private static final String MONITOR_APPLICATION = "default";
-
- private static final String MONITOR_VERSION = "latest";
-
- private final List<String> addresses = new ArrayList<>();
-
- private int index = 0;
-
- AddressManager() {
- updateAddresses();
- updateServersFromSC();
- EventManager.register(this);
+ AddressManager(List<String> addresses, EventBus eventBus) {
+ super(addresses);
+ eventBus.register(this);
}
- private void updateAddresses() {
- SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(
- MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE);
- if (info != null && info.getAccessURL() != null) {
- addresses.addAll(info.getAccessURL());
- }
- }
-
- String nextServer() {
- if (addresses.size() == 0) {
- return null;
- }
- synchronized (this) {
- this.index++;
- if (this.index >= addresses.size()) {
- this.index = 0;
- }
- return addresses.get(index);
- }
- }
-
- private void updateServersFromSC() {
- List<MicroserviceInstance> servers = RegistryUtils.findServiceInstance(MONITOR_APPLICATION,
- MONITOR_SERVICE_NAME,
- MONITOR_VERSION);
- if (servers != null) {
- for (MicroserviceInstance server : servers) {
- for (String endpoint : server.getEndpoints()) {
- if (!addresses.contains(endpoint)) {
- addresses.add(endpoint);
- }
- }
- }
- }
+ @Subscribe
+ public void onRefreshEndpointEvent(RefreshEndpointEvent event) {
+ refreshEndpoint(event, RefreshEndpointEvent.CSE_MONITORING_NAME);
}
}
diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java
index 18ff61a..e3b5308 100644
--- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java
+++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java
@@ -17,9 +17,13 @@
package org.apache.servicecomb.huaweicloud.dashboard.monitor;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import org.apache.commons.io.IOUtils;
+import org.apache.servicecomb.deployment.Deployment;
+import org.apache.servicecomb.deployment.SystemBootstrapInfo;
import org.apache.servicecomb.foundation.auth.SignRequest;
import org.apache.servicecomb.foundation.common.event.EventManager;
import org.apache.servicecomb.foundation.common.net.IpPort;
@@ -67,7 +71,14 @@
@Override
public void init() {
try {
- addressManager = new AddressManager();
+ List<String> addresses = new ArrayList<>();
+ SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(
+ MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE);
+ if (info != null && info.getAccessURL() != null) {
+ addresses.addAll(info.getAccessURL());
+ }
+
+ addressManager = new AddressManager(addresses, EventManager.getEventBus());
deployMonitorClient();
} catch (Exception e) {
LOGGER.warn("Deploy monitor data publisher failed will not send monitor data.");
@@ -80,7 +91,7 @@
if (data == null) {
return;
}
- String endpoint = addressManager.nextServer();
+ String endpoint = addressManager.address();
if (endpoint == null) {
return;
}
@@ -110,6 +121,7 @@
}
return request.send(jsonData).compose(rsp -> {
if (rsp.statusCode() != HttpResponseStatus.OK.code()) {
+ addressManager.recordSuccessState(endpoint);
if (times < MonitorConstant.MAX_RETRY_TIMES
&& rsp.statusCode() == HttpResponseStatus.BAD_GATEWAY.code()) {
doSend(endpoint, jsonData, url, host, times + 1);
@@ -123,11 +135,13 @@
return Future.succeededFuture();
});
} else {
+ addressManager.recordSuccessState(endpoint);
EventManager.post(new MonitorSuccEvent());
}
return Future.succeededFuture();
}).onFailure(failure -> {
EventManager.post(new MonitorFailEvent("send monitor data fail."));
+ addressManager.recordFailState(endpoint);
LOGGER.warn("Send monitor data to {} failed , {}", endpoint, failure);
});
});
diff --git a/huawei-cloud/dashboard/src/test/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManagerTest.java b/huawei-cloud/dashboard/src/test/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManagerTest.java
new file mode 100644
index 0000000..79cbb6b
--- /dev/null
+++ b/huawei-cloud/dashboard/src/test/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManagerTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.huaweicloud.dashboard.monitor;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.eventbus.EventBus;
+
+import mockit.Deencapsulation;
+
+class AddressManagerTest {
+
+ private static List<String> addresses = new ArrayList<>();
+
+ private static AddressManager addressManager1;
+
+ @Test
+ public void kieAddressManagerTest() {
+ addresses.add("http://127.0.0.1:30103");
+ addresses.add("https://127.0.0.2:30103");
+ addressManager1 = new AddressManager(addresses, new EventBus());
+
+ Assert.assertNotNull(addressManager1);
+
+ List<String> addresses = Deencapsulation.getField(addressManager1, "addresses");
+ Assert.assertEquals(2, addresses.size());
+ Assert.assertEquals("http://127.0.0.1:30103", addresses.get(0));
+
+ Assert.assertEquals("https://127.0.0.2:30103", addressManager1.address());
+ Assert.assertEquals("http://127.0.0.1:30103", addressManager1.address());
+ }
+
+
+ @Test
+ public void onRefreshEndpointEvent() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.3:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("http://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ addressManager1 = new AddressManager(addresses, new EventBus());
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "CseMonitoring");
+ addressManager1.refreshEndpoint(event, "CseMonitoring");
+
+ List<String> availableZone = Deencapsulation.getField(addressManager1, "availableZone");
+ Assert.assertEquals("http://127.0.0.3:30100", availableZone.get(0));
+
+ List<String> availableRegion = Deencapsulation.getField(addressManager1, "availableRegion");
+ Assert.assertEquals("http://127.0.0.4:30100", availableRegion.get(0));
+ }
+}
\ No newline at end of file
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Const.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Const.java
index d2ff215..125d77a 100644
--- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Const.java
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Const.java
@@ -185,6 +185,12 @@
public static final String REGISTRY_SERVICE_NAME = "SERVICECENTER";
+ public static final String KIE_NAME = "KIE";
+
+ public static final String CONFIG_CENTER_NAME = "CseConfigCenter";
+
+ public static final String CSE_MONITORING_NAME = "CseMonitoring";
+
public static final String PATH_CHECKSESSION = "checksession";
public static final int SERVICE_CENTER_ORDER = 100;
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Type.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Type.java
new file mode 100644
index 0000000..d198f9f
--- /dev/null
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/Type.java
@@ -0,0 +1,25 @@
+/*
+ * 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.serviceregistry.api;
+
+public enum Type {
+ SERVICECENTER,
+ KIE,
+ CseConfigCenter,
+ CseMonitoring
+}
\ No newline at end of file
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/RBACBootStrapService.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/RBACBootStrapService.java
index c7a4914..80250ed 100644
--- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/RBACBootStrapService.java
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/RBACBootStrapService.java
@@ -27,6 +27,7 @@
import org.apache.servicecomb.foundation.auth.Cipher;
import org.apache.servicecomb.foundation.auth.DefaultCipher;
import org.apache.servicecomb.foundation.bootstrap.BootStrapService;
+import org.apache.servicecomb.foundation.common.event.EventManager;
import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils;
import org.apache.servicecomb.foundation.ssl.SSLCustom;
import org.apache.servicecomb.foundation.ssl.SSLOption;
@@ -91,7 +92,7 @@
private AddressManager createAddressManager(Environment environment) {
return new AddressManager(getTenantName(environment),
- getRBACAddressList(environment));
+ getRBACAddressList(environment), EventManager.getEventBus());
}
private SSLProperties createSSLProperties(Environment environment, String tag) {
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/IpPortManager.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/IpPortManager.java
index e9728bf..58aec33 100644
--- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/IpPortManager.java
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/IpPortManager.java
@@ -17,23 +17,19 @@
package org.apache.servicecomb.serviceregistry.client;
-import static org.apache.servicecomb.serviceregistry.api.Const.REGISTRY_APP_ID;
-import static org.apache.servicecomb.serviceregistry.api.Const.REGISTRY_SERVICE_NAME;
-
import java.util.ArrayList;
import java.util.List;
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import org.apache.servicecomb.foundation.common.event.EventManager;
import org.apache.servicecomb.foundation.common.net.IpPort;
-import org.apache.servicecomb.foundation.common.net.URIEndpointObject;
-import org.apache.servicecomb.registry.cache.CacheEndpoint;
-import org.apache.servicecomb.registry.cache.InstanceCache;
import org.apache.servicecomb.registry.cache.InstanceCacheManager;
import org.apache.servicecomb.registry.cache.InstanceCacheManagerNew;
import org.apache.servicecomb.registry.consumer.AppManager;
-import org.apache.servicecomb.registry.definition.DefinitionConst;
+import org.apache.servicecomb.serviceregistry.api.Type;
import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
+import org.apache.servicecomb.serviceregistry.refresh.AddressManager;
+import org.apache.servicecomb.serviceregistry.refresh.ClassificationAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -44,78 +40,52 @@
InstanceCacheManager instanceCacheManager;
- private String defaultTransport = "rest";
-
private ArrayList<IpPort> defaultIpPort;
- private AtomicInteger currentAvailableIndex;
-
private boolean autoDiscoveryInited = false;
- private int maxRetryTimes;
+ private AddressManager addressManger;
+
+ ClassificationAddress classificationAddress;
+
+ private Object lock = new Object();
public void setAutoDiscoveryInited(boolean autoDiscoveryInited) {
this.autoDiscoveryInited = autoDiscoveryInited;
}
public int getMaxRetryTimes() {
- return maxRetryTimes;
+ return classificationAddress.getMaxRetryTimes();
}
public IpPortManager(ServiceRegistryConfig serviceRegistryConfig) {
this.serviceRegistryConfig = serviceRegistryConfig;
this.instanceCacheManager = new InstanceCacheManagerNew(new AppManager());
-
- defaultTransport = serviceRegistryConfig.getTransport();
defaultIpPort = serviceRegistryConfig.getIpPort();
if (defaultIpPort.isEmpty()) {
throw new IllegalArgumentException("Service center address is required to start the application.");
}
- int initialIndex = new Random().nextInt(defaultIpPort.size());
- currentAvailableIndex = new AtomicInteger(initialIndex);
+ List<String> addresses = defaultIpPort.stream().map(IpPort::toString).collect(Collectors.toList());
+ addressManger = new AddressManager(addresses, EventManager.getEventBus());
+ classificationAddress = new ClassificationAddress(serviceRegistryConfig, instanceCacheManager);
LOGGER.info("Initial service center address is {}", getAvailableAddress());
- maxRetryTimes = defaultIpPort.size();
}
// we have to do this operation after the first time setup has already done
public void initAutoDiscovery() {
if (!autoDiscoveryInited && this.serviceRegistryConfig.isRegistryAutoDiscovery()) {
- InstanceCache cache = instanceCacheManager.getOrCreate(REGISTRY_APP_ID,
- REGISTRY_SERVICE_NAME,
- DefinitionConst.VERSION_RULE_LATEST);
- if (cache.getInstanceMap().size() > 0) {
- setAutoDiscoveryInited(true);
- } else {
- setAutoDiscoveryInited(false);
+ for (Type type : Type.values()) {
+ classificationAddress.initEndPoint(type.name());
}
+ setAutoDiscoveryInited(true);
}
}
public IpPort getAvailableAddress() {
- return getAvailableAddress(currentAvailableIndex.incrementAndGet());
+ return addressManger.getAvailableIpPort();
}
- private IpPort getAvailableAddress(int index) {
- if (index < defaultIpPort.size()) {
- return defaultIpPort.get(index);
- }
- List<CacheEndpoint> endpoints = getDiscoveredIpPort();
- if (endpoints == null || (index >= defaultIpPort.size() + endpoints.size())) {
- currentAvailableIndex.set(0);
- return defaultIpPort.get(0);
- }
- maxRetryTimes = defaultIpPort.size() + endpoints.size();
- CacheEndpoint nextEndpoint = endpoints.get(index - defaultIpPort.size());
- return new URIEndpointObject(nextEndpoint.getEndpoint());
- }
-
- private List<CacheEndpoint> getDiscoveredIpPort() {
- if (!autoDiscoveryInited || !this.serviceRegistryConfig.isRegistryAutoDiscovery()) {
- return null;
- }
- InstanceCache instanceCache = instanceCacheManager.getOrCreate(REGISTRY_APP_ID,
- REGISTRY_SERVICE_NAME,
- DefinitionConst.VERSION_RULE_LATEST);
- return instanceCache.getOrCreateTransportMap().get(defaultTransport);
+ public void recordState(String address) {
+ addressManger.recordFailState(address);
}
}
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
index 2735ab3..c94af37 100644
--- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/client/http/ServiceRegistryClientImpl.java
@@ -123,6 +123,7 @@
private void retry(RequestContext requestContext, Handler<RestResponse> responseHandler) {
String oldUri = requestContext.getIpPort().toString();
+ ipPortManager.recordState(oldUri);
requestContext.setIpPort(ipPortManager.getAvailableAddress());
String newUri = requestContext.getIpPort().toString();
LOGGER.warn("invoke service [{}] failed, retry address [{}].", oldUri, newUri);
@@ -290,6 +291,7 @@
}
break;
default:
+ ipPortManager.recordState(requestContext.getIpPort().toString());
LOGGER.warn("failed to findInstances: " + bodyBuffer.toString());
break;
}
@@ -672,6 +674,7 @@
response.setOk(true);
return response;
}
+ ipPortManager.recordState(ipPort.toString());
LOGGER.warn(holder.value.statusMessage());
return response;
}
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/refresh/AddressManager.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/refresh/AddressManager.java
new file mode 100644
index 0000000..fd1ce16
--- /dev/null
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/refresh/AddressManager.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.serviceregistry.refresh;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.foundation.common.net.IpPort;
+import org.apache.servicecomb.foundation.common.net.URIEndpointObject;
+import org.apache.servicecomb.http.client.common.AbstractAddressManager;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
+public class AddressManager extends AbstractAddressManager {
+
+ private static final String URI_SPLIT = ":";
+
+ public AddressManager(List<String> addresses, EventBus eventBus) {
+ super(addresses);
+ eventBus.register(this);
+ }
+
+ public IpPort getAvailableIpPort() {
+ return transformIpPort(this.address());
+ }
+
+ @Override
+ protected String normalizeUri(String endpoint) {
+ return new URIEndpointObject(endpoint).toString();
+ }
+
+ private IpPort transformIpPort(String address) {
+ String[] result = StringUtils.split(address, URI_SPLIT);
+ return new IpPort(result[0], Integer.valueOf(result[1]));
+ }
+
+ @Subscribe
+ public void onRefreshEndpointEvent(RefreshEndpointEvent event) {
+ refreshEndpoint(event, RefreshEndpointEvent.SERVICE_CENTER_NAME);
+ }
+}
diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/refresh/ClassificationAddress.java b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/refresh/ClassificationAddress.java
new file mode 100644
index 0000000..2c2ccda
--- /dev/null
+++ b/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/refresh/ClassificationAddress.java
@@ -0,0 +1,191 @@
+/*
+ * 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.serviceregistry.refresh;
+
+import static org.apache.servicecomb.serviceregistry.api.Const.CONFIG_CENTER_NAME;
+import static org.apache.servicecomb.serviceregistry.api.Const.CSE_MONITORING_NAME;
+import static org.apache.servicecomb.serviceregistry.api.Const.KIE_NAME;
+import static org.apache.servicecomb.serviceregistry.api.Const.REGISTRY_APP_ID;
+import static org.apache.servicecomb.serviceregistry.api.Const.REGISTRY_SERVICE_NAME;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.foundation.common.net.IpPort;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.apache.servicecomb.registry.RegistrationManager;
+import org.apache.servicecomb.registry.api.registry.DataCenterInfo;
+import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.registry.cache.CacheEndpoint;
+import org.apache.servicecomb.registry.cache.InstanceCache;
+import org.apache.servicecomb.registry.cache.InstanceCacheManager;
+import org.apache.servicecomb.registry.definition.DefinitionConst;
+import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
+import org.apache.servicecomb.serviceregistry.event.ServiceCenterEventBus;
+import org.apache.servicecomb.serviceregistry.registry.cache.MicroserviceCache;
+import org.apache.servicecomb.serviceregistry.registry.cache.MicroserviceCacheRefreshedEvent;
+
+import com.google.common.eventbus.Subscribe;
+
+public class ClassificationAddress {
+
+ private static final String SC_KEY = "SERVICECENTER@default@@0.0.0.0+";
+
+ private static final String CC_KEY = "CseConfigCenter@default@@0.0.0.0+";
+
+ private static final String KIE_KEY = "KIE@default@@0.0.0.0+";
+
+ private static final String MONITORING_KEY = "CseMonitoring@default@@0.0.0.0+";
+
+ private String defaultTransport = "rest";
+
+ private DataCenterInfo dataCenterInfo;
+
+ InstanceCacheManager instanceCacheManager;
+
+ private ArrayList<IpPort> defaultIpPort;
+
+ private int maxRetryTimes;
+
+ public ClassificationAddress(ServiceRegistryConfig serviceRegistryConfig, InstanceCacheManager instanceCacheManager) {
+ this.defaultTransport = serviceRegistryConfig.getTransport();
+ this.defaultIpPort = serviceRegistryConfig.getIpPort();
+ this.instanceCacheManager = instanceCacheManager;
+ this.maxRetryTimes = defaultIpPort.size();
+ ServiceCenterEventBus.getEventBus().register(this);
+ }
+
+ public void initEndPoint(String typeName) {
+ Map<String, List<String>> zoneAndRegion = generateZoneAndRegionAddress(typeName);
+ if (zoneAndRegion == null) {
+ return;
+ }
+ EventManager.post(new RefreshEndpointEvent(zoneAndRegion, typeName));
+ }
+
+ @Subscribe
+ public void onMicroserviceCacheRefreshed(MicroserviceCacheRefreshedEvent event) {
+ List<MicroserviceCache> microserviceCaches = event.getMicroserviceCaches();
+ if (null == microserviceCaches || microserviceCaches.isEmpty()) {
+ return;
+ }
+
+ for (MicroserviceCache microserviceCache : microserviceCaches) {
+ if (microserviceCache.getKey().toString().equals(SC_KEY)) {
+ refreshEndPoints(microserviceCache, REGISTRY_SERVICE_NAME);
+ }
+ if (microserviceCache.getKey().toString().equals(CC_KEY)) {
+ refreshEndPoints(microserviceCache, KIE_NAME);
+ }
+ if (microserviceCache.getKey().toString().equals(KIE_KEY)) {
+ refreshEndPoints(microserviceCache, CONFIG_CENTER_NAME);
+ }
+ if (microserviceCache.getKey().toString().equals(MONITORING_KEY)) {
+ refreshEndPoints(microserviceCache, CSE_MONITORING_NAME);
+ }
+ }
+ }
+
+ private void refreshEndPoints(MicroserviceCache microserviceCache, String name) {
+ Map<String, List<String>> zoneAndRegion = refreshEndPoint(microserviceCache);
+ EventManager.post(new RefreshEndpointEvent(zoneAndRegion, name));
+ }
+
+ private Map<String, List<String>> refreshEndPoint(MicroserviceCache microserviceCache) {
+ List<String> sameZone = new ArrayList<>();
+ List<String> sameRegion = new ArrayList<>();
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+
+ List<MicroserviceInstance> microserviceCacheInstances = microserviceCache.getInstances();
+
+ microserviceCacheInstances.forEach(microserviceInstance -> {
+ String endPoint = microserviceInstance.getEndpoints().get(0);
+ if (regionAndAZMatch(dataCenterInfo, microserviceInstance)) {
+ sameZone.add(endPoint);
+ } else {
+ sameRegion.add(endPoint);
+ }
+ });
+ zoneAndRegion.put("sameZone", sameZone);
+ zoneAndRegion.put("sameRegion", sameRegion);
+ return zoneAndRegion;
+ }
+
+ private Map<String, List<String>> generateZoneAndRegionAddress(String key) {
+ InstanceCache KieCaches = instanceCacheManager
+ .getOrCreate(REGISTRY_APP_ID, key, DefinitionConst.VERSION_RULE_LATEST);
+ List<CacheEndpoint> CacheEndpoints = new ArrayList<>();
+ if (REGISTRY_SERVICE_NAME.equals(key)) {
+ CacheEndpoints = KieCaches.getOrCreateTransportMap().get(defaultTransport);
+ maxRetryTimes = CacheEndpoints.size();
+ } else {
+ if (KieCaches.getInstanceMap().size() <= 0) {
+ return null;
+ }
+ CacheEndpoints = KieCaches.getOrCreateTransportMap().get(defaultTransport);
+ }
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ dataCenterInfo = findRegion(CacheEndpoints);
+
+ List<String> sameZone = new ArrayList<>();
+ List<String> sameRegion = new ArrayList<>();
+ for (CacheEndpoint cacheEndpoint : CacheEndpoints) {
+ if (regionAndAZMatch(dataCenterInfo, cacheEndpoint.getInstance())) {
+ sameZone.add(cacheEndpoint.getEndpoint());
+ } else {
+ sameRegion.add(cacheEndpoint.getEndpoint());
+ }
+ }
+ zoneAndRegion.put("sameZone", sameZone);
+ zoneAndRegion.put("sameRegion", sameRegion);
+ return zoneAndRegion;
+ }
+
+ private DataCenterInfo findRegion(List<CacheEndpoint> CacheEndpoints) {
+ MicroserviceInstance myself = RegistrationManager.INSTANCE.getMicroserviceInstance();
+ if (myself.getDataCenterInfo() == null) {
+ return null;
+ }
+ for (CacheEndpoint cacheEndpoint : CacheEndpoints) {
+ boolean isMatch = cacheEndpoint.getEndpoint().contains(this.defaultIpPort.get(0).getHostOrIp());
+ if (isMatch && cacheEndpoint.getInstance().getDataCenterInfo() != null) {
+ return cacheEndpoint.getInstance().getDataCenterInfo();
+ }
+ }
+ return null;
+ }
+
+ private boolean regionAndAZMatch(DataCenterInfo myself, MicroserviceInstance target) {
+ if (myself == null) {
+ // when instance have no datacenter info, it will match all other datacenters
+ return true;
+ }
+ if (target.getDataCenterInfo() != null) {
+ return myself.getRegion().equals(target.getDataCenterInfo().getRegion()) &&
+ myself.getAvailableZone().equals(target.getDataCenterInfo().getAvailableZone());
+ }
+ return false;
+ }
+
+ public int getMaxRetryTimes() {
+ return maxRetryTimes;
+ }
+}
diff --git a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/TestIpPortManager.java b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/TestIpPortManager.java
index 11c9b85..68ca58f 100644
--- a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/TestIpPortManager.java
+++ b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/client/TestIpPortManager.java
@@ -24,12 +24,14 @@
import org.apache.servicecomb.config.ConfigUtil;
import org.apache.servicecomb.foundation.common.net.IpPort;
+import org.apache.servicecomb.registry.RegistrationManager;
import org.apache.servicecomb.serviceregistry.RegistryUtils;
import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
import org.apache.servicecomb.registry.cache.CacheEndpoint;
import org.apache.servicecomb.registry.cache.InstanceCache;
import org.apache.servicecomb.registry.cache.InstanceCacheManager;
import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig;
+import org.apache.servicecomb.serviceregistry.refresh.ClassificationAddress;
import org.apache.servicecomb.serviceregistry.registry.AbstractServiceRegistry;
import org.apache.servicecomb.serviceregistry.registry.LocalServiceRegistryFactory;
import org.junit.Assert;
@@ -59,7 +61,8 @@
@Test
public void testGetAvailableAddress(@Injectable ServiceRegistryConfig config,
@Injectable InstanceCacheManager cacheManager,
- @Injectable InstanceCache cache) {
+ @Injectable InstanceCache cache,
+ @Injectable ClassificationAddress classificationAddress) {
ArrayList<IpPort> ipPortList = new ArrayList<>();
ipPortList.add(new IpPort("127.0.0.1", 9980));
ipPortList.add(new IpPort("127.0.0.1", 9981));
@@ -102,6 +105,8 @@
List<CacheEndpoint> instances = new ArrayList<>();
instances.add(new CacheEndpoint("http://127.0.0.1:9982", null));
addresses.put("rest", instances);
+ ClassificationAddress classificationAddres = new ClassificationAddress(config, cacheManager);
+ manager.classificationAddress =classificationAddres;
new Expectations() {
{
cacheManager.getOrCreate("default", "SERVICECENTER", "latest");
@@ -112,7 +117,6 @@
};
// test getAvailableAddress() when auto discovery is disabled
- manager.initAutoDiscovery(); //init result is false at first time
IpPort address4 = manager.getAvailableAddress();
Assert.assertEquals("127.0.0.1", address4.getHostOrIp());
if (address1.getPort() == 9980) {
@@ -120,12 +124,25 @@
}
Assert.assertEquals(9980, address4.getPort());
- // test getAvailable address when auto discovery is enabled
- manager.setAutoDiscoveryInited(true);
IpPort address5 = manager.getAvailableAddress();
Assert.assertEquals("127.0.0.1", address5.getHostOrIp());
Assert.assertEquals(9981, address5.getPort());
+ //mock RegistrationManager.INSTANCE
+ String instanceId = "e8a04b54cf2711e7b701286ed488fc20";
+ MicroserviceInstance microserviceInstance = new MicroserviceInstance();
+ microserviceInstance.setInstanceId(instanceId);
+ Map<String, String> properties = new HashMap<>();
+ microserviceInstance.setProperties(properties);
+ new Expectations(RegistrationManager.INSTANCE) {
+ {
+ RegistrationManager.INSTANCE.getMicroserviceInstance();
+ result = microserviceInstance;
+ }
+ };
+ // test getAvailable address when auto discovery is enabled
+ manager.initAutoDiscovery();
+ manager.setAutoDiscoveryInited(true);
IpPort address6 = manager.getAvailableAddress();
Assert.assertEquals("127.0.0.1", address6.getHostOrIp());
Assert.assertEquals(9982, address6.getPort());
diff --git a/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/refresh/AddressManagerTest.java b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/refresh/AddressManagerTest.java
new file mode 100644
index 0000000..a81a56c
--- /dev/null
+++ b/service-registry/registry-service-center/src/test/java/org/apache/servicecomb/serviceregistry/refresh/AddressManagerTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.serviceregistry.refresh;
+
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.foundation.common.net.IpPort;
+import org.apache.servicecomb.http.client.event.RefreshEndpointEvent;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.eventbus.EventBus;
+
+import mockit.Deencapsulation;
+
+class AddressManagerTest {
+
+ private static List<String> addresses = new ArrayList<>();
+
+ private static AddressManager addressManager1;
+
+ private static AddressManager addressManager2;
+
+ @Test
+ public void addressManagerTest() {
+ IpPort ipPort = new IpPort("127.0.0.1", 30103);
+ addresses.add(ipPort.toString());
+ addressManager1 = new AddressManager(addresses, new EventBus());
+ addressManager2 = new AddressManager(addresses, new EventBus());
+
+ Assert.assertNotNull(addressManager1);
+ Assert.assertNotNull(addressManager2);
+
+ List<String> addresses = Deencapsulation.getField(addressManager1, "addresses");
+ Assert.assertEquals(1, addresses.size());
+ Assert.assertEquals("127.0.0.1:30103", addresses.get(0));
+ Assert.assertEquals("127.0.0.1:30103", addressManager1.address());
+
+ ipPort = addressManager2.getAvailableIpPort();
+ Assert.assertEquals("127.0.0.1:30103", ipPort.toString());
+ Assert.assertEquals("127.0.0.1", ipPort.getHostOrIp());
+ Assert.assertEquals(30103, ipPort.getPort());
+ }
+
+ @Test
+ public void onRefreshEndpointEvent() {
+ List<String> addressAZ = new ArrayList<>();
+ addressAZ.add("http://127.0.0.3:30100");
+ List<String> addressRG = new ArrayList<>();
+ addressRG.add("https://127.0.0.4:30100");
+ Map<String, List<String>> zoneAndRegion = new HashMap<>();
+ zoneAndRegion.put("sameZone", addressAZ);
+ zoneAndRegion.put("sameRegion", addressRG);
+ addressManager1 = new AddressManager(addresses, new EventBus());
+ RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "SERVICECENTER");
+ addressManager1.refreshEndpoint(event, "SERVICECENTER");
+
+ List<String> availableZone = Deencapsulation.getField(addressManager1, "availableZone");
+ Assert.assertEquals("127.0.0.3:30100", availableZone.get(0));
+
+ List<String> availableRegion = Deencapsulation.getField(addressManager1, "availableRegion");
+ Assert.assertEquals("127.0.0.4:30100", availableRegion.get(0));
+ }
+}
\ No newline at end of file