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();
+    }
 }

Reply via email to