Article starts from the public, the programmer blended address: mp.weixin.qq.com/s/FfJrAGQuH…

Introduction to the

Last article “Eureka source analysis of Eureka Client” through the source code know that Eureka Client is through HTTP REST to interact with Eureka Server, to achieve registration services, renewal services, services offline, etc.. This article explores eureka Server.

Source code analysis

From the @enableeurekaserver annotation as entry analysis, through the source can be seen that it is a tag annotation:

/**
 * Annotation to activate Eureka Server related configuration {@link* /
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {

}
Copy the code

Can know from the annotation, which is used to activate the eureka related configuration in the server configuration class EurekaServerAutoConfiguration, EurekaServerAutoConfiguration key code is as follows:

@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
		InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {
	/** * List of packages containing Jersey resources required by the Eureka server */
	private static final String[] EUREKA_PACKAGES = new String[] { "com.netflix.discovery"."com.netflix.eureka" };

	@Autowired
	private ApplicationInfoManager applicationInfoManager;

	@Autowired
	private EurekaServerConfig eurekaServerConfig;

	@Autowired
	private EurekaClientConfig eurekaClientConfig;

	@Autowired
	private EurekaClient eurekaClient;

	@Autowired
	private InstanceRegistryProperties instanceRegistryProperties;

	public static final CloudJacksonJson JACKSON_JSON = new CloudJacksonJson();

	@Bean
	public HasFeatures eurekaServerFeature(a) {
		return HasFeatures.namedFeature("Eureka Server",
				EurekaServerAutoConfiguration.class);
	}

	@Configuration
	protected static class EurekaServerConfigBeanConfiguration {
		// Create and load the implementation class of EurekaServer config, mainly the configuration information of Eureka server
		@Bean
		@ConditionalOnMissingBean
		public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
			EurekaServerConfigBean server = new EurekaServerConfigBean();
			if (clientConfig.shouldRegisterWithEureka()) {
				// Set a sensible default if we are supposed to replicate
				server.setRegistrySyncRetries(5);
			}
			returnserver; }}// load EurekaController. SpringCloud provides some additional interfaces to get information about eurekaServer
	@Bean
	@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
	public EurekaController eurekaController(a) {
		return new EurekaController(this.applicationInfoManager);
	}

	/ / to omit...
	
	InstanceRegistry handles requests such as receiving client registrations. InstanceRegistry is a class that actually handles business, which we'll look at in more detail next
	@Bean
	public PeerAwareInstanceRegistry peerAwareInstanceRegistry( ServerCodecs serverCodecs) {
		this.eurekaClient.getApplications(); // force initialization
		return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig,
				serverCodecs, this.eurekaClient,
				this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(),
				this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
	}
	
	This function is mainly used to configure the peer nodes of Eureka, that is, which nodes need to be notified when some nodes are registered
	@Bean
	@ConditionalOnMissingBean
	public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry, ServerCodecs serverCodecs) {
		return new RefreshablePeerEurekaNodes(registry, this.eurekaServerConfig,
				this.eurekaClientConfig, serverCodecs, this.applicationInfoManager);
	}
	
	/ / to omit...
	
	// Context of EurekaServer
	@Bean
	public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs, PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) {
		return new DefaultEurekaServerContext(this.eurekaServerConfig, serverCodecs,
				registry, peerEurekaNodes, this.applicationInfoManager);
	}
	
	// Initializing Eureka-server synchronizes data from other registries to the current registry
	@Bean
	public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry, EurekaServerContext serverContext) {
		return new EurekaServerBootstrap(this.applicationInfoManager,
				this.eurekaClientConfig, this.eurekaServerConfig, registry,
				serverContext);
	}

	The Jersey framework is used to implement the restFull interface to eurekaServer
	@Bean
	public FilterRegistrationBean jerseyFilterRegistration( javax.ws.rs.core.Application eurekaJerseyApp) {
		FilterRegistrationBean bean = new FilterRegistrationBean();
		bean.setFilter(new ServletContainer(eurekaJerseyApp));
		bean.setOrder(Ordered.LOWEST_PRECEDENCE);
		bean.setUrlPatterns(
				Collections.singletonList(EurekaConstants.DEFAULT_PREFIX + "/ *"));

		return bean;
	}

	/ / to omit...
	

}
Copy the code

From EurekaServerAutoConfiguration annotation on the class @ Import (EurekaServerInitializerConfiguration. Class), Instantiate classes EurekaServerAutoConfiguration before, has been instantiated EurekaServerInitializerConfiguration class, the code is as follows:

@Configuration
@CommonsLog
public class EurekaServerInitializerConfiguration
      implements ServletContextAware.SmartLifecycle.Ordered {
 
   // Omit some code here
 
   @Override
   public void start(a) {
      // Start a thread
      new Thread(new Runnable() {
         @Override
         public void run(a) {
            try {
               // Initialize EurekaServer and start EurekaServer
               eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
               log.info("Started Eureka Server");
                // Publish EurekaServer registration event
               publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
                // Set the startup state to true
               EurekaServerInitializerConfiguration.this.running = true;
                // Send the Eureka Start event, and all sorts of other events. We can listen for this time and then do some specific business requirements, which will be covered later.
               publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
            }
            catch (Exception ex) {
               // Help!
               log.error("Could not initialize Eureka servlet context", ex);
            }
         }
      }).start();
   }
 
   // Omit some code here
 
}
Copy the code

