Reprint please indicate the source: blog.csdn.net/forezp/arti… This article is from Fang Zhipeng’s blog

Some concepts of Eureka

  • When the Eureka client registers with the Eureka Server, it provides its own metadata, such as IP address, port, health indicator URL, home page, and so on.

  • 1. Eureka customers send a heartbeat every 30 seconds to Renew their service. Renew the contract to inform the Eureka Server that the Eureka customer still exists and there is no problem. Normally, if Eureka Server does not receive a renewal from an Eureka customer within 90 seconds, it removes the instance from its registry. You are not advised to change the renewal interval.

  • Fetch Registries The Eureka client obtains the registry information from the server and caches it locally. The client uses this information to find other services to make remote calls. This registration list information is updated regularly (every 30 seconds). The information returned from the registration list may be different from the information cached by the Eureka client. The Eureka client processes the information automatically. If for any reason the registry information does not match in time, the Eureka client retrieves the entire registry information. The Eureka server caches the registry information, and the entire registry as well as the information for each application is compressed so that the compressed content is identical to the uncompressed content. The Eureka client and Eureka server can communicate using JSON/XML format. By default, the Eureka client uses compressed JSON format to retrieve the registry information.

  • Cancel: Service goes offline The Eureka client sends a cancellation request to the Eureka server when the program is closed. After the request is sent, the client instance information is removed from the server’s instance registry. The offline request will not automatically completed, it needs to call the following content: DiscoveryManager. GetInstance () shutdownComponent ();

  • By default, when a Eureka client does not send a service renewal, i.e. heartbeat, to the Eureka server for 90 consecutive seconds, the Eureka server will remove the service instance from the service registry, i.e. service rejection.

Eureka’s highly available architecture

The high-level architecture of Eureka is shown in the Eureka open source documentation at github.com/Netflix/eur… .

High-level architecture diagram for Eureka

As can be seen from the figure, there are two roles in this system, namely Eureka Server and Eureka Client. Eureka Client is divided into Applicaton Service and Application Client, namely Service provider and Service consumer. Each zone has one Eureka cluster, and each zone has at least one Eureka server that can handle zone failures in case the server crashes.

Eureka Client registers with Eureka Serve and sends some of its Client information to Eureka Serve. The Eureka Client then renewed the service by sending a heartbeat to the Eureka Serve every 30 seconds. If the client continues to fail to renew, it will be removed from the server registry in about 90 seconds. Registration information and renewals are copied to all Eureka Serve nodes in the cluster. Eureka clients from any region can look up registry information (this happens every 30 seconds). Based on this registry information, the Application Client can remotely invoke the Applicaton Service to consume services.

Register service

Service registration: The Eureka Client submits its service information to the Eureka Server, including the IP address, port, and service ID. If the Eureka Client does not write the service ID, the default is ${spring.application.name}.

Service registration is actually very simple. When the Eureka Client starts, it sends its service information to the Eureka Server. Now take a quick look at the source code. Under Maven’s dependencies, find the Eureka-client-1.6.2.jar package. In com.Net flix. Discovery package, there is a class DiscoveryClient, which contains methods related to Eureka Client to Eureka Server. DiscoveryClient implements the EurekaClient interface, which is a singleton pattern, while EurekaClient inherits the LookupService interface. The relationship between them is shown in the figure.

Write the picture description here

In the DiscoveryClient class there is a service registration method, Register (), which registers with the Eureka Client through an Http request. The code is as follows:

boolean register() throws Throwable {
        logger.info(PREFIX + appPathIdentifier + ": registering 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;
    }Copy the code

Tracing the Register () method continues in the DiscoveryClient class, which is called by the Run () method of the InstanceInfoReplicator class, which implements the Runnable interface, The run() method looks like this:

 public void run() {
        try {
            discoveryClient.refreshInstanceInfo();

            Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
            if(dirtyTimestamp ! =null) { discoveryClient.register(); instanceInfo.unsetIsDirty(dirtyTimestamp); }}catch (Throwable t) {
            logger.warn("There was a problem with the instance info replicator", t);
        } finally {
            Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS); scheduledPeriodicRef.set(next); }}Copy the code

The InstanceInfoReplicator class, which has an initScheduledTasks() method, is used during DiscoveryClient initialization. This method enables obtaining information about the service registration list. To register with the Eureka Server, enable registration and the scheduled task of renewing the Eureka Server service. The code is as follows:

