eureka.instance.leaseRenewalIntervalInSeconds = 30 # hearbeat interval eureka.server.renewalPercentThreshold = 0.85 eureka.server.renewalThresholdUpdateIntervalMs = 15 * 60 * 1000 # 15mins
client发送心跳的频率html
触发自我保护的心跳数比例阈值java
多久重置一下心跳阈值node
factor = 60/leaseRenewalIntervalInSecondsweb
factor * Nspring
factor N renewalPercentThreshold微信
this.expectedNumberOfRenewsPerMin = N * 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
eureka-core-1.4.12-sources.jar!/com/netflix/eureka/registry/PeerAwareInstanceRegistryImpl.java网络
@Override public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) { // Renewals happen every 30 seconds and for a minute it should be a factor of 2. this.expectedNumberOfRenewsPerMin = count * 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()); logger.info("Got " + count + " instances from neighboring DS node"); logger.info("Renew threshold is: " + numberOfRenewsPerMinThreshold); this.startupTime = System.currentTimeMillis(); if (count > 0) { this.peerInstancesTransferEmptyOnStartup = false; } DataCenterInfo.Name selfName = applicationInfoManager.getInfo().getDataCenterInfo().getName(); boolean isAws = Name.Amazon == selfName; if (isAws && serverConfig.shouldPrimeAwsReplicaConnections()) { logger.info("Priming AWS connections for all replicas.."); primeAwsReplicas(applicationInfoManager); } logger.info("Changing status to UP"); applicationInfoManager.setInstanceStatus(InstanceStatus.UP); super.postInit(); }
count为eureka个数,此时expectedNumberOfRenewsPerMin为2(1个注册中心,每30秒发送一次心跳,则每分钟对于每一个client,应该发送2次心跳),numberOfRenewsPerMinThreshold=(int)2*0.85 =1app
eureka-core-1.4.12-sources.jar!/com/netflix/eureka/registry/AbstractInstanceRegistry.javaide
public void register(InstanceInfo registrant, int leaseDuration, boolean isReplication) { try { read.lock(); Map<String, Lease<InstanceInfo>> gMap = registry.get(registrant.getAppName()); REGISTER.increment(isReplication); if (gMap == null) { final ConcurrentHashMap<String, Lease<InstanceInfo>> gNewMap = new ConcurrentHashMap<String, Lease<InstanceInfo>>(); gMap = registry.putIfAbsent(registrant.getAppName(), gNewMap); if (gMap == null) { gMap = gNewMap; } } Lease<InstanceInfo> existingLease = gMap.get(registrant.getId()); // Retain the last dirty timestamp without overwriting it, if there is already a lease if (existingLease != null && (existingLease.getHolder() != null)) { Long existingLastDirtyTimestamp = existingLease.getHolder().getLastDirtyTimestamp(); Long registrationLastDirtyTimestamp = registrant.getLastDirtyTimestamp(); logger.debug("Existing lease found (existing={}, provided={}", existingLastDirtyTimestamp, registrationLastDirtyTimestamp); if (existingLastDirtyTimestamp > registrationLastDirtyTimestamp) { logger.warn("There is an existing lease and the existing lease's dirty timestamp {} is greater" + " than the one that is being registered {}", existingLastDirtyTimestamp, registrationLastDirtyTimestamp); logger.warn("Using the existing instanceInfo instead of the new instanceInfo as the registrant"); registrant = existingLease.getHolder(); } } else { // The lease does not exist and hence it is a new registration synchronized (lock) { if (this.expectedNumberOfRenewsPerMin > 0) { // Since the client wants to cancel it, reduce the threshold // (1 // for 30 seconds, 2 for a minute) this.expectedNumberOfRenewsPerMin = this.expectedNumberOfRenewsPerMin + 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()); } } logger.debug("No previous lease information found; it is new registration"); } Lease<InstanceInfo> lease = new Lease<InstanceInfo>(registrant, leaseDuration); if (existingLease != null) { lease.setServiceUpTimestamp(existingLease.getServiceUpTimestamp()); } gMap.put(registrant.getId(), lease); synchronized (recentRegisteredQueue) { recentRegisteredQueue.add(new Pair<Long, String>( System.currentTimeMillis(), registrant.getAppName() + "(" + registrant.getId() + ")")); } // This is where the initial state transfer of overridden status happens if (!InstanceStatus.UNKNOWN.equals(registrant.getOverriddenStatus())) { logger.debug("Found overridden status {} for instance {}. Checking to see if needs to be add to the " + "overrides", registrant.getOverriddenStatus(), registrant.getId()); if (!overriddenInstanceStatusMap.containsKey(registrant.getId())) { logger.info("Not found overridden id {} and hence adding it", registrant.getId()); overriddenInstanceStatusMap.put(registrant.getId(), registrant.getOverriddenStatus()); } } InstanceStatus overriddenStatusFromMap = overriddenInstanceStatusMap.get(registrant.getId()); if (overriddenStatusFromMap != null) { logger.info("Storing overridden status {} from map", overriddenStatusFromMap); registrant.setOverriddenStatus(overriddenStatusFromMap); } // Set the status based on the overridden status rules InstanceStatus overriddenInstanceStatus = getOverriddenInstanceStatus(registrant, existingLease, isReplication); registrant.setStatusWithoutDirty(overriddenInstanceStatus); // If the lease is registered with UP status, set lease service up timestamp if (InstanceStatus.UP.equals(registrant.getStatus())) { lease.serviceUp(); } registrant.setActionType(ActionType.ADDED); recentlyChangedQueue.add(new RecentlyChangedItem(lease)); registrant.setLastUpdatedTimestamp(); invalidateCache(registrant.getAppName(), registrant.getVIPAddress(), registrant.getSecureVipAddress()); logger.info("Registered instance {}/{} with status {} (replication={})", registrant.getAppName(), registrant.getId(), registrant.getStatus(), isReplication); } finally { read.unlock(); } }
其中,重点看这段post
synchronized (lock) { if (this.expectedNumberOfRenewsPerMin > 0) { // Since the client wants to cancel it, reduce the threshold // (1 // for 30 seconds, 2 for a minute) this.expectedNumberOfRenewsPerMin = this.expectedNumberOfRenewsPerMin + 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold()); } }
每注册上一个实例,从新算一下,即
this.expectedNumberOfRenewsPerMin = this.expectedNumberOfRenewsPerMin + 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
总的来讲,全部实例都注册上了,就是
this.expectedNumberOfRenewsPerMin = N * 2; this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
leaseRenewalIntervalInSeconds: 10 --> 每分钟6次 this.expectedNumberOfRenewsPerMin = N * 2 = 32 ; this.numberOfRenewsPerMinThreshold = (int) (32 * 0.85) = (int)27.2 = 27;
leaseRenewalIntervalInSeconds: 30 --> 每分钟2次 this.expectedNumberOfRenewsPerMin = N * 2 = 6 ; this.numberOfRenewsPerMinThreshold = (int) (6* 0.85) = (int)5.1 = 5;
对于单机版eureka的,比较特殊,因为openForTraffic这个方法里头
this.expectedNumberOfRenewsPerMin = count * 2;
这里count=1多算了一个实例的心跳次数,因此以下:
leaseRenewalIntervalInSeconds: 30 --> 每分钟2次 this.expectedNumberOfRenewsPerMin = N * 2 = 2 ; this.numberOfRenewsPerMinThreshold = (int) (2 * 0.85) = (int)1.7 = 1; 实际显示是3,应该是按N=2算 this.expectedNumberOfRenewsPerMin = N * 2 = 4 ; this.numberOfRenewsPerMinThreshold = (int) (4 * 0.85) = (int)3.4 = 3;
leaseRenewalIntervalInSeconds: 30 --> 每分钟2次 this.expectedNumberOfRenewsPerMin = N * 2 = 4 ; this.numberOfRenewsPerMinThreshold = (int) (4 * 0.85) = (int)3.4 = 3; 实际显示是5,应该是按N=3算 this.expectedNumberOfRenewsPerMin = N * 2 = 6 ; this.numberOfRenewsPerMinThreshold = (int) (6 * 0.85) = (int)5.1 = 5;
因为eureka-core-1.4.12版本里头,你去调整eureka.instance.leaseRenewalIntervalInSeconds的话,代码里头没有相应调整factor,也就是代码仍是60/30=2,因此会破坏eureka内置的设计思路。不过对于小型项目来讲,没有跨机房,网络没有那么恶劣的话,想避免自我保护致使的服务注册列表不能修改的问题,能够选择如下任一方式尝试下:
关闭自我保护eureka.server.enableSelfPreservation=false
调小eureka.instance.leaseRenewalIntervalInSeconds,好比设置为10秒
调小renewalPercentThreshold,好比改成0.49
另外,还有一个参数能够调整,就是心跳阈值从新计算的周期:
eureka.server.renewalThresholdUpdateIntervalMs = 15 60 1000 # 15mins
默认是15分钟能够改小一点,好比5分钟=5601000
想获取最新内容,请关注微信公众号