The foreword 0.
- Springboot version: 2.1.9.RELEASE
- Springcloud version: Greenwich.SR4
1. Process the deletion request
The server handles client state change and state deletion requests in the InstanceResource class
// InstanceResource.class
public Response deleteStatusUpdate(
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
@QueryParam("value") String newStatusValue,
@QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
// isReplication: indicates whether synchronous replication is performed by cluster nodes
// newStatusValue: null when the client initiates the deletion state
// lastDirtyTimestamp: last modified timestamp (dirty)
try {
if (registry.getInstanceByAppAndId(app.getName(), id) == null) {
// Query the service instance information in the local registry. If no service instance information is found, 404 is returned
logger.warn("Instance not found: {}/{}", app.getName(), id);
return Response.status(Status.NOT_FOUND).build();
}
// newStatusValue = null, so newStatus = UNKNOWN
InstanceStatus newStatus = newStatusValue == null ? InstanceStatus.UNKNOWN : InstanceStatus.valueOf(newStatusValue);
// 2 Handle deletion status
boolean isSuccess = registry.deleteStatusOverride(app.getName(), id,
newStatus, lastDirtyTimestamp, "true".equals(isReplication));
if (isSuccess) {
logger.info("Status override removed: {} - {}", app.getName(), id);
// 200 is returned on success
return Response.ok().build();
} else {
// Failure to process returns 500
logger.warn("Unable to remove status override: {} - {}", app.getName(), id);
returnResponse.serverError().build(); }}catch (Throwable e) {
logger.error("Error removing instance's {} status override", id);
// Handle an exception and return 500
returnResponse.serverError().build(); }}Copy the code
2. Handle the deletion status
// PeerAwareInstanceRegistryImpl.class
public boolean deleteStatusOverride(String appName, String id,
InstanceStatus newStatus,
String lastDirtyTimestamp,
boolean isReplication) {
// 3 Call the parent class to handle the delete state method
if (super.deleteStatusOverride(appName, id, newStatus, lastDirtyTimestamp, isReplication)) {
// 4 Synchronize the data to the cluster node
replicateToPeers(Action.DeleteStatusOverride, appName, id, null.null, isReplication);
return true;
}
return false;
}
Copy the code
3. The parent class handles the delete state method
// AbstractInstanceRegistry.class
public boolean deleteStatusOverride(String appName, String id,
InstanceStatus newStatus,
String lastDirtyTimestamp,
boolean isReplication) {
try {
// Open the read lock
read.lock();
STATUS_OVERRIDE_DELETE.increment(isReplication);
// Get service lease information
Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
Lease<InstanceInfo> lease = null;
if(gMap ! =null) {
// Get instance lease information
lease = gMap.get(id);
}
if (lease == null) {
// If not, return false
return false;
} else {
// Refresh the lease expiration time
// The client is still alive, so update the lease expiration time
lease.renew();
InstanceInfo info = lease.getHolder();
// Lease is always created with its instance info object.
// This log statement is provided as a safeguard, in case this invariant is violated.
if (info == null) {
logger.error("Found Lease without a holder for instance id {}", id);
}
/ / to get cover state, and deleted from the overriddenInstanceStatusMap
InstanceStatus currentOverride = overriddenInstanceStatusMap.remove(id);
if(currentOverride ! =null&& info ! =null) {
// Set the coverage state of the instance information to UNKNOWN
info.setOverriddenStatus(InstanceStatus.UNKNOWN);
// Sets the state of the instance information, but does not mark dirty
info.setStatusWithoutDirty(newStatus);
long replicaDirtyTimestamp = 0;
if(lastDirtyTimestamp ! =null) {
replicaDirtyTimestamp = Long.valueOf(lastDirtyTimestamp);
}
// If the replication's dirty timestamp is more than the existing one, just update
// it to the replica's.
if (replicaDirtyTimestamp > info.getLastDirtyTimestamp()) {
// If the latest modified timestamp of the client instance is larger than the latest modified timestamp of the corresponding instance information in the local registry (dirty)
// Update the local to the client
info.setLastDirtyTimestamp(replicaDirtyTimestamp);
}
// Set the behavior type to change
info.setActionType(ActionType.MODIFIED);
// The instance change lease information is put into the latest change queue
recentlyChangedQueue.add(new RecentlyChangedItem(lease));
// Set the latest modified timestamp of the local instance information
info.setLastUpdatedTimestamp();
// invalidate the corresponding cache
invalidateCache(appName, info.getVIPAddress(), info.getSecureVipAddress());
}
return true; }}finally{close read lock read.unlock(); }}Copy the code
4. Synchronize the data to the cluster node
This is covered in EurekaServer- handling client registration requests
5. Process status change requests
// InstanceResource.class
public Response statusUpdate(
@QueryParam("value") String newStatus,
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
@QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
try {
if (registry.getInstanceByAppAndId(app.getName(), id) == null) {
logger.warn("Instance not found: {}/{}", app.getName(), id);
// Query instance information in the local registry. If no instance is found, 404 is returned
return Response.status(Status.NOT_FOUND).build();
}
// 6 Handle the change status
boolean isSuccess = registry.statusUpdate(app.getName(), id,
InstanceStatus.valueOf(newStatus), lastDirtyTimestamp,
"true".equals(isReplication));
if (isSuccess) {
logger.info("Status updated: {} - {} - {}", app.getName(), id, newStatus);
// 200 is returned on success
return Response.ok().build();
} else {
logger.warn("Unable to update status: {} - {} - {}", app.getName(), id, newStatus);
// Return 500 on success
returnResponse.serverError().build(); }}catch (Throwable e) {
logger.error("Error updating instance {} for status {}", id,
newStatus);
// Handle an exception and return 500
returnResponse.serverError().build(); }}Copy the code
6. Handle the change status
// PeerAwareInstanceRegistryImpl.class
public boolean statusUpdate(final String appName, final String id,
final InstanceStatus newStatus, String lastDirtyTimestamp,
final boolean isReplication) {
// 7 calls the parent class to handle the change status method
if (super.statusUpdate(appName, id, newStatus, lastDirtyTimestamp, isReplication)) {
// 4 Synchronize the data to the cluster node
replicateToPeers(Action.StatusUpdate, appName, id, null, newStatus, isReplication);
return true;
}
return false;
}
Copy the code
7. The parent class handles change-state methods
// AbstractInstanceRegistry.class
public boolean statusUpdate(String appName, String id,
InstanceStatus newStatus, String lastDirtyTimestamp,
boolean isReplication) {
try {
// Open the read lock
read.lock();
STATUS_UPDATE.increment(isReplication);
// Get service lease information
Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
Lease<InstanceInfo> lease = null;
if(gMap ! =null) {
// Get instance lease information
lease = gMap.get(id);
}
if (lease == null) {
return false;
} else {
// Refresh the lease expiration time
// Update the lease expiration time because the client is still alive
lease.renew();
InstanceInfo info = lease.getHolder();
// Lease is always created with its instance info object.
// This log statement is provided as a safeguard, in case this invariant is violated.
if (info == null) {
logger.error("Found Lease without a holder for instance id {}", id);
}
if((info ! =null) && !(info.getStatus().equals(newStatus))) {
// If the local instance information is not empty and the status is inconsistent with that requested by the client
// Mark service as UP if needed
if (InstanceStatus.UP.equals(newStatus)) {
// If the state is to change to UP and the instance is started for the first time, the startup time is recorded
lease.serviceUp();
}
// This is NAC overriden status
/ / to overriddenInstanceStatusMap saving changes
overriddenInstanceStatusMap.put(id, newStatus);
// Set it for transfer of overridden status to replica on
// replica start up
// Instance info Sets the overwrite status
info.setOverriddenStatus(newStatus);
long replicaDirtyTimestamp = 0;
// Sets the state of the instance information, but does not record the dirty timestamp
info.setStatusWithoutDirty(newStatus);
if(lastDirtyTimestamp ! =null) {
replicaDirtyTimestamp = Long.valueOf(lastDirtyTimestamp);
}
// If the replication's dirty timestamp is more than the existing one, just update
// it to the replica's.
if (replicaDirtyTimestamp > info.getLastDirtyTimestamp()) {
// If the latest modified timestamp of the client instance is larger than the latest modified timestamp of the corresponding instance information in the local registry (dirty)
// Update the local to the client
info.setLastDirtyTimestamp(replicaDirtyTimestamp);
}
// Set the behavior type to change
info.setActionType(ActionType.MODIFIED);
// Put into the latest change queue
recentlyChangedQueue.add(new RecentlyChangedItem(lease));
// Set the latest modified timestamp of the local instance information
info.setLastUpdatedTimestamp();
// invalidate the corresponding cache
invalidateCache(appName, info.getVIPAddress(), info.getSecureVipAddress());
}
return true; }}finally {
// Close the read lockread.unlock(); }}Copy the code