Cancel(服务下线)

在Service Provider服务shut down的时候,需要及时通知Eureka Server把自己剔除,从而避免其它客户端调用已经下线的服务,导致服务不可用。

com.netflix.discovery.DiscoveryClient中shutdown()的867行。

/**
* Shuts down Eureka Client. Also sends a deregistration request to the
* eureka server.
*/
@PreDestroy
@Override
public synchronized void shutdown() {
if (isShutdown.compareAndSet(false, true)) {
logger.info("Shutting down DiscoveryClient ...");
if (statusChangeListener != null && applicationInfoManager != null) {
applicationInfoManager.unregisterStatusChangeListener(statusChangeListener.getId());
}
cancelScheduledTasks();
// If APPINFO was registered
if (applicationInfoManager != null && clientConfig.shouldRegisterWithEureka()) {
applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
//调用下线接口
unregister();
}
if (eurekaTransport != null) {
eurekaTransport.shutdown();
}
heartbeatStalenessMonitor.shutdown();
registryStalenessMonitor.shutdown();
logger.info("Completed shut down of DiscoveryClient");
}
}

@PreDestroy注解或shutdown()的方法是服务下线的入口

com.netflix.discovery.DiscoveryClientunregister()897

void unregister() {
// It can be null if shouldRegisterWithEureka == false
if(eurekaTransport != null && eurekaTransport.registrationClient != null) {
try {
logger.info("Unregistering ...");
//发送服务下线请求
EurekaHttpResponse<Void> httpResponse = eurekaTransport.registrationClient.cancel(instanceInfo.getAppName(), instanceInfo.getId());
logger.info(PREFIX + appPathIdentifier + " - deregister status: " + httpResponse.getStatusCode());
} catch (Exception e) {
logger.error(PREFIX + appPathIdentifier + " - de-registration failed" + e.getMessage(), e);
}
}
}

Eureka Server服务下线实现细节

  1. com.netflix.eureka.resources.InstanceResource中的280行中的cancelLease()方法

@DELETE
public Response cancelLease(
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
//调用cancel
boolean isSuccess = registry.cancel(app.getName(), id,
"true".equals(isReplication));
if (isSuccess) {
logger.debug("Found (Cancel): " + app.getName() + " - " + id);
return Response.ok().build();
} else {
logger.info("Not Found (Cancel): " + app.getName() + " - " + id);
return Response.status(Status.NOT_FOUND).build();
}
}

com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl中的376

@Override
public boolean cancel(final String appName, final String id,
final boolean isReplication) {
if (super.cancel(appName, id, isReplication)) {
//服务下线成功后,同步更新信息到其它Eureka Server节点
replicateToPeers(Action.Cancel, appName, id, null, null, isReplication);
synchronized (lock) {
if (this.expectedNumberOfRenewsPerMin > 0) {
// Since the client wants to cancel it, reduce the threshold (1 for 30 seconds, 2 for a minute)
this.expectedNumberOfRenewsPerMin = this.expectedNumberOfRenewsPerMin - 2;
this.numberOfRenewsPerMinThreshold =
(int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());
}
}
return true;
}
return false;
}

在com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl中的618行,主要接口实现方式和register基本一致:首先更新自身Eureka Server中服务的状态,再同步到其它Eureka Server中。

private void replicateToPeers(Action action, String appName, String id,
InstanceInfo info /* optional */,
InstanceStatus newStatus /* optional */, boolean isReplication) {
Stopwatch tracer = action.getTimer().start();
try {
if (isReplication) {
numberOfReplicationsLastMin.increment();
}
// If it is a replication already, do not replicate again as this will create a poison replication
if (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {
return;
}
// 同步把服务信息同步到其它的Eureka Server中
for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {
// If the url represents this host, do not replicate to yourself.
if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
continue;
}
//根据action做相应操作的同步
replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
}
} finally {
tracer.stop();
}
}

