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…