Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement semaphore synchronization to prevent concurrent modificatio…issue#4094 #4301

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the date in the license comment to 2013-2024.


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
import org.springframework.boot.actuate.health.StatusAggregator;
Expand All @@ -35,6 +34,8 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.Semaphore;

/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add your full name with @author tag to the javadoc of the class.

* @author Dave Syer
* @author Spencer Gibb
Expand All @@ -51,52 +52,100 @@
@ConditionalOnBlockingDiscoveryEnabled
public class EurekaDiscoveryClientConfiguration {

@Bean
@ConditionalOnMissingBean
public EurekaDiscoveryClient discoveryClient(EurekaClient client, EurekaClientConfig clientConfig) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you've changed formatting - as a result it shows as if you've modified all these lines of code. Please revert to our formatting (possibly a spaces/ tabs issue) so that it's clearly visible in the diff what code has been changed by you.

return new EurekaDiscoveryClient(client, clientConfig);
}

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
protected static class EurekaHealthCheckHandlerConfiguration {

@Autowired(required = false)
private StatusAggregator statusAggregator = new SimpleStatusAggregator();

@Bean
@ConditionalOnMissingBean(HealthCheckHandler.class)
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
return new EurekaHealthCheckHandler(this.statusAggregator);
}

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScopeRefreshedEvent.class)
protected static class EurekaClientConfigurationRefresher
implements ApplicationListener<RefreshScopeRefreshedEvent> {

@Autowired(required = false)
private EurekaClient eurekaClient;

@Autowired(required = false)
private EurekaAutoServiceRegistration autoRegistration;

public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
// This will force the creation of the EurekaClient bean if not already
// created
// to make sure the client will be re-registered after a refresh event
if (eurekaClient != null) {
eurekaClient.getApplications();
}
if (autoRegistration != null) {
// register in case meta data changed
this.autoRegistration.stop();
this.autoRegistration.start();
}
}

}
@Bean
@ConditionalOnMissingBean
public EurekaDiscoveryClient discoveryClient(EurekaClient client, EurekaClientConfig clientConfig) {
return new EurekaDiscoveryClient(client, clientConfig);
}

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "eureka.client.healthcheck.enabled", matchIfMissing = false)
protected static class EurekaHealthCheckHandlerConfiguration {

@Autowired(required = false)
private StatusAggregator statusAggregator = new SimpleStatusAggregator();

@Bean
@ConditionalOnMissingBean(HealthCheckHandler.class)
public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
return new EurekaHealthCheckHandler(this.statusAggregator);
}

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScopeRefreshedEvent.class)
protected static class EurekaClientConfigurationRefresher
implements ApplicationListener<RefreshScopeRefreshedEvent> {

private final Semaphore semaphore = new Semaphore(1);

@Autowired(required = false)
private EurekaClient eurekaClient;

@Autowired(required = false)
private EurekaAutoServiceRegistration autoRegistration;

public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
try {
semaphore.acquire();
if (eurekaClient != null) {
eurekaClient.getApplications();
}
if (autoRegistration != null) {
// deregister instance
this.autoRegistration.stop();
// register instance
this.autoRegistration.start();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}

}

@Configuration(proxyBeanMethods = false)
protected static class DiscoveryClientConfiguration {

private final Semaphore semaphore = new Semaphore(1);

@Autowired
private ApplicationInfoManager applicationInfoManager;

@Autowired
private HealthCheckHandler healthCheckHandler;

@Autowired
private InstanceInfo instanceInfo;

void refreshInstanceInfo() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this method is not ever used - please verify and finish up your changes, and then request another review.

try {
semaphore.acquire();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use binary semaphore rather than a ReentrantLock?

applicationInfoManager.refreshDataCenterInfoIfRequired();
applicationInfoManager.refreshLeaseInfoIfRequired();

InstanceStatus status;
try {
// get instance status
status = healthCheckHandler.getStatus(instanceInfo.getStatus());
} catch (Exception e) {
logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", e);
status = InstanceStatus.DOWN;
}

if (null != status) {
// modify instance status
applicationInfoManager.setInstanceStatus(status);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
}
}

}
Loading