当前位置:网站首页>Eureka core source code analysis

Eureka core source code analysis

2022-06-27 10:24:00 InfoQ

Eureka As Spring Cloud One of the core modules of , It plays an important role in service registration and discovery . If you sort it out Eureka Actual workflow , It can be roughly divided into the following parts :

  • Service registration
  • Renewal of service
  • Service to eliminate
  • Service offline
  • Service discovery
  • Cluster information synchronization

The above aspects , Service based running scenarios are different , May be from Eureka The service side ( Registry Center ) With client ( Include service providers and service callers ) Analyze , For the sake of simplicity, we will Eureka The server is called Eureka-server, The client is called Eureka-client. This article first talks about basic service registration .

Service registration

Eureka-client

stay Eureka-client in ,DiscoveryClient This class is used to communicate with Eureka-server Cooperate with each other , Take a look at its notes , It can complete the service registration , Renewal of service , Service offline , Get the list of services, etc , It can be said that it is finished client Most of the features of . First , To look at eureka-server The person who initiated the registration request
register
Method :

null
call  
AbstractJerseyEurekaHttpClient
  Class
register
Method :

null
Jersey It's a Restful A framework for requesting services , With the usual springmvc similar , I'll talk about it later Eureka-server It is also used to intercept requests Jersy.

Call the underlying class here :

com.sun.jersey.api.client.Client

adopt HTTP The client sends http request , And build the response results .

Eureka-server

stay Eureka-server, Good configuration
yml
After the required parameters in the file , Only one annotation is needed to open :

@EnableEurekaServer

Check the implementation method of this annotation , Found as blank annotation , And used
@Import

@Import(EurekaServerMarkerConfiguration.class)

see
EurekaServerMarkerConfiguration
The realization of the class :

null
Here only to spring Container injection bean, It doesn't make any sense . It's used here Springboot Automatic assembly of ( This unfamiliar can refer to
springboot Zero configuration startup
):

null
Find out Eureka server Core auto configuration class
EurekaServerAutoConfiguration

null
We see , Conditionally inject annotations on this class :

@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)

Only in Spring Container exists Marker This Bean This class will only be instantiated when , therefore
@EnableEurekaServer
It's like a switch , It serves as a sign .

Interceptors are defined in this configuration class , Also use Jersy Intercept request :

null
ApplicationResource
Class
addInstance
Method to receive the request , After verifying the information of the instance , Add an instance to the service registry :

null
Get into
InstanceRegistry
Of
register
Method :

null
There are two functions here :

1、 call
handleRegistration
, Use... In methods
publishEvent
Released listening Events  .Spring Support event driven , You can listen to events in listener mode , Broadcast here to all listeners , Received a service registration request .

As for the listener , It can be written by ourselves , Event type in parameter spring Will help us inject :

@Component
public class EurekaRegisterListener {
 @EventListener
 public void registe(EurekaInstanceRegisteredEvent event){
 System.out.println(event.getInstanceInfo().getAppName());
 }
}

2、 Call the parent class
PeerAwareInstanceRegistryImpl
Of
register
Method :

null
The following operations are carried out :

①  The expiration time of getting the micro service , And update

②  Hand over the service registration to the parent class to complete

③  Complete cluster information synchronization ( This will be explained later )

Call the parent class
AbstractInstanceRegistry
Of
register
Method , Start doing service registration here . First, let's talk about the..., which is defined in this class Eureka-server The structure of the service registration list :

ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry;

ConcurrentHashMap
Middle and outer String Represents the service name ;

Map
Medium String Represents the of the service node id ( That is, the of the example instanceid);

Lease
Is a heartbeat renewal object ,
InstanceInfo
Indicates the instance information .

null
First , The registry takes... According to the name of the micro service Map, If it doesn't exist, create a new one , Use
putIfAbsent
.

then , from
gMap
(gMap This is the list of instances of the service ) Get a service instance , Determine whether the microservice node exists , In the case of first registration, it generally does not exist

Of course , There may also be registration information conflicts , At this time Eureka It will judge which one is covered according to the last active time :

null
In this code ,Eureka Get the last active time of the existing node , And the initiation registration time of the current registration node , Contrast . When the last active time of the existing node is greater than the time of the current registered node , It means that the existing nodes are more active , Replace the current node .

Here's an idea , Is that if Eureka Cached old nodes are more active , That means it can be used , And I don't know if the new service can be used , that Eureka It conservatively uses the available old nodes , From this point, it also ensures the availability

After getting the service instance, encapsulate it :

null
Lease It is a packaging class for contract renewal , It stores the registration information , Last operation time , Registration time , Expiration time , Eliminate information such as time . Here, put the registered instance and expiration time into the heartbeat renewal object , Then put the heartbeat renewal object into
gmap
Go to the registry . Then change the service status , System data statistics , So far, a service registration process is completed .

