当前位置: 首页 > news >正文

SpringCloud源码分析 (Eureka-Server-处理客户端删除状态请求) (六)

文章目录

      • 1.处理客户端删除状态请求
        • 1.1 InstanceResource.deleteStatusUpdate()
        • 1.2 PeerAwareInstanceRegistryImpl.deleteStatusOverride()
        • 1.3 AbstractInstanceRegistry.deleteStatusOverride()
        • 1.4 PeerAwareInstanceRegistryImpl.replicateToPeers()

1.处理客户端删除状态请求

一但客户端发起了删除状态请求,服务端就不在接受来自该客户端的心跳请求。

1.1 InstanceResource.deleteStatusUpdate()

    @DELETE
    @Path("status")
    public Response deleteStatusUpdate(
            @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
            @QueryParam("value") String newStatusValue,
            @QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
            //isReplication:是否是服务端之间的复制同步请求
    		//newStatusValue:我们知道客户端发起删除状态请求的时候,不会传状态,所以这里为null
 	  		 //lastDirtyTimestamp:客户端的最新修改时间戳
        try {
	        // 根据微服务名称和instanceId获取注册表中的实例信息
            if (registry.getInstanceByAppAndId(app.getName(), id) == null) {
                logger.warn("Instance not found: {}/{}", app.getName(), id);
                return Response.status(Status.NOT_FOUND).build();
            }

			// 为了保证服务健壮性,其实客户端发过来时newStatusValue是null
            InstanceStatus newStatus = newStatusValue == null ? InstanceStatus.UNKNOWN : InstanceStatus.valueOf(newStatusValue);
            // 删除覆盖状态
            boolean isSuccess = registry.deleteStatusOverride(app.getName(), id,
                    newStatus, lastDirtyTimestamp, "true".equals(isReplication));

            if (isSuccess) {
                logger.info("Status override removed: {} - {}", app.getName(), id);
                return Response.ok().build();
            } else {
                logger.warn("Unable to remove status override: {} - {}", app.getName(), id);
                return Response.serverError().build();
            }
        } catch (Throwable e) {
            logger.error("Error removing instance's {} status override", id);
            return Response.serverError().build();
        }
    }

在这里插入图片描述

1.2 PeerAwareInstanceRegistryImpl.deleteStatusOverride()

删除覆盖状态方法

    @Override
    public boolean deleteStatusOverride(String appName, String id,
                                        InstanceStatus newStatus,
                                        String lastDirtyTimestamp,
                                        boolean isReplication) {
         // 调用父类先本地删除覆盖状态
        if (super.deleteStatusOverride(appName, id, newStatus, lastDirtyTimestamp, isReplication)) {
        // 删除成功后,将删除覆盖状态的操作同步给集群中的其他节点
            replicateToPeers(Action.DeleteStatusOverride, appName, id, null, null, isReplication);
            return true;
        }
        return false;
    }

在这里插入图片描述

1.3 AbstractInstanceRegistry.deleteStatusOverride()

本地删除状态

    @Override
    public boolean deleteStatusOverride(String appName, String id,
                                        InstanceStatus newStatus,
                                        String lastDirtyTimestamp,
                                        boolean isReplication) {
        try {
     	    // 读锁
            read.lock();
            STATUS_OVERRIDE_DELETE.increment(isReplication);
            // 获取注册表中的实例信息
            Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
            Lease<InstanceInfo> lease = null;
            if (gMap != null) {
                lease = gMap.get(id);
            }
            if (lease == null) {
                return false;
            } else {
            	// 刷新续约时间
                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);
                }

				// 根据instanceId删除对应的覆盖状态
                InstanceStatus currentOverride = overriddenInstanceStatusMap.remove(id);
                if (currentOverride != null && info != null) {
                	// 新instanceInfo的覆盖状态为UNKNOWN
                    info.setOverriddenStatus(InstanceStatus.UNKNOWN);
                    // 更新instanceInfo的状态,但不记录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()) {
                        info.setLastDirtyTimestamp(replicaDirtyTimestamp);
                    }
                    // 设置行为类型为修改
                    info.setActionType(ActionType.MODIFIED);
                    // 放入最近更新队列
                    recentlyChangedQueue.add(new RecentlyChangedItem(lease));
                    // 更新服务端的最新修改时间
                    info.setLastUpdatedTimestamp();
                    // 缓存失效
                    invalidateCache(appName, info.getVIPAddress(), info.getSecureVipAddress());
                }
                return true;
            }
        } finally {
            read.unlock();
        }
    }

1.4 PeerAwareInstanceRegistryImpl.replicateToPeers()

删除状态操作同步给集群中其他节点

在这里插入图片描述

