介绍下Eureka的使用以及相关配置参数
高可用
服务调用
1.使用原始的Eureka DiscoveryClient 来找到服务实例的主机并且用Spring的RestTemplate来发起调用。 2.使用Ribbon,一个使用Eureka来找到服务实例的客户端负载均衡解决方案 3. 使用Feigin,它使用了一个说明性的方法来调用服务。它内部使用了Ribbo
源码
服务端
服务端启动
EurekaServerInitializerConfiguration.start()
try { //TODO: is this class even needed now? eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext); log.info("Started Eureka Server"); publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig())); EurekaServerInitializerConfiguration.this.running = true; publish(new EurekaServerStartedEvent(getEurekaServerConfig())); } catch (Exception ex) { // Help! log.error("Could not initialize Eureka servlet context", ex); }
复制 neighboring eureka node
// Copy registry from neighboring eureka node int registryCount = this.registry.syncUp();
计算Renews threshold (numberOfRenewsPerMinThreshold)
公式: 2 * N * 0.85 ==> 60/心跳时间(总是认为是30s)*instance num *factor Netflix code assumes that heartbeats are always received at intervals of 30 seconds for this calculation.
1.初始化 numberOfRenewsPerMinThreshold PeerAwareInstanceRegistryImpl
@Override //count 来自 this.registry.syncUp(); 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; // serverConfig.getRenewalPercentThreshold() 来自配置 默认0.85 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(); }
2.客户端注册时候刷新numberOfRenewsPerMinThreshold
AbstractInstanceRegistry // 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");
3.renewal-threshold-update-interval-ms 时间间隔后从新计算阀值.
接收客户端的rest 请求 DiscoveryJerseyProvider
@Override public Object readFrom(Class serializableClass, Type type, Annotation[] annotations, MediaType mediaType, MultivaluedMap headers, InputStream inputStream) throws IOException { DecoderWrapper decoder; if (MediaType.MEDIA_TYPE_WILDCARD.equals(mediaType.getSubtype())) { decoder = xmlDecoder; } else if ("json".equalsIgnoreCase(mediaType.getSubtype())) { decoder = jsonDecoder; } else { decoder = xmlDecoder; // default } try { return decoder.decode(inputStream, serializableClass); } catch (Throwable e) { if (e instanceof Error) { // See issue: https://github.com/Netflix/eureka/issues/72 on why we catch Error here. closeInputOnError(inputStream); throw new WebApplicationException(createErrorReply(500, e, mediaType)); } LOGGER.debug("Cannot parse request body", e); throw new WebApplicationException(createErrorReply(400, "cannot parse request body", mediaType)); } }
EvictionTask
以eviction-interval-timer-in-ms (eureka.server.evictionIntervalTimerInMs)指定的频率执行 移除过期的instacne.在移除之前检查是否进入自我保护模式.(Renews < Renews threshold && eureka.server.enableSelfPreservation=true)
Renews (last min)
每分钟计算一次.