Eureka Source Code Analysis: Self-Preservation Mechanism

Core Architecture Overview The self-preservation mechanism in Eureka Server is designed to handle network instability and prevent healthy services from being prematurely removed during communication failures.

Mechanism Behavior Eureka Server continuously monitors heartbeat success rates over 15-minute intervals. If the failure rate exceeds 15% (success rate drops below 85%), the server assumes network issues are affecting client communication. During this state:

Existing healthy instances are protected from expiration
New service registrations and queries are still accepted
Updates are not synchronized to other nodes to maintain local availability

Configuration Example

Demo configuration for sync failure scenarios

eureka.server.wait-time-in-ms-when-sync-empty=10000

Key Variables Two critical variables in AbstractInstanceRegistry: protected volatile int renewalThreshold; // Minimum expected renewals per minute protected volatile int expectedRenewalClients; // Expected number of clients sending renewals

Threshold Calculation

private void calculateRenewalThreshold() {
    this.renewalThreshold = (int) (this.expectedRenewalClients 
            * (60.0 / serverConfig.getClientRenewalInterval()) 
            * serverConfig.getRenewalPercentageThreshold());
}

Default client renewal interval: 30 seconds
Default threshold factor: 0.85 (85% minimum renewal requirement)

Variable Update Points

Server Initialization

protected void initializeServerContext() throws Exception {
    EurekaServerConfig config = new DefaultEurekaServerConfig();
    registry.activateTraffic(applicationManager, instanceCount);
}

Traffic Activation

public void activateTraffic(ApplicationManager manager, int count) {
    this.expectedRenewalClients = count;
    calculateRenewalThreshold();
    // Additional initialization logic
}

Instance Removal

protected boolean removeInstance(String appName, String id, boolean replication) {
    synchronized (lock) {
        if (this.expectedRenewalClients > 0) {
            this.expectedRenewalClients--;
            calculateRenewalThreshold();
        }
    }
    return true;
}

New Registration

public void register(InstanceInfo info, int leaseDuration, boolean replication) {
    synchronized (lock) {
        if (this.expectedRenewalClients > 0) {
            this.expectedRenewalClients++;
            calculateRenewalThreshold();
        }
    }
    // Additional registration logic
}

Periodic Threshold Update

private void scheduleThresholdUpdate() {
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            refreshThreshold();
        }
    }, serverConfig.getThresholdUpdateInterval(), 
      serverConfig.getThresholdUpdateInterval());
}

Self-Preservation Task

protected void finalizeInitialization() {
    renewalMonitor.start();
    if (evictionTask.get() != null) {
        evictionTask.get().cancel();
    }
    evictionTask.set(new CleanupTask());
    evictionTimer.schedule(evictionTask.get(),
            serverConfig.getCleanupInterval(),
            serverConfig.getCleanupInterval());
}

Cleanup Logic

private final AtomicLong lastRunNanos = new AtomicLong(0l);

@Override
public void run() {
    try {
        long adjustmentTime = getAdjustmentTime();
        performCleanup(adjustmentTime);
    } catch (Throwable e) {
        logger.error("Cleanup execution failed", e);
    }
}

Expiration Control

public boolean isExpirationAllowed() {
    if (!isProtectionActive()) {
        return true;
    }
    return renewalThreshold > 0 && getCurrentRenewals() > renewalThreshold;
}

Tags: Eureka Service Discovery Self-Preservation java microservices

Posted on Fri, 06 Nov 2026 16:03:22 +0000 by kevinak