This is an automated email from the ASF dual-hosted git repository.
hefengen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 0dca04348e [BUG #5268] Fix bug when registering with Eureka through
EurekaInstanceRegisterRepository#persistInstance. (#5269)
0dca04348e is described below
commit 0dca04348e9ce92707e247870342e95124968191
Author: Shawn Jim <[email protected]>
AuthorDate: Mon Nov 6 15:19:04 2023 +0800
[BUG #5268] Fix bug when registering with Eureka through
EurekaInstanceRegisterRepository#persistInstance. (#5269)
* [BUG #5268] Fix the abnormal status when registering with Eureka through
EurekaInstanceRegisterRepository#persistInstance.
* [BUG #5268] Refactor some code for review.
---------
Co-authored-by: ShawnJim <[email protected]>
Co-authored-by: moremind <[email protected]>
---
.../eureka/EurekaInstanceRegisterRepository.java | 130 ++++++++++++++++-----
.../EurekaInstanceRegisterRepositoryTest.java | 70 ++++++-----
2 files changed, 137 insertions(+), 63 deletions(-)
diff --git
a/shenyu-registry/shenyu-registry-eureka/src/main/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepository.java
b/shenyu-registry/shenyu-registry-eureka/src/main/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepository.java
index e87b0d694e..2960078622 100644
---
a/shenyu-registry/shenyu-registry-eureka/src/main/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepository.java
+++
b/shenyu-registry/shenyu-registry-eureka/src/main/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepository.java
@@ -21,18 +21,15 @@ import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
-import com.netflix.appinfo.MyDataCenterInfo;
+import com.netflix.appinfo.LeaseInfo;
import com.netflix.appinfo.MyDataCenterInstanceConfig;
-import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
-import com.netflix.config.ConfigurationManager;
+import com.netflix.appinfo.RefreshableInstanceConfig;
+import com.netflix.appinfo.UniqueIdentifier;
+import com.netflix.appinfo.providers.Archaius1VipAddressResolver;
import com.netflix.discovery.DefaultEurekaClientConfig;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClient;
-import com.netflix.discovery.shared.transport.EurekaHttpClient;
-import com.netflix.discovery.shared.transport.EurekaHttpResponse;
-import com.netflix.discovery.shared.transport.jersey.JerseyApplicationClient;
-import com.sun.jersey.client.apache4.ApacheHttpClient4;
-import org.apache.shenyu.common.utils.IpUtils;
+import org.apache.commons.lang.StringUtils;
import org.apache.shenyu.registry.api.ShenyuInstanceRegisterRepository;
import org.apache.shenyu.registry.api.config.RegisterConfig;
import org.apache.shenyu.registry.api.entity.InstanceEntity;
@@ -40,7 +37,9 @@ import org.apache.shenyu.spi.Join;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Arrays;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
@Join
@@ -50,36 +49,113 @@ public class EurekaInstanceRegisterRepository implements
ShenyuInstanceRegisterR
private EurekaClient eurekaClient;
- private EurekaHttpClient eurekaHttpClient;
+ private DefaultEurekaClientConfig eurekaClientConfig;
+
+ private EurekaInstanceConfig eurekaInstanceConfig;
@Override
public void init(final RegisterConfig config) {
-
ConfigurationManager.getConfigInstance().setProperty("eureka.client.service-url.defaultZone",
config.getServerLists());
-
ConfigurationManager.getConfigInstance().setProperty("eureka.serviceUrl.default",
config.getServerLists());
- ApplicationInfoManager applicationInfoManager =
initializeApplicationInfoManager(new MyDataCenterInstanceConfig());
- eurekaClient = new DiscoveryClient(applicationInfoManager, new
DefaultEurekaClientConfig());
- eurekaHttpClient = new JerseyApplicationClient(new
ApacheHttpClient4(), config.getServerLists(), null);
- }
-
- private ApplicationInfoManager initializeApplicationInfoManager(final
EurekaInstanceConfig instanceConfig) {
- InstanceInfo instanceInfo = new
EurekaConfigBasedInstanceInfoProvider(instanceConfig).get();
- return new ApplicationInfoManager(instanceConfig, instanceInfo);
+ eurekaInstanceConfig = new MyDataCenterInstanceConfig();
+ eurekaClientConfig = new DefaultEurekaClientConfig() {
+ @Override
+ public List<String> getEurekaServerServiceUrls(final String zone) {
+ return Arrays.asList(config.getServerLists().split(","));
+ }
+ };
}
@Override
public void persistInstance(final InstanceEntity instance) {
- EurekaHttpResponse<Void> register =
eurekaHttpClient.register(generateInstanceInfo(instance));
- LOGGER.info("eureka client register success: {}",
register.getEntity());
- }
-
- private InstanceInfo generateInstanceInfo(final InstanceEntity instance) {
- return InstanceInfo.Builder.newBuilder()
+ InstanceInfo.Builder instanceInfoBuilder = instanceInfoBuilder();
+ InstanceInfo instanceInfo = instanceInfoBuilder
.setAppName(instance.getAppName())
- .setIPAddr(IpUtils.getHost())
+ .setIPAddr(instance.getHost())
.setHostName(instance.getHost())
.setPort(instance.getPort())
- .setDataCenterInfo(new
MyDataCenterInfo(DataCenterInfo.Name.MyOwn))
+ .setStatus(InstanceInfo.InstanceStatus.UP)
.build();
+ LeaseInfo.Builder leaseInfoBuilder = LeaseInfo.Builder.newBuilder()
+
.setRenewalIntervalInSecs(eurekaInstanceConfig.getLeaseRenewalIntervalInSeconds())
+
.setDurationInSecs(eurekaInstanceConfig.getLeaseExpirationDurationInSeconds());
+ instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
+ ApplicationInfoManager applicationInfoManager = new
ApplicationInfoManager(eurekaInstanceConfig, instanceInfo);
+ eurekaClient = new DiscoveryClient(applicationInfoManager,
eurekaClientConfig);
+ }
+
+ /**
+ * Gets the instance information from the config instance and returns it
after setting the appropriate status.
+ * ref:
com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider#get
+ *
+ * @return InstanceInfo instance to be registered with eureka server
+ */
+ public InstanceInfo.Builder instanceInfoBuilder() {
+ // Builder the instance information to be registered with eureka server
+ final InstanceInfo.Builder builder =
InstanceInfo.Builder.newBuilder(new Archaius1VipAddressResolver());
+
+ // set the appropriate id for the InstanceInfo, falling back to
datacenter Id if applicable, else hostname
+ String instanceId = eurekaInstanceConfig.getInstanceId();
+ if (StringUtils.isEmpty(instanceId)) {
+ DataCenterInfo dataCenterInfo =
eurekaInstanceConfig.getDataCenterInfo();
+ if (dataCenterInfo instanceof UniqueIdentifier) {
+ instanceId = ((UniqueIdentifier) dataCenterInfo).getId();
+ } else {
+ instanceId = eurekaInstanceConfig.getHostName(false);
+ }
+ }
+
+ String defaultAddress;
+ if (eurekaInstanceConfig instanceof RefreshableInstanceConfig) {
+ // Refresh AWS data center info, and return up to date address
+ defaultAddress = ((RefreshableInstanceConfig)
eurekaInstanceConfig).resolveDefaultAddress(false);
+ } else {
+ defaultAddress = eurekaInstanceConfig.getHostName(false);
+ }
+
+ // fail safe
+ if (StringUtils.isEmpty(defaultAddress)) {
+ defaultAddress = eurekaInstanceConfig.getIpAddress();
+ }
+
+ builder.setNamespace(eurekaInstanceConfig.getNamespace())
+ .setInstanceId(instanceId)
+ .setAppName(eurekaInstanceConfig.getAppname())
+ .setAppGroupName(eurekaInstanceConfig.getAppGroupName())
+ .setDataCenterInfo(eurekaInstanceConfig.getDataCenterInfo())
+ .setIPAddr(eurekaInstanceConfig.getIpAddress())
+ .setHostName(defaultAddress)
+ .setPort(eurekaInstanceConfig.getNonSecurePort())
+ .enablePort(InstanceInfo.PortType.UNSECURE,
eurekaInstanceConfig.isNonSecurePortEnabled())
+ .setSecurePort(eurekaInstanceConfig.getSecurePort())
+ .enablePort(InstanceInfo.PortType.SECURE,
eurekaInstanceConfig.getSecurePortEnabled())
+ .setVIPAddress(eurekaInstanceConfig.getVirtualHostName())
+
.setSecureVIPAddress(eurekaInstanceConfig.getSecureVirtualHostName())
+ .setHomePageUrl(eurekaInstanceConfig.getHomePageUrlPath(),
eurekaInstanceConfig.getHomePageUrl())
+ .setStatusPageUrl(eurekaInstanceConfig.getStatusPageUrlPath(),
eurekaInstanceConfig.getStatusPageUrl())
+ .setASGName(eurekaInstanceConfig.getASGName())
+
.setHealthCheckUrls(eurekaInstanceConfig.getHealthCheckUrlPath(),
+ eurekaInstanceConfig.getHealthCheckUrl(),
eurekaInstanceConfig.getSecureHealthCheckUrl());
+
+ // Start off with the STARTING state to avoid traffic
+ if (!eurekaInstanceConfig.isInstanceEnabledOnit()) {
+ InstanceInfo.InstanceStatus initialStatus =
InstanceInfo.InstanceStatus.STARTING;
+ LOGGER.info("Setting initial instance status as: {}",
initialStatus);
+ builder.setStatus(initialStatus);
+ } else {
+ LOGGER.info("Setting initial instance status as: {}. This may be
too early for the instance to advertise "
+ + "itself as available. You would instead want to
control this via a healthcheck handler.",
+ InstanceInfo.InstanceStatus.UP);
+ }
+
+ // Add any user-specific metadata information
+ for (Map.Entry<String, String> mapEntry :
eurekaInstanceConfig.getMetadataMap().entrySet()) {
+ String key = mapEntry.getKey();
+ String value = mapEntry.getValue();
+ // only add the metadata if the value is present
+ if (StringUtils.isNotEmpty(value)) {
+ builder.add(key, value);
+ }
+ }
+ return builder;
}
@Override
diff --git
a/shenyu-registry/shenyu-registry-eureka/src/test/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepositoryTest.java
b/shenyu-registry/shenyu-registry-eureka/src/test/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepositoryTest.java
index e54be5a728..6e963a1544 100644
---
a/shenyu-registry/shenyu-registry-eureka/src/test/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepositoryTest.java
+++
b/shenyu-registry/shenyu-registry-eureka/src/test/java/org/apache/shenyu/registry/eureka/EurekaInstanceRegisterRepositoryTest.java
@@ -21,12 +21,12 @@ import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaEventListener;
-import com.netflix.discovery.shared.transport.EurekaHttpClient;
-import com.netflix.discovery.shared.transport.EurekaHttpResponse;
-import com.netflix.discovery.shared.transport.jersey.JerseyApplicationClient;
+import org.apache.shenyu.registry.api.config.RegisterConfig;
import org.apache.shenyu.registry.api.entity.InstanceEntity;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
import java.lang.reflect.Field;
import java.util.HashMap;
@@ -34,20 +34,22 @@ import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
public final class EurekaInstanceRegisterRepositoryTest {
private EurekaInstanceRegisterRepository repository;
- private final String instanceId = "shenyu-instances";
+ private final InstanceEntity instance = new
InstanceEntity("shenyu-instances", "shenyu-host", 9195);
private final Map<String, InstanceInfo> instanceStorage = new HashMap<>();
private final Map<String, EurekaEventListener> eurekaEventStorage = new
HashMap<>();
+ private MockedConstruction<DiscoveryClient>
discoveryClientMockedConstruction;
+
@BeforeEach
public void setUp() throws Exception {
repository = new EurekaInstanceRegisterRepository();
@@ -57,19 +59,26 @@ public final class EurekaInstanceRegisterRepositoryTest {
eurekaClientField.setAccessible(true);
eurekaClientField.set(repository, mockEurekaClient());
- Field eurekaHttpClientField =
clazz.getDeclaredField("eurekaHttpClient");
- eurekaHttpClientField.setAccessible(true);
- eurekaHttpClientField.set(repository, mockEurekaHttpClient());
+ RegisterConfig registerConfig = new RegisterConfig();
+ registerConfig.setServerLists("");
+ repository.init(registerConfig);
+
+ // mock the function discoveryClient#register().
+ discoveryClientMockedConstruction =
mockConstruction(DiscoveryClient.class, (mock, context) -> {
+ InstanceInfo.Builder builder = repository.instanceInfoBuilder();
+ builder.setAppName(instance.getAppName())
+ .setIPAddr(instance.getHost())
+ .setHostName(instance.getHost())
+ .setPort(instance.getPort())
+ .setStatus(InstanceInfo.InstanceStatus.UP);
+ InstanceInfo instanceInfo = builder.build();
+ instanceStorage.put(instanceInfo.getAppName(), instanceInfo);
+ });
}
private EurekaClient mockEurekaClient() {
DiscoveryClient discoveryClient = mock(DiscoveryClient.class);
- doAnswer(invocationOnMock -> {
- eurekaEventStorage.put(instanceId,
invocationOnMock.getArgument(0));
- return null;
- }).when(discoveryClient).registerEventListener(any());
-
doAnswer(invocationOnMock -> {
eurekaEventStorage.clear();
return null;
@@ -78,36 +87,25 @@ public final class EurekaInstanceRegisterRepositoryTest {
return discoveryClient;
}
- private EurekaHttpClient mockEurekaHttpClient() {
- EurekaHttpClient eurekaHttpClient =
mock(JerseyApplicationClient.class);
- doAnswer(invocationOnMock -> {
- InstanceInfo instanceInfo = invocationOnMock.getArgument(0);
- instanceStorage.put(instanceInfo.getAppName(), instanceInfo);
- return EurekaHttpResponse.anEurekaHttpResponse(204, "response
success")
- .build();
- }).when(eurekaHttpClient).register(any());
- return eurekaHttpClient;
- }
-
@Test
public void persistInstance() {
- InstanceEntity data = InstanceEntity.builder()
- .appName(instanceId)
- .host("shenyu-host")
- .port(9195)
- .build();
- repository.persistInstance(data);
-
assertTrue(instanceStorage.containsKey(data.getAppName().toUpperCase()));
- InstanceInfo instanceInfo =
instanceStorage.get(data.getAppName().toUpperCase());
- assertEquals(data.getHost(), instanceInfo.getHostName());
- assertEquals(data.getPort(), instanceInfo.getPort());
- assertEquals(data.getAppName().toUpperCase(),
instanceInfo.getAppName());
+ repository.persistInstance(instance);
+
assertTrue(instanceStorage.containsKey(instance.getAppName().toUpperCase()));
+ InstanceInfo instanceInfo =
instanceStorage.get(instance.getAppName().toUpperCase());
+ assertEquals(instance.getHost(), instanceInfo.getHostName());
+ assertEquals(instance.getPort(), instanceInfo.getPort());
+ assertEquals(instance.getAppName().toUpperCase(),
instanceInfo.getAppName());
}
@Test
public void testSelectInstancesAndWatcher() {
- repository.selectInstances(instanceId);
+ repository.selectInstances(instance.getAppName());
repository.close();
assertTrue(eurekaEventStorage.isEmpty());
}
+
+ @AfterEach
+ public void clear() {
+ discoveryClientMockedConstruction.close();
+ }
}