private void initScheduledTasks() {
       ...// Omit the task scheduler to get the registry code
        if (clientConfig.shouldRegisterWithEureka()) {
         ... 
            // Heartbeat timer
            scheduler.schedule(
                    new TimedSupervisorTask(
                            "heartbeat",
                            scheduler,
                            heartbeatExecutor,
                            renewalIntervalInSecs,
                            TimeUnit.SECONDS,
                            expBackOffBound,
                            new HeartbeatThread()
                    ),
                    renewalIntervalInSecs, TimeUnit.SECONDS);

            // InstanceInfo replicator
            instanceInfoReplicator = new InstanceInfoReplicator(
                    this,
                    instanceInfo,
                    clientConfig.getInstanceInfoReplicationIntervalSeconds(),
                    2); // burstSize

            statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {
                @Override
                public String getId() {
                    return "statusChangeListener";
                }

                @Override
                public voidnotify(StatusChangeEvent statusChangeEvent) { instanceInfoReplicator.onDemandUpdate(); }}; . }Copy the code

Then take a look at the Eureka Server code in Maven’s Eureka-Core :1.6.2 JAR package. If you open the com.Net flix. Eureka package, you can easily find another EurekaBootStrap class. BootStrapContext has the permission to initialize it first, so look at this class first.

protected void initEurekaServerContext() throws Exception {

 ...// omit the code
   PeerAwareInstanceRegistry registry;
        if (isAws(applicationInfoManager.getInfo())) {
           ...// Omit code, if AWS code
        } else {
            registry = new PeerAwareInstanceRegistryImpl(
                    eurekaServerConfig,
                    eurekaClient.getEurekaClientConfig(),
                    serverCodecs,
                    eurekaClient
            );
        }

        PeerEurekaNodes peerEurekaNodes = getPeerEurekaNodes(
                registry,
                eurekaServerConfig,
                eurekaClient.getEurekaClientConfig(),
                serverCodecs,
                applicationInfoManager
        );
 }Copy the code

Which PeerAwareInstanceRegistryImpl and PeerEurekaNodes two class to see its name, should be related to service registry and Eureka Server high availability. Track PeerAwareInstanceRegistryImpl class, first in the class has a register () method, this method provides the registration, and after registration information synchronization to other Eureka Server service. The code is as follows:

public void register(final InstanceInfo info, final boolean isReplication) {
        int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
        if(info.getLeaseInfo() ! =null && info.getLeaseInfo().getDurationInSecs() > 0) {
            leaseDuration = info.getLeaseInfo().getDurationInSecs();
        }
        super.register(info, leaseDuration, isReplication);
        replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
    }Copy the code

In the super.register(info, leaseDuration, isReplication) method, click on subclass AbstractInstanceRegistry to find more details, where the registration list information is saved in a Map. The replicateToPeers() method, which is synchronized to other Peers of other Eureka servers, tracks the code and finds that it iterates through the Peers and registers with all Peers. Finally, it executes the register() method of class PeerEurekaNodes. This method synchronizes the registration information to other nodes by performing a task as follows:

  public void register(final InstanceInfo info) throws Exception {
        long expiryTime = System.currentTimeMillis() + getLeaseRenewalOf(info);
        batchingDispatcher.process(
                taskId("register", info),
                new InstanceReplicationTask(targetHost, Action.Register, info, null.true) {
                    public EurekaHttpResponse<Void> execute() {
                        return replicationClient.register(info);
                    }
                },
                expiryTime
        );
    }Copy the code

Track after a series of source code, can be found PeerAwareInstanceRegistryImpl register () method implements the service registration, and the other had the Peer Server nodes synchronize the registration information, So who called the register() method? According to the previous analysis of Eureka Client, Eureka Client registers with The Eureka Server through HTTP, so the Eureka Server must provide a registered interface for the Eureka Client to call. So PeerAwareInstanceRegistryImpl register () method certainly will ultimately be exposed the call to Http interface. In the Idea development tool, you can quickly locate the addInstance () method of the ApplicationResource class, the interface registered by the service, by holding down Alt + left mouse button:


@POST
    @Consumes({"application/json"."application/xml"})
    public Response addInstance(InstanceInfo info,
                                @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {

    ...// omit the code
               registry.register(info, "true".equals(isReplication));
        return Response.status(204).build();  // 204 to be backwards compatible
    }Copy the code

Renew service

Service renewal is very similar to service registration. According to the previous analysis, service registration is started after Eureka Client starts, and the scheduled task of service renewal is started at the same time. Renew () method in Eureka-client-1.6.2.jar DiscoveryClient class renew() method:

  /** * Renew with the eureka service by making the appropriate REST call */
    boolean renew() {
        EurekaHttpResponse<InstanceInfo> httpResponse;
        try {
            httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
            logger.debug("{} - Heartbeat status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
            if (httpResponse.getStatusCode() == 404) {
                REREGISTER_COUNTER.increment();
                logger.info("{} - Re-registering apps/{}", PREFIX + appPathIdentifier, instanceInfo.getAppName());
                return register();
            }
            return httpResponse.getStatusCode() == 200;
        } catch (Throwable e) {
            logger.error("{} - was unable to send heartbeat!", PREFIX + appPathIdentifier, e);
            return false; }}Copy the code

In addition, the renewal interface of the service side is under InstanceResource class of com.net Flix. Eureka package, and the interface method is renewLease(), which is a REST interface. Most of the code presentation has been omitted to reduce class size. There is a registry.renew() method, i.e. service renewal, with the following code:

@PUT public Response renewLease(... Parameter omitted) {... Boolean isSuccess=registry.renew(app.getName(),id, isFromReplicaNode); . Code omission}Copy the code

Readers can follow the code of Registry.renew all the way into depth. I will not tell you more here. In addition, there are two parameters for service renewal that can be configured, namely, the time when Eureka Client sends the renewed heartbeat and the time when Eureka Server does not receive the heartbeat and excludes the instance. By default, these two parameters are 30 seconds and 90 seconds respectively. The official advice is not to change them. If you have special requirements, you only need to modify the following parameters on the Eureka Client and Eureka Server:

eureka.instance.leaseRenewalIntervalInSeconds
eureka.instance.leaseExpirationDurationInSecondsCopy the code

Finally, access to the service registration list, service offline and service removal is not here for source tracking interpretation, because similar to service registration and renewal, interested friends can look at the source code, in-depth understanding. Overall, reading the source code, you can see that the overall architecture is exactly the same as the eureka highly available architecture diagram in the previous section.

Why is it so slow for Eureka Client to register an instance

  • The Eureka Client does not register with the Eureka Server immediately after it is started. It has a delay to register with the Server. Source in eureka – the client – 1.6.2. Jar DefaultEurekaClientConfig class, the code is as follows:
public int getInitialInstanceInfoReplicationIntervalSeconds() {
    return configInstance.getIntProperty(
        namespace + INITIAL_REGISTRATION_REPLICATION_DELAY_KEY, 40).get();
 }Copy the code
  • Had the response of the Server cache Eureka response cache Server maintenance update every 30 seconds, can Eureka. By changing the configuration Server. ResponseCacheUpdateIntervalMs to modify. So even if the instance is just registered, it will not appear in the result of calling the/Eureka/apps REST endpoint.

  • Eureka Server Refreshes the cache. The Eureka client retains the cache of registry information. This cache is updated every 30 seconds (as mentioned earlier). Because of this, it may take 30 seconds for the client to decide to flush its local cache and discover other newly registered instances.

  • The LoadBalancer Refresh Ribbon LoadBalancer gets the service registry information from the local Eureka Client. The Ribbon itself also maintains a local cache to avoid calling a local client for each request. This cache refresh every 30 seconds (can be made of ribbon. ServerListRefreshInterval configuration). As a result, it may take more than 30 seconds to use the newly registered instance.

In summary, a newly registered instance, especially one that starts quickly (the default delay is 40 seconds), cannot be immediately detected by Eureka Server. In addition, the newly registered Eureka Client cannot be immediately called by other services because the caller does not get the new registration list in time due to various caches.

Eureka’s mode of self-protection

When a new Eureka Server appears, it tries to get all instance registry information from adjacent nodes. If there is a problem getting information from the Peer node, Eureka Serve tries other Peer nodes. If the server is able to successfully acquire all instances, the update threshold that should be received is set based on this information. If at any time, Eureka Serve receives less than the percentage of renewals specified for this value (less than 85% within 15 minutes by default), the server starts the self-protection mode, that is, the server does not remove the registration list information.

In this way, if the Eureka Client cannot be renewed due to network problems of the Eureka Server, the registration list of the Eureka Client cannot be deleted. In other words, the Eureka Client can be consumed by other services.

The resources

Cloud. Spring. IO/spring – clou…

Github.com/Netflix/eur…

Github.com/Netflix/eur…

Xujin.org/sc/sc-eurek…

Blog.abhijitsarkar.org/technical/n…

Nobodyiam.com/2016/06/25/…