Eureka is a component of the Springcloud family, because it has service registration and discovery mechanism, so it is very suitable for the registration center. Eureka has the service side and the client, the registration center serves as the service side, we provide the service as the client registers to the service end, by Eureka Unified Management. as a registry, its internal operating mechanism is what. Below I take these questions to study Eureka.
1. How to develop an integrated Spring Cloud Eureka program.
2. How the service provider registers with the service center.
3. How the service center receives the registration request.
4. How to store the service center.
5. The service center itself is how to achieve high availability.
6. How to synchronize information between service clusters. How to go heavy.
7. How the service center checks whether the service provider is normal.
8. Service Provider if the next service.
1. How to develop an integrated Spring Cloud Eureka program.
The following is the development of a pseudo cluster (on a stand-alone) of the Eureka program:
Server-side Pom.xml file main configuration:
<!--Spring Boot Package Spring Starter Encapsulation, automatic configuration autoconfiguration--> <parent> <groupid>org .springframework.cloud</groupid> <artifactId>spring-cloud-starter-parent</artifactId> &L
t;version>edgware.sr2</version> <relativepath/> </parent> <!--The following references do not add version number--> <dependencyManagement> <dependencies> <dependency> <GROUPID&G
T;org.springframework.cloud</groupid> <artifactId>spring-cloud-dependencies</artifactId> <version>Edgware.SR2</version> <type>pom</type> & lt;scope>import</scope> </dependency> </dependencies> </dependencymanageme
Nt> <dependencies> <!--spring-boot-starter-web Web project, integrated container tomcat--> <dependency> <groupid>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--spring-boot-starter-actuator management tools/web view stack, dynamic refresh configuration--> <dependency>
; <groupId>org.springframework.boot</groupId> <artifactid>spring-boot-starter-actuator</art
Ifactid> </dependency> <!--Cloud Eureka Component Registration Center--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactid>spring-cloud-starter-eureka-server& Lt;/artifactid> </dependency> </dependencies>
BOOTSTRAP.YML file:
# Application Name
Spring:
application:
name:eureka-server
APPLICATION.YML file:
# context Initialization Load
info:
name:eureka server
contact:wenthkim
Spring:
profiles:
active:eureka1
Spring:
profiles:eureka1
server:
port:8761
Eureka:
client:
# Whether to register to Eurekaserver
registerwitheureka:false
# Whether to pull information
fetchregistry:true
# Eureka server address
serviceurl:
defaultzone:http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763 /eureka/
server:
# false turns off self-protection, regardless of how the heartbeat detection exception is removed service
enableselfpreservation:true
# Updatepeereurekanodes execution interval
peereurekanodesupdateintervalms:10000000
waittimeinmswhensyncempty:0
Instance:
hostname:eureka1
metadatamap:
Instanceid: ${spring.application.name}:${ Vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
To start the Java class:
@SpringBootApplication
@EnableEurekaServer Public
class Eurekaapp {public
static void Main (string[] args {
new Springapplicationbuilder (Eurekaapp.class). Web (True). Run (args);
}
Below the Bootstrap.yml file port and hostname (need to own computer C:\Windows\System32\drivers\etc under the Hosts file configuration corresponding to the domain name), respectively, to 8761, 8762,8763 and Eureka1,eureka2,eureka3, respectively, start the Eureka program to build a highly available registration center.
After successful startup, the browser input http://localhost:8761/to see the successful interface
2. How the service provider registers with the service center.
What are the main information that is registered with the service center:
IP, port (ports), instance_id (instance ID), name (service name), and so on.
When the Eureka client starts, eurekaclientconfiguration the reading client configuration information, creates a Instanceinfo instance, then gives the Applicationinfomanager management, reads the paragraph code below:
@Configuration @ConditionalOnMissingRefreshScope protected Static class Eurekaclientconfiguration {@
autowired private ApplicationContext context;
@Autowired (required = false) private Discoveryclientoptionalargs Optionalargs; @Bean (Destroymethod = "shutdown") @ConditionalOnMissingBean (value = eurekaclient.class, search = Searchstrategy.cu rrent) public eurekaclient eurekaclient (applicationinfomanager Manager, Eurekaclientconfig config)
{return new cloudeurekaclient (Manager, config, This.optionalargs, this.context); @Bean @ConditionalOnMissingBean (value = applicationinfomanager.class, search = Searchstrategy.current
) Public Applicationinfomanager eurekaapplicationinfomanager (eurekainstanceconfig config) {
Get configuration Creation instance Instanceinfo Instanceinfo = new Instanceinfofactory (). Create (config); return new Applicationinfomanager (config, instanceinfo); }
}
During the instantiation process, the Heartbeatthread timed task of the discoveryclient is scanned, the unregistered instance is found, and the service center is registered, following a section of the Discoveryclient Class code:
/** * The heartbeat task that renews the lease in the given intervals. * Heartbeat, Registration timed Task * * Private class Heartbeatthread implements Runnable {public void run () {if (R)
Enew ()) {Lastsuccessfulheartbeattimestamp = System.currenttimemillis (); }}/** * Renew with the Eureka service by making the appropriate REST call/Boolean R
Enew () {eurekahttpresponse<instanceinfo> httpresponse; try {//Send a registration request to the Registry HttpResponse = EurekaTransport.registrationClient.sendHeartBeat (instanceinfo
. Getappname (), Instanceinfo.getid (), instanceinfo, NULL);
Logger.debug ("{}-Heartbeat status: {}", PREFIX + Apppathidentifier, Httpresponse.getstatuscode ()); When the registry returns 404 to prove that this instance is not registered, register, or return the registration success if (httpresponse.getstatuscode () = 404) {Reregister_co
Unter.increment (); Logger.info ("{}-re-registeringapps/{} ", PREFIX + Apppathidentifier, Instanceinfo.getappname ());
return register ();
return Httpresponse.getstatuscode () = = 200;
catch (Throwable e) {Logger.error ("{}-is unable to send heartbeat!", PREFIX + Apppathidentifier, E);
return false;
}/** * Register with the Eureka service by making the appropriate REST call. * Register method to Server/Boolean register () throws Throwable {Logger.info (PREFIX + apppathidentifier + ": registeri
Ng service ... ");
Eurekahttpresponse<void> HttpResponse;
try {HttpResponse = EurekaTransport.registrationClient.register (Instanceinfo); catch (Exception e) {Logger.warn ("{}-registration failed {}", PREFIX + Apppathidentifier, E.getmessage (),
e);
Throw e; } if (logger.isinfoenabled ()) {Logger.info ("{}-Registration status: {}", PREFIX + ApppaThidentifier, Httpresponse.getstatuscode ());
return Httpresponse.getstatuscode () = = 204;
}
3. How the service center receives the registration request.
Received through the rest interface, Spring Cloud integrates the Jersey RESTful interface in Eureka Server native package, Jerseyapi
Following the source view of the receiving process (Eureka Server is blocked through the filter request), the code is as follows:
The jerseyfilterregistration under the entry Eurekaserverautoconfiguration class will add a filter to intercept the registration request
@Bean public
Filterregistrationbean jerseyfilterregistration (Application Eurekajerseyapp) {
Filterregistrationbean bean = new Filterregistrationbean ();
Bean.setfilter (New Servletcontainer (Eurekajerseyapp));
Bean.setorder (2147483647);
Intercept the image client registration request
Bean.seturlpatterns (collections.singletonlist ("/eureka/*"));
return bean;
The Addinstance admissibility request under the Applicationresource class, the code is as follows:
@POST @Consumes ({"Application/json", "Application/xml"}) public Response addinstance (instanceinfo info, @Heade Rparam ("X-netflix-discovery-replication") String isreplication) {logger.debug ("registering Instance {}" (Replicati
on={}) ", Info.getid (), isreplication);
if (This.isblank (Info.getid ())) {return response.status () entity ("Missing Instanceid"). Build ();
else if (This.isblank (Info.gethostname ())) {return response.status. Entity ("Missing hostname"). Build (); else if (This.isblank (Info.getappname ())) {return response.status. Entity ("Missing appName"). b
Uild (); else if (!this.appname.equals (Info.getappname ())) {return response.status. Entity ("mismatched appName,
Expecting "+ This.appname +" but is "+ info.getappname ()). build (); else if (info.getdatacenterinfo () = = null) {return response.status. Entity ("Missing datacenterinfo"). Bu ILD ();
else if (Info.getdatacenterinfo (). GetName () = null) {return Response.Status (). Entity ("Missing
Datacenterinfo Name "). Build ();
else {Datacenterinfo datacenterinfo = Info.getdatacenterinfo (); if (datacenterinfo instanceof uniqueidentifier) {String datacenterinfoid = ((uniqueidentifier) datacenteri
NFO). GetId (); if (This.isblank (Datacenterinfoid)) {Boolean experimental = ' true '. Equalsignorecase (this.serverconfig
. Getexperimental ("Registration.validation.dataCenterInfoId")); if (experimental) {String entity = "Datacenterinfo of type" + datacenterinfo.getclass () + must
contain a valid ID ";
return Response.Status. Entity (Entity)-build (); } if (Datacenterinfo instanceof amazoninfo) {amazoninfo Amazoninfo = (Amazon
Info) Datacenterinfo; String Effectiveid = Amazoninfo.get (Metadatakey.instanceid); if (Effectiveid = null) {Amazoninfo.getmetadata (). Put (MetaDataKey.instanceId.getName (), info
. GetId ()); } else {Logger.warn ("registering Datacenterinfo of type {} without an Appro
Priate id ", Datacenterinfo.getclass ()); Register successfully and return 204,isreplication to prevent circular propagation this.registry.register (info
, "true". Equals (Isreplication));
Return Response.Status (204). build (); }
}
The Register method for calling the Instanceregistry class succeeds and publishes the Eurekainstanceregisteredevent registration event with the following code:
/**
* Registers and publishes registration events
/public void register (Instanceinfo info, Boolean isreplication) {
This.handleregistration (Info, this.resolveinstanceleaseduration (info), isreplication);
Super.register (info, isreplication);
/**
* Post Registration Event
/private void handleregistration (instanceinfo info, int leaseduration, Boolean isreplication) {
this.log ("register" + info.getappname () + ", VIP" + info.getvipaddress () + ", leaseduration" + le Aseduration + ", isreplication" + isreplication);
This.publishevent (this, info, leaseduration, isreplication) (new eurekainstanceregisteredevent);
}
4. How to store the service center.
View the Register method under the Abstractinstanceregistry class to see clearly that the client information exists within CONCURRENTHASHMAP. 5. The service center itself is how to achieve high availability.
With the Peer-to-peer Eureka Server instance, when the Eureka server is started, the other server-side addresses that are filled in by the configuration file are found and registered with each other. Examples, such as now there are eureka1,eureka2,eureka3. When a service is registered to EUREKA1, EUREKA1 issues a registration event, at which point Eureka2,eureka3 synchronizes the instance information. 6. How to synchronize information between service clusters. How to go heavy.
When Eurekaserver initializes, a peereurekanodes.peereurekanodes list is maintained,
When updating information needs to be synchronized, traversing all nodes and propagating the information, the Peerawareinstanceregistryimpl class's methods are called, Cancel/register/renew, and the code is as follows:
public boolean Cancel (string appName, String ID, Boolean isreplication) {if Super.cancel (appName, ID, isreplicat Ion)) {this.replicatetopeers (PeerAwareInstanceRegistryImpl.Action.Cancel, AppName, ID, (instanceinfo) null, (I
nstancestatus) null, isreplication);
Object VAR4 = This.lock; Synchronized (This.lock) {if (This.expectednumberofrenewspermin > 0) {this.expecte
Dnumberofrenewspermin-= 2; This.numberofrenewsperminthreshold = (int) (double) this.expectednumberofrenewspermin *
This.serverConfig.getRenewalPercentThreshold ());
return true;
} else {return false;
} public void Register (Instanceinfo info, Boolean isreplication) {int leaseduration = 90; if (info.getleaseinfo ()!= null && info.getleaseinfo (). Getdurationinsecs () > 0) {leaseduration = i Nfo.getleaseInfo (). Getdurationinsecs ();
} super.register (Info, leaseduration, isreplication); This.replicatetopeers (PeerAwareInstanceRegistryImpl.Action.Register, Info.getappname (), Info.getid (), info, (
instancestatus) null, isreplication); Public boolean Renew (string appName, String ID, Boolean isreplication) {if (super.renew appName, ID, isrep lication)) {this.replicatetopeers (PeerAwareInstanceRegistryImpl.Action.Heartbeat, AppName, ID, (instanceinfo)
NULL, (Instancestatus) null, isreplication);
return true;
else {return false; }/** * Traverse all nodes */private void Replicatetopeers (Peerawareinstanceregistryimpl.action Action, String AppName, String ID, instanceinfo info, Instancestatus newstatus, Boolean isreplication) {Stopwatch tracer = Actio
N.gettimer (). Start ();
try {if (isreplication) {this.numberOfReplicationsLastMin.increment (); } if (this.peereurekanodes = = Collections.empty_list | | isreplication) {return;
} Iterator Var8 = This.peerEurekaNodes.getPeerEurekaNodes (). iterator ();
while (Var8.hasnext ()) {peereurekanode node = (peereurekanode) var8.next (); if (!this.peereurekanodes.isthismyurl (Node.getserviceurl ())) {This.replicateinstanceactionstopeers (AC
tion, appName, id, info, newstatus, node);
}}} finally {Tracer.stop (); }/** * Handles different events * * private void Replicateinstanceactionstopeers (Peerawareinstanceregistryimpl.action Action, Str ing appName, String ID, instanceinfo info, instancestatus newstatus, Peereurekanode node) {try {Inst
Anceinfo infofromregistry = null;
Currentrequestversion.set (VERSION.V2); Switch (action) {Case Cancel:node.cancel (aPpname, id);
Break Case Heartbeat:instancestatus Overriddenstatus = (instancestatus) this.overriddenInstanceStatusMap.get (ID)
;
Infofromregistry = This.getinstancebyappandid (AppName, ID, false);
Node.heartbeat (AppName, id, Infofromregistry, overriddenstatus, false);
Break
Case Register:node.register (info);
Break
Case statusupdate:infofromregistry = This.getinstancebyappandid (AppName, ID, false);
Node.statusupdate (AppName, id, newstatus, infofromregistry);
Break
Case deletestatusoverride:infofromregistry = This.getinstancebyappandid (AppName, ID, false);
Node.deletestatusoverride (AppName, ID, infofromregistry); } catch (Throwable var9) {logger.error ("cannot replicate information to {} for action {}", new Obje ct[]{node.getserviceurl (), Action.name (), var9});
}
}
7. How the service center checks whether the service provider is normal.
Service culling: Does not give the heartbeat default 90 seconds for a long time
When Eureka initiates the initialization context, a timed task Evictiontask (Detect exception Service) is initiated.
A little more code will not be posted. The code entry is the Start method for the Eurekaserverinitializerconfiguration class, and finally to the Postinit boot Evictiontask of the Abstractinstanceregistry class.
When Eureka Server opens self-protection, no service is removed. That's when eureka.server.enableselfpreservation=true. Self-protection examples:
When a service has 10 instances, the default commit heartbeat time is 30 seconds.
At this point the valve value is 0.8,
Then the number of heartbeat packs per minute is required.