After registration , Check it out.
registry
Service instance in , Find out what we started Eureka-client It's all in there :

null

Renewal of service

Eureka-client

Service renewal by Eureka-client The end initiates , From the previously introduced
DiscoveryClient
Class
renew
Method to complete , The main content is still sending http request :

null
every other 30 Renew the contract once a second , call
AbstractJerseyEurekaHttpClient
Of
sendHeartBeat
Method :

null

Eureka-server

stay Eureka-server End , The call chain of service renewal is basically the same as that of service registration :

InstanceRegistry # renew() ->
PeerAwareInstanceRegistry # renew()->
AbstractInstanceRegistry # renew()v

Let's see
AbstractInstanceRegistry
  Of
renew
Method :

null
First get the instance list of the service from the registry gMap, Again from gMap Through the example of id  Get specific   Instance to renew . Then, according to the service instance
InstanceStatus
Determine whether it is in a state of downtime , And whether it is the same as before . If everything is normal , The final call
Lease
Medium
renew
Method :

null
It can be seen that , Service renewal is actually very simple , Its essence is to modify the last update time of the service . Change the last update time to the current time of the system plus the expiration time of the service . It is worth mentioning that ,
lastUpdateTimestamp
This variable is called
volatile
Keyword modifier .

null
In the previous article, we talked about
volitaile
Is used to ensure visibility . So who should be visible , Say it in advance , Here, the scheduled tasks to be executed in the service are visible , It will be analyzed in detail later .

Service to eliminate

Eureka-server

When Eureka-server It is found that some instances have not renewed their contracts for more than a certain period of time , Remove the service from the registration list , The work is completed by a scheduled task . The definition process of this task is complex , List only its calling procedures :

EurekaServerInitializerConfiguration # start() ->
EurekaServerBootstrap # contextInitialized() ->
 # initEurekaServerContext() ->
PeerAwareInstanceRegistryImpl # openForTraffic() ->
AbstractInstanceRegistry # postInit()

null
stay
AbstractInstanceRegistry
Of
postInit
In the method , Definition
EvictionTask
Timing task , The build timer starts the task , Elimination method in task execution  
evict()
.

private long evictionIntervalTimerInMs = 60 * 1000;

The time of the task is defined as 60 second , That is, it is executed every minute by default . Specific to see
evit()
Elimination method :

null
Realized the function :

1、 Create a new instance list
expiredLeases
, Used to store expired real

2、 Traverse
registry
The registry , Test the instance , Use
isExpired
Method to determine whether the instance is expired :

null
Explain the meaning of each parameter :

evictionTimestamp: Cut out the time , When removing nodes , Assign the current system time to this evictionTimestamp
additionalLeaseMs: Reservation time generated by cluster synchronization , This time is transmitted from the program

Here's the judgment :

Current system time  >  Last update time  +  Expiration time  +  Set aside time

When this condition holds , Think the service is overdue . stay Eureka The default expiration time is defined as 3 Within a heartbeat , A heartbeat is 30 second , So the expiration time is 90 second . When this condition holds , Think the service is overdue . stay Eureka The default expiration time is defined as 3 Within a heartbeat , A heartbeat is 30 second , So the expiration time is 90 second

When one of the above two conditions holds , Judge whether the instance is expired , Put the expired instance into the list created above . Note that this is just putting the instance into List in , No actual elimination .

Before actually eliminating tasks , Need to mention eureka Self-protection mechanism , When 15 Within minutes , When the service with heartbeat failure is greater than a certain proportion , Will trigger a self-protection mechanism .

null
This value is in the Eureka Is defined as 85%, Once the self-protection mechanism is triggered ,Eureka Will try to protect the information in its service registry , Data in the service registry is no longer deleted .

null
Parameter meaning :

registrySizeThreshold: Calculate the maximum number of services that can be eliminated according to the threshold
evictionLimit: Minimum quantity remaining after elimination
expiredLeases.size(): Number of culled lists

The above code makes a judgment according to the self-protection mechanism , Use Min The function calculates the minimum value of both , Eliminate a small number of service instances .

for instance , If there are currently 100 A service , Then the elimination threshold is 85, If list There is 60 A service , Then it will eliminate the 60 A service . But if list There is 95 A service , Then only one of them will be eliminated 85 A service , under these circumstances , Another problem will arise ,eureka-server How to determine which services to eliminate , What services are retained ?

null
Here, a random algorithm is used to eliminate , It is guaranteed that all instances of a microservice will not be eliminated continuously . The final call
internalCancel
Method , Actual execution .

null
In fact, the essence of the culling operation is very simple , It's from
gMap
in
remove
Drop this node , And remove... From the cache .

Service offline

Eureka-client