/**
 * Replicates all eureka actions to peer eureka nodes except for replication
 * traffic to this node.
 * 将所有eureka操作复制到对等eureka节点,但复制到该节点的流量除外。
 */
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) {//是否是Server之间的复制请求,此时还是客户端发起的请求,所以是false
            numberOfReplicationsLastMin.increment();
        }
        // If it is a replication already, do not replicate again as this will create a poison replication 
        // 如果已经是复制,则不要再次复制,因为这将创建有毒复制
        // peerEurekaNodes代表的就是当前Eureka Server的集群
        if (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {
            return;
        }

        for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {
	        //遍历集群中所有的节点
	        
            // If the url represents this host, do not replicate to yourself.
            // 如果URL代表此主机,请不要复制到您自己。
            if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
                continue;
            }
            //将对eureka的操作行为复制给其他eureka节点
            replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
        }
    } finally {
        tracer.stop();
    }
}

replicateInstanceActionsToPeers()

    private void replicateInstanceActionsToPeers(Action action, String appName,
                                                 String id, InstanceInfo info, InstanceStatus newStatus,
                                                 PeerEurekaNode node) {
        try {
            InstanceInfo infoFromRegistry = null;
            CurrentRequestVersion.set(Version.V2);
            switch (action) {
                case Cancel:
                    node.cancel(appName, id);
                    break;
                case Heartbeat:
                    InstanceStatus overriddenStatus = overriddenInstanceStatusMap.get(id);
                    infoFromRegistry = getInstanceByAppAndId(appName, id, false);
                    node.heartbeat(appName, id, infoFromRegistry, overriddenStatus, false);
                    break;
                case Register:
                    node.register(info);
                    break;
                case StatusUpdate:
                    infoFromRegistry = getInstanceByAppAndId(appName, id, false);
                    node.statusUpdate(appName, id, newStatus, infoFromRegistry);
                    break;
                case DeleteStatusOverride:
                    infoFromRegistry = getInstanceByAppAndId(appName, id, false);
                    node.deleteStatusOverride(appName, id, infoFromRegistry);
                    break;
            }
        } catch (Throwable t) {
            logger.error("Cannot replicate information to {} for action {}", node.getServiceUrl(), action.name(), t);
        }
    }

AbstractJerseyEurekaHttpClient.cancal()

AbstractJerseyEurekaHttpClient.sendHeartBeat()

AbstractJerseyEurekaHttpClient.register()

AbstractJerseyEurekaHttpClient.statusUpdate()

AbstractJerseyEurekaHttpClient.deleteStatusOverride()

相关文章:

  • 微信小程序开发01 双线程模型:为什么小程序不用浏览器的线程模型?
  • 用Python破解WiFi密码,只需要1行代码,太刺激了
  • Linux基础学习笔记(十三)——文件的格式化处理
  • 微信小程序开发02 授权模型: 小程序的用户体系与 OAuth 规范
  • codeforces:E. Madoka and The Best University【因数list + 分析拆解 + 公因数特性 + 欧拉函数】
  • 华为OD 社招(Java后端)一面
  • DDD - 理论到落地从统一语言开始
  • 【LeetCode 48】旋转图像
  • 计算机网络.第五节课.笔记.以太网、CSMA/CD、VLAN
  • 运行时数据区域
  • 机器学习----k-means聚类
  • 姿态分析开源工具箱MMPose使用示例:人体姿势估计
  • 如何安装虚拟机
  • ICP问题 SVD方法推导(Markdown版)
  • java基于ssm+vue+elementui的水果生鲜销售购物商城
  • JavaScript 如何正确处理 Unicode 编码问题!
  • (三)从jvm层面了解线程的启动和停止
  • CAP理论的例子讲解
  • ES学习笔记(12)--Symbol
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Java的Interrupt与线程中断
  • KMP算法及优化
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Mysql数据库的条件查询语句
  • Nacos系列:Nacos的Java SDK使用
  • Protobuf3语言指南
  • Vue.js 移动端适配之 vw 解决方案
  • Vue2.x学习三:事件处理生命周期钩子
  • 产品三维模型在线预览
  • 初识 beanstalkd
  • 欢迎参加第二届中国游戏开发者大会
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 设计模式走一遍---观察者模式
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 微信小程序实战练习(仿五洲到家微信版)
  • 一个SAP顾问在美国的这些年
  • 最近的计划
  • Spring Batch JSON 支持
  • ​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​
  • "无招胜有招"nbsp;史上最全的互…
  • #数学建模# 线性规划问题的Matlab求解
  • $.type 怎么精确判断对象类型的 --(源码学习2)
  • (2)(2.10) LTM telemetry
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (Java数据结构)ArrayList
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (汇总)os模块以及shutil模块对文件的操作
  • (三分钟)速览传统边缘检测算子
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)ORM