Eureka服务下线(Cancel)源码分析的更多相关文章

  1. Netty 心跳服务之 IdleStateHandler 源码分析

    前言:Netty 提供的心跳介绍 Netty 作为一个网络框架,提供了诸多功能,比如我们之前说的编解码,Netty 准备很多现成的编解码器,同时,Netty 还为我们准备了网络中,非常重要的一个服务- ...

  2. 【一起学源码-微服务】Nexflix Eureka 源码九:服务续约源码分析

    前言 前情回顾 上一讲 我们讲解了服务发现的相关逻辑,所谓服务发现 其实就是注册表抓取,服务实例默认每隔30s去注册中心抓取一下注册表增量数据,然后合并本地注册表数据,最后有个hash对比的操作. 本 ...

  3. SpringCloud(4)---Ribbon服务调用,源码分析

    SpringCloud(4)---Ribbon 本篇模拟订单服务调用商品服务,同时商品服务采用集群部署. 注册中心服务端口号7001,订单服务端口号9001,商品集群端口号:8001.8002.800 ...

  4. Netty源码分析 (三)----- 服务端启动源码分析

    本文接着前两篇文章来讲,主要讲服务端类剩下的部分,我们还是来先看看服务端的代码 /** * Created by chenhao on 2019/9/4. */ public final class ...

  5. Netty源码分析 (十二)----- 心跳服务之 IdleStateHandler 源码分析

    什么是心跳机制? 心跳说的是在客户端和服务端在互相建立ESTABLISH状态的时候,如何通过发送一个最简单的包来保持连接的存活,还有监控另一边服务的可用性等. 心跳包的作用 保活Q:为什么说心跳机制能 ...

  6. Netty之旅三:Netty服务端启动源码分析,一梭子带走!

    Netty服务端启动流程源码分析 前记 哈喽,自从上篇<Netty之旅二:口口相传的高性能Netty到底是什么?>后,迟迟两周才开启今天的Netty源码系列.源码分析的第一篇文章,下一篇我 ...

  7. eureka client服务续约源码分析

    必备知识: 1.定时任务 ScheduledExecutorService public class demo { public static void main(String[] args){ Sc ...

  8. ActivityManagerService服务线程启动源码分析【转】

    本文转载自:http://blog.csdn.net/yangwen123/article/details/8177702 Android系统服务线程都驻留在SystemServer进程中,由Syst ...

  9. 【springcloud】1.微服务之springcloud-》eureka源码分析之请叫我灵魂画师。。。

随机推荐

  1. Matlab 中的varargin/nargin varargout/nargout

    Varargin = var+ arg+ in = variable length(可变长) input argument(输入参数) list(列表) :允许调用该函数时根据需要改变输入参数的个数 ...

  2. Android OCR文字识别 实时扫描手机号(极速扫描单行文本方案)

    身份证识别:https://github.com/wenchaosong/OCR_identify 遇到一个需求,要用手机扫描纸质面单,获取面单上的手机号,最后决定用tesseract这个开源OCR库 ...

  3. Delphi:ADOConnection连接SQLServer自动断网问题解决

    =============================== 解决方法一:异常时关闭连接,WinXP,win7 32位大部分情况都是起作用的,不过在有些windows操作系统下(如家庭版)不起作用, ...

  4. BZOJ 1789 Y形项链(思维)

    这题类似于1787,最后的节点一定是两点的LCA,这里也就是两个字符串的最长公共前缀. # include <cstdio> # include <cstring> # inc ...

  5. BZOJ1008:[HNOI2008]越狱——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1008 监狱有连续编号为1...N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中 ...

  6. HDU 2089 不要62 | 暴力(其实是个DP)

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=2089 题解: 暴力水过 #include<cstdio> #include<algor ...

  7. CodeForces.158A Next Round (水模拟)

    CodeForces.158A Next Round (水模拟) 题意分析 校赛水题的英文版,坑点就是要求为正数. 代码总览 #include <iostream> #include &l ...

  8. javascript push 和 concat 的区别

    array.push(item1,item2,item3...) array.concat(item1,item2,item3...) 1. push和concat的元素都既可以是普通元素(任意类型) ...

  9. 负载均衡配置(基于Nginx)

    以下是基于nginx进行负载均衡配置的流程: 服务器配置如下: 1.  安装nginx的服务器:192.168.1.1 2.  nginx配置负载均衡位置及端口:192.168.1.1 80端口 3. ...

  10. cuda环境下安装opencv出现nvcc warning : The 'compute_11'

    警告打印: nvcc warning : The 'compute_11', 'compute_12', 'compute_13', 'sm_11', 'sm_12', and 'sm_13' arc ...