When eureka-client closed , It won't close immediately , You need to send a request to eureka-server, Tell yourself you're going offline . Mainly look at the client
shutdown
Method , Where the key
unregister
Method :

null
call
AbstractJerseyEurekaHttpClient
  Of
cancel
Method

null
send out http Request to tell eureka-server Go offline by yourself .

Eureka-server

call
AbstractInstanceRegistry
in  
cancel
Method :

null
Finally, the same method as in service culling is called ,
remove
It fell off
gMap
Examples in .

Service discovery

Eureka-client

Before learning the source code of service discovery , Write a test case first :

@Autowired
private DiscoveryClient discoveryClient;

@GetMapping(&quot;/find&quot;)
public void test(String id){
 List<ServiceInstance> instances = discoveryClient.getInstances(id);
 System.out.println(instances);
}

call
DiscoveryClient
  Of
getInstances
Method , According to the service id Get the list of service instances :

null
So here's a question , We haven't called microservices yet , When is the service list pulled or cached to the local service list ? The answer is to call... Here
CompositeDiscoveryClient
  Of  
getInstances()
Method :

null
The intermediate calling procedure is omitted :

EurekaDiscoveryClient # getInstances() ->
DiscoveryClient # getInstancesByVipAddress() ->
 # getInstancesByVipAddress() -> // It's not the same way as the above
Applications # getInstancesByVirtualHostName()

see
Applications
Medium
getInstancesByVirtualHostName
Method :

null
We found one called
virtualHostNameAppMap
Of Map All current registrations to... Have been saved in the collection eureka List of services for .

private final Map<String, VipIndexSupport> virtualHostNameAppMap;

in other words , When we don't call the service manually , There are already values in the set , Description in Eureka-server After the project starts , Will automatically pull the service , And cache the pulled Services .

Then go back to the source , To find out when the service discovery was completed . go back to
DiscoveryClient
This class , The task scheduling thread pool is defined in its construction method
cacheRefreshExecutor
, After definition , call
initScheduledTask
Method :

null
In this thread in , Called
refreshRegistry()
Method :

null
stay
fetchRegistry
In the method , Perform real service list pull :

null
stay
fetchRegistry
In the method , First judge whether to perform incremental pull or full pull :

1、 Pull in full

When the cache is
null
, Or the data inside is empty , Or mandatory , Carry out a full pull , perform
getAndStoreFullRegistry
Method :

null
2、 Incremental pull

Only pull the modified , perform
getAndUpdateDelta
Method :

null
①②: Send... First http request , To get in eureka-server Set modified or added in

③: Judge , If the set pulled is null, Then pull the whole amount

④: update operation , stay
updateDelta
In the method , Change according to type

null
⑤: For consistency hashcode value , Used to verify eureka-server Whether the collection is the same as the local

null
Judge here , If remote collection hash The value is equal to... In the cache hash value , There is no need to pull , Otherwise, pull again .

Last mention ,
Applications
The following variables defined in , It's all in eureka-server I'm ready for you , Just pull it directly .

private final AbstractQueue<Application> applications;
private final Map<String, Application> appNameApplicationMap;
private final Map<String, VipIndexSupport> virtualHostNameAppMap;
private final Map<String, VipIndexSupport> secureVirtualHostNameAppMap;

Summarize the service discovery process :

  • The service list is not pulled when the service is called , But when the project starts, there are regular tasks to pull , This is in
    DiscoveryClient
    Can be embodied in the construction method of ;
  • Instances of services are not real-time Eureka-server Data in , It is a locally cached data ;
  • Cache update is divided into full pull and incremental pull according to the actual demand .

Cluster information synchronization

Eureka-server

Cluster information synchronization occurs in Eureka-server Between , Previously mentioned in
PeerAwareInstanceRegistryImpl
Class , In execution
register
Method after registering the micro service instance , The cluster information synchronization method is implemented
replicateToPeers
, Analyze the method in detail :

null
First , Traverse cluster nodes , It is used to synchronize information for each cluster information node .

then , call
replicateInstanceActionsToPeers
Method , In this method, according to the specific operation type Action, Select branch , The final call
PeerEurekaNode
Of
register
Method :

null
Finally send http request , But different from the normal registration operation , At this time, set the identification of cluster synchronization to true, The registration information comes from the cluster synchronization .

null
Run to... During the registration process
addInstance
When the method is used , When registering separately
isReplication
The value of is false, Cluster synchronization is true. By this value , It can avoid dead circulation between clusters , The problem of cyclic synchronization .

Last

Come here ,Eureka We have finished the six important parts of the declaration cycle . Due to limited space , I can only talk about the general process , If you want to know more , You might as well look at the source code yourself , After all , Source code is the best teacher .

If it helps you , Guys, you can like it 、 Forwarding , Thank you very much .
official account
Manongshen
, Add a friend , Make a point of praise
原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/178/202206271013476646.html