The start method starts a new thread and performs some initialization of the EurekaServer, such as calling the contextInitialized method of eurekaServerBootstrap. The code for the eurekaServerBootstrap is as follows:

public class EurekaServerBootstrap {

	// Omit some code here

	public void contextInitialized(ServletContext context) {
	   try {
	      // Initialize Eureka's environment variables
	      initEurekaEnvironment();
	      // Initialize the Eureka context
	      initEurekaServerContext();
	 
	      context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
	   }
	   catch (Throwable e) {
	      log.error("Cannot bootstrap eureka server :", e);
	      throw new RuntimeException("Cannot bootstrap eureka server :", e); }}protected void initEurekaEnvironment(a) throws Exception {
	   log.info("Setting the eureka configuration..");
	 
	   String dataCenter = ConfigurationManager.getConfigInstance()
	         .getString(EUREKA_DATACENTER);
	   if (dataCenter == null) {
	      log.info(
	            "Eureka data center value eureka.datacenter is not set, defaulting to default");
	      ConfigurationManager.getConfigInstance()
	            .setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, DEFAULT);
	   }
	   else {
	      ConfigurationManager.getConfigInstance()
	            .setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, dataCenter);
	   }
	   String environment = ConfigurationManager.getConfigInstance()
	         .getString(EUREKA_ENVIRONMENT);
	   if (environment == null) {
	      ConfigurationManager.getConfigInstance()
	            .setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, TEST);
	      log.info(
	            "Eureka environment value eureka.environment is not set, defaulting to test");
	   }
	   else{ ConfigurationManager.getConfigInstance() .setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, environment); }}protected void initEurekaServerContext(a) throws Exception {
	   // For backward compatibility
	   JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
	         XStream.PRIORITY_VERY_HIGH);
	   XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
	         XStream.PRIORITY_VERY_HIGH);
	 
	   if (isAws(this.applicationInfoManager.getInfo())) {
	      this.awsBinder = new AwsBinderDelegate(this.eurekaServerConfig,
	            this.eurekaClientConfig, this.registry, this.applicationInfoManager);
	      this.awsBinder.start();
	   }
	  
	   // Initialize the Eureka server context
	   EurekaServerContextHolder.initialize(this.serverContext);
	 
	   log.info("Initialized server context");
	 
	   // Copy registry from neighboring eureka node
	   // Copy the registry from the adjacent Eureka node
	   int registryCount = this.registry.syncUp();
	    // By default, heartbeat is sent every 30 seconds, twice a minute
	    // Change the Eureka status to Up
	    // At the same time, there will be a scheduled task to clean up the client that has no heartbeat for 60 seconds. Automatic logoff
	   this.registry.openForTraffic(this.applicationInfoManager, registryCount);
	 
	   // Register all monitoring statistics.
	   EurekaMonitors.registerAllStats();
	}
	public void contextDestroyed(ServletContext context) {
	   try {
	      log.info("Shutting down Eureka Server..");
	      context.removeAttribute(EurekaServerContext.class.getName());
	 
	      destroyEurekaServerContext();
	      destroyEurekaEnvironment();
	 
	   }
	   catch (Throwable e) {
	      log.error("Error shutting down eureka", e);
	   }
	   log.info("Eureka Service is now shutdown..."); }}Copy the code

After the Eureka Server context is initialized, the openForTraffic method is executed. This method sets the expected heartbeat count per minute, sets the state of the service instance to UP, and finally starts a scheduled task with postInit. Use to clear service instances that are not renewed at regular intervals (60 seconds by default) (90 seconds by default). The openForTraffic method code is as follows:

@Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {
    // Renewals happen every 30 seconds and for a minute it should be a factor of 2.
    // Calculate the maximum number of renewals per minute
    this.expectedNumberOfRenewsPerMin = count * 2;
    // Calculate the minimum number of renewals per minute
    this.numberOfRenewsPerMinThreshold =
            (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
    logger.info("Got {} instances from neighboring DS node", count);
    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");
    // Change the status of the service instance to UP
    applicationInfoManager.setInstanceStatus(InstanceStatus.UP);
    // Enable the scheduled task to clear the service instances that are not renewed at intervals (60 seconds by default) (90 seconds by default)
    super.postInit();
}
Copy the code

The postInit method starts a new scheduled task with the following code:

protected void postInit(a) {
    renewsLastMin.start();
    if(evictionTaskRef.get() ! =null) {
        evictionTaskRef.get().cancel();
    }
    evictionTaskRef.set(new EvictionTask());
    evictionTimer.schedule(evictionTaskRef.get(),
            serverConfig.getEvictionIntervalTimerInMs(),
            serverConfig.getEvictionIntervalTimerInMs());
}
Copy the code

The intervals here are all from the EurekaServerConfigBean class, which can be set in the configuration file starting with Eureka.server.

reference

www.e-learn.cn/content/qit… Nobodyiam.com/2016/06/25/… Blog.csdn.net/Lammonpeter…

Pay attention to my