Eureka 啟動分析 和 配置調優


1. InstanceInfoFactory
2. com.netflix.discovery.DiscoveryClient
3. DefaultEurekaServerContext : Initializing ...
4. cluster.PeerEurekaNodes : Adding new peer nodes
5. AbstractInstanceRegistry : Finished initializing remote region registries.
6. DefaultEurekaServerContext : Initialized
7. EurekaServiceRegistry : Registering application EUREKASERVER with eureka with status UP
8. EurekaServerBootstrap : Initialized server context

EurekaBootStrap

this.initEurekaEnvironment();
this.initEurekaServerContext();
((PeerAwareInstanceRegistry)registry).openForTraffic(applicationInfoManager, registryCount);
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
    this.expectedNumberOfClientsSendingRenews = count;
    this.updateRenewsPerMinThreshold();

AbstractInstanceRegistry

  • 自我保護機制 ,若關閉 ------> evict 剔除服務。 若開啟 --------> 進行服務保護( 網絡抖動或者真的掛掉 )
  • eureka 優化點 RenewalPercentThreshold()); 續約百分比閾值
  • RenewalPercentThreshold 續約百分比閾值 ----默認0.85D
  • 這兩個配置 需要考慮 實際服務數、閾值等測算后調節。少量服務建議開啟保護,服務數量多可以下線,寫事件監聽進行 郵件、釘釘等通知提醒
public void evict(long additionalLeaseMs) {
   .....
int registrySize = (int)this.getLocalRegistrySize();
int registrySizeThreshold = (int)((double)registrySize * this.serverConfig.getRenewalPercentThreshold());
int evictionLimit = registrySize - registrySizeThreshold;
int toEvict = Math.min(expiredLeases.size(), evictionLimit);
if (toEvict > 0) {
    logger.info("Evicting {} items (expired={}, evictionLimit={})", new Object[]{toEvict, expiredLeases.size(), evictionLimit});
    Random random = new Random(System.currentTimeMillis());
  • RenewalThresholdUpdateIntervalMs 續約閾值更新間隔 ----默認900000ms
  • ExpectedClientRenewalIntervalSeconds 期望客戶端續約間隔-----默認30s
  • 定時任務 Timer 進行剔除沒有心跳的服務
  • 缺點:Timer 多線程並行處理任務時運行多個TimerTask,只要其中之一沒有捕獲拋出的異常,其他任務就會自動終止,建議使用ScheduleExecutorService
  • 優化點 剔除服務時間間隔毫秒數 EvictionIntervalTimerInMs
  • 可以進行 服務的快速下線 配置為 每1s進行一次剔除服務,提高可用性
this.evictionTimer.schedule((TimerTask)this.evictionTaskRef.get(), this.serverConfig.getEvictionIntervalTimerInMs(), this.serverConfig.getEvictionIntervalTimerInMs());

三級緩存機制

  • register --> readWriteCacheMap --> readonlyCacheMap

  • 每次注冊的時候 更新register ,失效readWriteCacheMap中的相關服務

  • readWriteCacheMap readonly 之間 ,定時任務Timer 每隔30s 更新一次 (從readWriteCacheMap 中取數據放入readonlyCacheMap 主要提供讀,高可用性)。不是強一致性

    eureka.server.response-cache-update-interval-ms=1000
    
  • 優化點 response-cache-update-interval-ms 配置時間間隔小一點,可以更快速的從readWriteCacheMap 取到數據,放入readonlyCacheMap

  • 優化點 eureka.server.use-read-only-response-cache=false

  • 三級緩存 默認為 true , false直接從readWriteCacheMap 中取數據,不去readonlyCacheMap,readonlyCacheMap數據一致性不高。

@VisibleForTesting
ResponseCacheImpl.Value getValue(Key key, boolean useReadOnlyCache) {
    ResponseCacheImpl.Value payload = null;

    try {
        if (useReadOnlyCache) {
            ResponseCacheImpl.Value currentPayload = (ResponseCacheImpl.Value)this.readOnlyCacheMap.get(key);
            if (currentPayload != null) {
                payload = currentPayload;
            } else {
                payload = (ResponseCacheImpl.Value)this.readWriteCacheMap.get(key);
                this.readOnlyCacheMap.put(key, payload);
            }
        } else {
            payload = (ResponseCacheImpl.Value)this.readWriteCacheMap.get(key);
        }
    } catch (Throwable var5) {
        logger.error("Cannot get value for key : {}", key, var5);
    }

    return payload;
}
  • CAP 中的C 一致性無法保證
  • eureka的數據結構
private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry = new ConcurrentHashMap();

ApplicationResource

@POST
@Consumes({"application/json", "application/xml"})
public Response addInstance(InstanceInfo info, @HeaderParam("x-netflix-discovery-replication") String isReplication) {

InstanceRegistry

public void register(final InstanceInfo info, final boolean isReplication) {
    this.handleRegistration(info, this.resolveInstanceLeaseDuration(info), isReplication);
    super.register(info, isReplication);
}
  • 服務注冊 對readWriteCacheMap 中服務 進行失效
public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) {
    try {
        this.read.lock();
       .......
        Lease<InstanceInfo> existingLease = (Lease)((Map)gMap).get(registrant.getId());
            synchronized(this.lock) {
                if (this.expectedNumberOfClientsSendingRenews > 0) {
                    ++this.expectedNumberOfClientsSendingRenews;
                    this.updateRenewsPerMinThreshold();
                }
            }
-----------------------------------------------------------------------------------------
        Lease<InstanceInfo> lease = new Lease(registrant, leaseDuration);
-----------------------------------------------------------------------------------------      
       ........
-----------------------------------------------------------------------------------------
        this.invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress());
-----------------------------------------------------------------------------------------
        logger.info("Registered instance {}/{} with status {} (replication={})", new Object[]{registrant.getAppName(), registrant.getId(), registrant.getStatus(), isReplication});
    } finally {
        this.read.unlock();
    }

}

Lease<InstanceInfo>,<T>泛型 。Lease自帶各種時間字段

  • 服務信息 注入Lease中, 由於每30s心跳后進行服務續約,這個數據結構便於服務續約 (直接調用方法,而不用進行get、set)

  • 服務續約 和 服務下線

  • public void renew() {
        this.lastUpdateTimestamp = System.currentTimeMillis() + this.duration;
    }
    
    public void cancel() {
        if (this.evictionTimestamp <= 0L) {
            this.evictionTimestamp = System.currentTimeMillis();
        }
    

ResponseCacheImpl

public void invalidate(String appName, @Nullable String vipAddress, @Nullable String secureVipAddress) {

EurekaServerAutoConfiguration

  • @Import({EurekaServerInitializerConfiguration.class})
    @ConditionalOnBean({Marker.class})
    

EurekaServerInitializerConfiguration

  • implements SmartLifecycle
    
  • SmartLifecycle extends Lifecycle
    
  • Lifecycle -------> springframework.context

  • EurekaServerInitializerConfiguration 實現了Lifecycle中 start();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM