百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

面试官:Dubbo服务重启下线,消费者继续调用,都异常了怎么办?

bigegpt 2024-09-06 17:57 46 浏览

我们有没有想过一个问题,在分布式系统中,服务节点重启的时候,消费者流量继续调用该节点,那么这部分调用全部异常,对于线上用户来说,系统故障?

针对这种情况,我们可以这么想:Dubbo服务重启下线的时候,消费者还会不会继续调用此服务节点?

答案当然是不会

今天就结合dubbo源码一起来捋一捋,先上一个目录:

  • 一、操作系统的优雅停机
  • 二、JVM的优雅下线
  • 三、Spring容器的优雅下线
  • 四、Dubbo的优雅停机
  • 五、结语


一、操作系统的优雅停机

优雅停机是指在停止应用时,执行一系列"操作"保证应用正常关闭。这些操作包括拒绝新请求和新连接、关闭服务注册、等待已有请求执行完成、关闭线程池、关闭连接、释放资源等。

优雅停机可以避免非正常关闭程序可能造成的任务被抛弃、数据丢失、应用异常等问题。优雅停机本质上是进程即将关闭前执行的一些额外流程。

操作系统本身也有对优雅停机的思考。

我们停止一个进程是,会使用kill -9和kill -15命令。但是,我们一般不建议使用kill -9。

这是因为kill -9命令很强硬,它会向操作系统内核发出SIGKILL信号,该信号直接停止进程,不能被阻塞或者忽略。

kill -9显然不那么优雅,如果在发出SIGKILL信号的时候,进程还有未处理完成的任务,这时候任务就会被丢弃或者终止导致数据的不可预知错误。

使用kill -15就不一样了,这时候发给系统内核的是一个SIGTERM信号。

当进程接收到SIGTERM信号时,具体要如何处理是由进程自己决定,进程就可以拒绝外部新的任务并完成已有任务后再停止。

在Docker中,docker stop相当于kill -15,他会向容器内的进程发送SIGTERM信号,在10S之后(可通过参数指定)再发送SIGKILL信号。

而docker kill就像kill -9,直接发送SIGKILL信号。


二、JVM的优雅下线

我们Java应用运行时就是一个独立的进程,它的关闭也即是JVM的关闭。

JVM的关闭也分为正常关闭、强制关闭、异常关闭。

JVM的正常关闭是Java程序优雅停机的关键,正常关闭的过程中,JVM可以做一系列预善后工作,比如线程池、连接池任务的完成和资源的释放等。

JVM还预留了钩子机制,供我们开发自行处理一些特定操作。

这种钩子机制就是JDK中提供的shutdown hook,它有一个方法Java.Runtime.addShutdownHook(Thread hook),可以注册一个JVM关闭的钩子。

比如我们写一个关闭【看点代码再上班】书库的钩子,如下:

package com.tin.example.shutdown.hook;

/**
 * title: ShutdownHookTest
 * <p>
 * description:
 *
 * @author tin @公众号【看点代码再上班】 on 2022/4/5 下午12:27
 */
public class JVMShutdownHookTest {
    public static void main(String[] args) throws Exception {
        Runtime.getRuntime().addShutdownHook(new Thread(JVMShutdownHookTest::doSomething));

        while (true) {
            System.out.println("i am running...");
            Thread.sleep(500);
        }
    }

    /**
     * 停机前处理事项
     */
    private static void doSomething() {
        System.out.println("关闭【看点代码再上班】书库。");
    }
}

执行命令:

ericli@EricdeAir IntelliJIdea2020.1 % jps
5458 Jps
5394 KotlinCompileDaemon
2986 QuorumPeerMain
5451 Launcher
5452 JVMShutdownHookTest
3023 ZooKeeperMain
ericli@EricdeAir IntelliJIdea2020.1 % kill 5452

本地测试控制台结果输出如下:

从测试输出可以看出,当我执行kill pid(实际也是kill -15命令)命名时,我们的Java程序会先执行ShutDownHook钩子逻辑,最后才退出进程。

三、Spring容器的优雅下线

Spring的优雅下线也使用到了JVM的ShutdownHook。

首先,在application context被load时会注册一个ShutdownHook。这个ShutdownHook会在进程退出前执行销毁bean、容器的销毁等操作。

同时,Spring除了销毁bean等操作之外,还会发出一个ContextClosedEvent事件,很多基于Spring容器的三方框架都可以监听这个事件实现更多的优雅停机操作。

比如,我们可以监听Spring的事件:

@Override
    public void onApplicationContextEvent(ApplicationContextEvent event) {
        if (event instanceof ContextClosedEvent) {
            //自定一些容器关闭前业务要进行的操作
            onContextClosedEvent((ContextClosedEvent) event);
        }
    }

四、Dubbo的优雅停机

Dubbo的优雅停机从起初的2.5版本到当前的2.7,经历了多次优化。

最终版本也同样采用到了Spring的ApplicationContextEventListener接口,监听Spring容器的close事件。

在org.apache.dubbo.config.spring.extension.SpringExtensionFactory类中,就有关于ShutDownHook注册的相关代码:

特别有意思的是,这里有一个issue,看②处代码,它是一个关闭注册的动作,①处则是一个注册的动作。

既要注册又要注销,这是为什么呢?

Dubbo的开发者们已经发现,Spring容器下的Dubbo进程会触发两次关机钩子。

一次在org.apache.dubbo.config.bootstrap.DubboBootstrap中:

另一次是在org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener中通过监听spring的关闭事件来关闭dubbo服务:

这会导致什么后果?

答:会导致高并**况下,一些任务线程获取不到资源而抛异常。

这个issue中也讲得很明白了,如下:

?

dubbo没有关闭完,数据库连接池已经关闭,导致应用并发高的时候很多没跑完的dubbo线程拿不到数据库连接抛出异常。

If there is an exception, please attach the exception trace:

msg:DUBBO服务异常 remoteHost:xxx.xx.xxx.xxx service:com.xxx.service.xxxService method:xxx message:nested exception is org.apache.ibatis.exceptions.PersistenceException:

Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection; nested exception is java.sql.SQLException: HikariDataSource HikariDataSource (HikariPool-1) has been closed.

?

这也是Dubbo优化多次后做出的处理结果,以下文章描述得非常详细,值得一看:

https://www.cnkirito.moe/dubbo-gracefully-shutdown

我们再来看看Dubbo ShutdownHook都做了哪些事情。

org.apache.dubbo.config.DubboShutdownHook#doDestroy

1. 注册中心数据销毁:关闭注册中心中本节点对应的提供者地址以及订阅数据。

2. 协议流程数据销毁:销毁所有协议,包括所有已经暴露和引用的服务,释放协议所占用的所有资源,比如连接和端口。

Dubbo销毁注册中心的同时还需要注销Spring容器,这部分工作由Spring的ShutdownHook完成。

org.springframework.context.support.AbstractApplicationContext#doClose

发布close事件,就有利于我们应用层自己做一些特殊处理逻辑,比如Dubbo关闭注册中心。

在关闭Spring容器之前,Dubbo已经关闭注册中心上对应的服务注册,不再接收新请求进来,同时还会把本地未完成的任务做完,最后才销毁bean以及关闭进程。

结语

看到这里请安排个“三连”(分享、点赞、在看)再走吧,坚持创作不容易,你的正反馈是我坚持输出的最强大动力,谢谢!

相关推荐

Linux gron 命令使用详解(linux gminer)

简介gron是一个独特的命令行工具,用于将JSON数据转换为离散的、易于grep处理的赋值语句格式。它的名字来源于"grepableon"或"grepable...

【Linux】——从0到1的学习,让你熟练掌握,带你玩转Linu

学习Linux并掌握Java环境配置及SpringBoot项目部署是一个系统化的过程,以下是从零开始的详细指南,帮助你逐步掌握这些技能。一、Linux基础入门1.安装Linux系统选择发行版:推荐...

Linux常用的shell命令汇总(linux中shell的作用)

本文介绍Linux系统下常用的系统级命令,包括软硬件查看、修改命令,有CPU、内存、硬盘、网络、系统管理等命令。说明命令是在Centos6.464位的虚拟机系统进行测试的。本文介绍的命令都会在此C...

零成本搭建个人加密文件保险柜(适用于 Win11 和 Linux)

不依赖收费软件操作简单,小白也能跟着做支持双系统,跨平台使用实现数据加密、防删除、防泄露内容通俗无技术门槛,秒懂秒用使用工具简介我们将使用两个核心工具:工具名用途系统支持Veracrypt创建加密虚...

如何在 Linux 中使用 Gzip 命令?(linux怎么用gzip命令)

gzip(GNUzip)是Linux系统中一个开源的压缩工具,用于压缩和解压缩文件。它基于DEFLATE算法,广泛应用于文件压缩、备份和数据传输。gzip生成的文件通常带有.gz后缀,压缩效率...

Linux 必备的20个核心知识点(linux内核知识点)

学习和使用Linux所必备的20个核心知识点。这些知识点涵盖了从基础操作到系统管理和网络概念,是构建扎实Linux技能的基础。Linux必备的20个知识点1.Linux文件系统层级标...

谷歌 ChromeOS 已支持 7z、iso、tar 文件格式

IT之家6月21日消息,谷歌ChromeOS在管理文件方面进行了改进,新增了对7z、iso和tar等格式的支持。从5月的ChromeOS101更新开始,ChromeOS...

如何在 Linux 中提取 Tar Bz2 文件?

在深入解压方法之前,我们先来了解.tar.bz2文件的本质。.tar.bz2是一种组合文件格式,包含两个步骤:Tar(TapeArchive):tar是一种归档工具,用于将多个文件或目录打包...

如何在 CentOS 7/8 上安装 Kitematic Docker 管理器

Kitematic是一款流行的Docker图形界面管理平台,适用于Ubuntu、macOS和Windows操作系统。然而,其他发行版(如CentOS、OpenSUSE、Fedora、R...

Nacos3.0重磅来袭!全面拥抱AI,单机及集群模式安装详细教程!

之前和大家分享过JDK17的多版本管理及详细安装过程,然后在项目升级完jdk17后又发现之前的注册和配置中心nacos又用不了,原因是之前的nacos1.3版本的,版本太老了,已经无法适配当前新的JD...

爬虫搞崩网站后,程序员自制“Zip炸弹”反击,6刀服务器成功扛住4.6万请求

在这个爬虫横行的时代,越来越多开发者深受其害:有人怒斥OpenAI的爬虫疯狂“偷”数据,7人团队十年心血的网站一夜崩溃;也有人被爬虫逼到极限,最后只好封掉整个巴西的访问才勉强止血。但本文作者却走...

Ubuntu 操作系统常用命令详解(ubuntu必学的60个命令)

UbuntuLinux是一款流行的开源操作系统,广泛应用于服务器、开发、学习等场景。命令行是Ubuntu的灵魂,也是高效、稳定管理系统的利器。本文按照各大常用领域,详细总结Ubuntu必学...

Linux面板8.0.54 测试版-已上线(linux主机面板)

Linux面板8.0.54测试版【增加】[网站]Java项目新增刷新列表按钮【增加】[网站]PHP项目-Apache-服务新增守护进程功能【增加】[网站]Python项目创建/删除网站时新增同时创建...

开源三剑客——构建私有云世界的基石

公共云原生的浪潮正在席卷这个世界,亚马逊AWS、谷歌GCP和微软的Azure年收入增长超过了30%,越来越多的公司和个人开始将自己的服务部署到云环境中,大型数据中心的规模经济带来了成本的降低,可以在保...

2.2k star,一款业界领先的私有云+在线文档管理系统

简介kodbox可道云(原KodExplorer)是业内领先的企业私有云和在线文档管理系统,为个人网站、企业私有云部署、网络存储、在线文档管理、在线办公等提供安全可控,简便易用、可高度定制的私有云产品...