52 如何 尽可能的减少 自定义ClassLoader 造成的影响

news2024/11/17 21:57:06

前言 

// 呵呵 很快又该总结 2022 了, 希望这一年也能总结出很多收获 

接着 java.lang.Class/java.lang.ClassLoader/InstanceKlass/ClassloaderData 的卸载 

可以先看一下 这一篇文章, 明确一下 上下文 

这里 主要说的是 如果我们的场景中存在自定义的 classloader 的情况下 

应该 怎么尽可能少的减小 自定义classloader 的存在造成潜在的 内存泄漏的风险  

第一是 classloader 的数量的控制, 其次是 一些代码层面的一些控制, 需要明确 

另外 在文章 java.lang.Class/java.lang.ClassLoader/InstanceKlass/ClassloaderData 的卸载 中, 还有一些 可以看到的疑问, 没有提到的, 这里一起看一下 

以下测试用例基于 jdk8, 部分截图基于 jdk9 

测试用例 

测试用例, 这里暂时使用第一个版本的测试用例, 我们再迭代 

/**
 * Test29MultiLoaderContextInvoker
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-19 09:31
 */
public class Test29MultiLoaderContextInvoker {

    // Test29MultiLoaderContextInvoker
    // -Xmx10M -XX:+UseSerialGC -XX:+TraceClassLoading
    // -Xmx10M -XX:+UseSerialGC -XX:+TraceClassUnloading
    public static void main(String[] args) throws Exception {

        ClassLoader appClassloader = Test29MultiLoaderContextInvoker.class.getClassLoader();
        String[] alwaysParentPatterns = new String[]{};
        URL[] classpathes = new URL[]{
                new File("/Users/jerry/IdeaProjects/HelloWorld/target/classes").toURI().toURL()
        };
        Consumer<Throwable> throwableConsumer = (ex) -> {
            ex.printStackTrace();
        };

        int loopCount = 20;
        for (int i = 0; i < loopCount; i++) {
            ChildFirstClassLoader classLoader = new ChildFirstClassLoader(classpathes, appClassloader, alwaysParentPatterns, throwableConsumer);
            Class mainClass = classLoader.loadClass("com.hx.test12.Test29MultiLoaderContextMain");
            Method mainMethod = mainClass.getDeclaredMethod("main", int.class, String[].class);
            mainMethod.invoke(null, i, args);
        }

    }

}

/**
 * Test29MultiLoaderContextInvoker
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-19 09:31
 */
public class Test29MultiLoaderContextMain {

    // hold 1M
    public static byte[] dummyBytes = new byte[1 * 1024 * 1024];

    // Test29MultiLoaderContextInvoker
    public static void main(int idx, String[] args) throws Exception {
        System.out.println(String.format(" Test29MultiLoaderContextMain.main be invoked, idx : %s, args : %s ", idx, args));
        new Thread(() -> {
            try {
                System.out.println(String.format(" bizThread - %s is started ", idx));
                Thread.sleep(10_000);
                System.out.println(String.format(" bizThread - %s is end ", idx));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

}

ChildFirstClassLoader 的引用有哪些 ?

如下, 首先要查询的是 classloader 加载了那些东西, 这里可以看到的是 只是加载了 com.hx.test12.Test29MultiLoaderContextMain

但是 实际不然 其实还有 com.hx.test12.Test29MultiLoaderContextMain 里面的这一个内部类 

com.hx.test12.Test29MultiLoaderContextMain 的类型是没有实例的 

com.hx.test12.Test29MultiLoaderContextMain$$Lambda$3/1032000752 类型存在一个实例, 传递给了 Thread-$N 

其次是当前 Thread 上下文的一些引用 

这里的 target 就是我们上面提到的 com.hx.test12.Test29MultiLoaderContextMain$$Lambda$3/1032000752 的实例 

我们这里关心的是 inheritedAccessControlContext 中的 context 中的第一个 ProtectionDomain 元素, 可以看到的是 引用了一个 ChildFirstClassLoader 

总结一下 我们明显能够看到的有两条路径 

1.  Thread-$N 关联的 target 是一个 com.hx.test12.Test29MultiLoaderContextMain$$Lambda$3/1032000752 的实例, 其 classloader 为 ChildFirstClassLoader 

2. Thread-$N 关联的 inheritedAccessControlContext 中的 context[0] 会关联到 ChildFirstClassLoader

AccessController. inheritedAccessControlContext 是怎么来的? 

上面我们可以看到 com.hx.test12.Test29MultiLoaderContextMain$$Lambda$3/1032000752 的实例也会关联 ChildFirstClassLoader, 那么我们这里是需要取消他对 ChildFirstClassLoader 的关联, 这个还是挺好处理的 

那么另外一个呢? Thread.inheritedAccessControlContext 呢? 

首先我们要看 它的初始化的地方 调用的是 AccessController.getStackAccessControlContext 

AccessController.getStackAccessControlContext  是一个 native 方法 

实现大致是如下, 从遍历当前线程的堆栈, 分别获取 调用的方法对应的 java.lang.Class 的 ProtectionDomain 

分别是 Test29MultiLoaderContextMain 的 ProtectionDomain 和 Test29MultiLoaderContextInvoker 的 ProtectionDomain 

呵呵 既然知道了构造的方式, 那么才有 处理的方式 

输出一下 其中的两个元素, 大致是 

java.security.ProtectionDomain 
{0x00000007bf795450} - klass: 'java/security/ProtectionDomain'
 - ---- fields (total size 5 words):
 - private 'hasAllPerm' 'Z' @12  false
 - private final 'staticPermissions' 'Z' @13  false
 - private 'codesource' 'Ljava/security/CodeSource;' @16  a 'java/security/CodeSource'{0x00000007bf78d5c0} (f7ef1ab8 f7ef168a)
 - private 'classloader' 'Ljava/lang/ClassLoader;' @20  a 'org/apache/flink/util/ChildFirstClassLoader'{0x00000007bf78b450} (f7ef168a f7ef2a91)
 - private 'principals' '[Ljava/security/Principal;' @24  a 'java/security/Principal'[0] {0x00000007bf795488} (f7ef2a91 f7ef1af6)
 - private 'permissions' 'Ljava/security/PermissionCollection;' @28  a 'java/security/Permissions'{0x00000007bf78d7b0} (f7ef1af6 f7ef2a8f)
 - final 'key' 'Ljava/security/ProtectionDomain$Key;' @32  a 'java/security/ProtectionDomain$Key'{0x00000007bf795478} (f7ef2a8f 0)
java.security.ProtectionDomain 
{0x00000007bf8bb638} - klass: 'java/security/ProtectionDomain'
 - ---- fields (total size 5 words):
 - private 'hasAllPerm' 'Z' @12  false
 - private final 'staticPermissions' 'Z' @13  false
 - private 'codesource' 'Ljava/security/CodeSource;' @16  a 'java/security/CodeSource'{0x00000007bf8c1518} (f7f182a3 f7f378cb)
 - private 'classloader' 'Ljava/lang/ClassLoader;' @20  a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x00000007bf9bc658} (f7f378cb f7f182a8)
 - private 'principals' '[Ljava/security/Principal;' @24  a 'java/security/Principal'[0] {0x00000007bf8c1540} (f7f182a8 f7f182aa)
 - private 'permissions' 'Ljava/security/PermissionCollection;' @28  a 'java/security/Permissions'{0x00000007bf8c1550} (f7f182aa f7f182ae)
 - final 'key' 'Ljava/security/ProtectionDomain$Key;' @32  a 'java/security/ProtectionDomain$Key'{0x00000007bf8c1570} (f7f182ae 0)

去掉 ChildFirstClassLoader 的两个引用 

调整 Test29MultiLoaderContextInvoker 如下 

第一个是 新建 MyRunnable 的地方是 Test29MultiLoaderContextInvoker 中, 对应的 classloader 为 AppClassLoader 

第二个是 新建 Thread 的地方也放在了 Test29MultiLoaderContextInvoker, 这样 Thread-$N 的 inheritedAccessControlContext 的 context 中就只会有一个 ProtectionDomain 关联的 classloader 为 AppClassLoader 

/**
 * Test29MultiLoaderContextInvoker
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-19 09:31
 */
public class Test29MultiLoaderContextInvoker {

    // Test29MultiLoaderContextInvoker
    // -Xmx10M -XX:+UseSerialGC -XX:+TraceClassLoading
    // -Xmx10M -XX:+UseSerialGC -XX:+TraceClassUnloading
    public static void main(String[] args) throws Exception {

        ClassLoader appClassloader = Test29MultiLoaderContextInvoker.class.getClassLoader();
        String[] alwaysParentPatterns = new String[]{};
        URL[] classpathes = new URL[]{
                new File("/Users/jerry/IdeaProjects/HelloWorld/target/classes").toURI().toURL()
        };
        Consumer<Throwable> throwableConsumer = (ex) -> {
            ex.printStackTrace();
        };

        int loopCount = 20;
        for (int i = 0; i < loopCount; i++) {
            ChildFirstClassLoader classLoader = new ChildFirstClassLoader(classpathes, appClassloader, alwaysParentPatterns, throwableConsumer);
            Class mainClass = classLoader.loadClass("com.hx.test12.Test29MultiLoaderContextMain");
            Thread runnable = new Thread(new MyRunnable());

            Method mainMethod = mainClass.getDeclaredMethod("main", int.class, Thread.class, String[].class);
            mainMethod.invoke(null, i, runnable, args);
        }

    }

    /**
     * MyRunnable
     *
     * @author Jerry.X.He
     * @version 1.0
     * @date 2021-12-26 14:55
     */
    private static class MyRunnable implements Runnable {
        @Override
        public void run() {
            try {
                int idx = 0;
                System.out.println(String.format(" bizThread - %s is started ", idx));
                Thread.sleep(10_000);
                System.out.println(String.format(" bizThread - %s is end ", idx));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

调整 Test29MultiLoaderContextMain 如下 

/**
 * Test29MultiLoaderContextInvoker
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2021-12-19 09:31
 */
public class Test29MultiLoaderContextMain {

    // hold 1M
    public static byte[] dummyBytes = new byte[1 * 1024 * 1024];

    // Test29MultiLoaderContextInvoker
    public static void main(int idx, Thread runnable, String[] args) throws Exception {
        System.out.println(String.format(" Test29MultiLoaderContextMain.main be invoked, idx : %s, args : %s ", idx, args));
        runnable.start();
    }

}

看一下 是否符合我们上面的期望 

然后 重新执行, 日志如下, 可以看到, 在执行 20 个循环的过程中存在 Test29MultiLoaderContextMain 的卸载, 这个就是 我们期望达到的结果 

 Test29MultiLoaderContextMain.main be invoked, idx : 0, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 1, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 2, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 3, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 4, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0098828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0098028]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0097828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0097028]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c007e828]
 Test29MultiLoaderContextMain.main be invoked, idx : 5, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 6, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 7, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 8, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 9, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 10, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c007e828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0097028]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0097828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0098028]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0098828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0099028]
 Test29MultiLoaderContextMain.main be invoked, idx : 11, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 12, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 13, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 14, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 15, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 16, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0098828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0098028]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0097828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0097028]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c007e828]
[Unloading class com.hx.test12.Test29MultiLoaderContextMain 0x00000007c0099828]
 Test29MultiLoaderContextMain.main be invoked, idx : 17, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 18, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 Test29MultiLoaderContextMain.main be invoked, idx : 19, args : [Ljava.lang.String;@2bea5ab4 
 bizThread - 0 is started 
 // after 10s 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 
 bizThread - 0 is end 

最终的结论如下 

1. 控制 自定义 ClassLoader 的数量, 避免比较麻烦的细节控制 

2. 自定义 ClassLoader 加载的 class 需要尽可能的单纯, 少去 access 其他的上下文, 把控的成本很高, 有一定的经验要求 

完 

参考

java.lang.Class/java.lang.ClassLoader/InstanceKlass/ClassloaderData 的卸载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/97787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flask + echarts 轻松解决 nginx 日志可视化

最近&#xff0c;线上的业务系统不太稳定&#xff0c;需要分析下访问情况&#xff0c;能拿到的数据只有 nginx 服务器的访问日志&#xff0c;不过难不倒我&#xff0c;用合适的工具&#xff0c;分分钟做出图形化展示&#xff0c;看看怎么做的吧 思路 nginx 访问日志&#xff…

9 CPP结构体注意事项

注意&#xff1a; 1 结构名是标识符 2 结构体的成员可以是任意数据类型 3 定义结构体描述的代码可以放在程序的人和地方&#xff0c;一般放在main函数的上面或头文件中。 4 结构体成员可以用C的类&#xff08;如string&#xff09;&#xff0c;但是不提倡。 5 在C中&#…

java:AES加密和解密

java&#xff1a;AES加密和解密 1 前言 对称加密&#xff0c;即单秘钥加密&#xff0c;指加密和解密的过程中&#xff0c;使用相同的秘钥&#xff0c;相比于非对称加密&#xff0c;因仅有一把钥匙&#xff0c;故而速度更快&#xff0c;更适合解密大文件&#xff08;常见于如视…

ESP32的arduino IDE代码使用flash download tool进行烧录

ESP32的arduino IDE代码使用flash download tool进行烧录前言arduino代码烧录arduino下载了一些什么文件flash download tool工具烧录总结前言 最近遇到用户在使用 arduino IDE开发环境编写了ESP32的代码&#xff0c;希望提供编写好的程序给用户烧录&#xff0c;但是又不希望让…

Kotlin + SpringBoot + JPA 服务端开发

Kotlin SpringBoot JPA 服务端开发 本篇主要介绍一下 kotlin springboot的服务端开发环境搭建 1.概述 Kotlin 是一个基于JVM的编程语言, 是IDEA开发工具 jetbrains 公司开发的语言,也被google选为android开发的首选语言, 因为它是完全兼容Java的 所以也可以做后端开发 比如…

[Java] 如何理解和设置ThreadPoolExecutor三大核心属性?什么情况下工作线程数会突破核心线程数?任务拒绝策略都有哪些?

文章目录前言ThreadPoolExecutor类是什么&#xff1f;ThreadPoolExecutor的三大核心属性1. 核心线程数&#xff08;corePoolSize&#xff09;属性2. 任务队列&#xff08;workQueue&#xff09;属性3. 最大线程数&#xff08;maximumPoolSize&#xff09;属性总结&#xff1a;T…

【开发百宝箱之猿如意使用指南】「工欲成其事,必先利其器」一文教你如何通过“猿如意”便捷的使用数据库管理工具DBeaver

开发百宝箱之猿如意使用指南欢迎您使用“猿如意”百宝箱大家科普一下什么是猿如意&#xff1f;赶快趁热下载个【猿如意】吧每个程序猿值得拥有的学习开发工作必备“良药”没有猿如意的“我们”&#xff08;猿如意帮我们解决了哪些问题&#xff1f;&#xff09;【如何快速下载自…

非零基础自学Golang 第12章 接口与类型 12.2 接口的创建与实现 12.2.1 接口创建

非零基础自学Golang 文章目录非零基础自学Golang第12章 接口与类型12.2 接口的创建与实现12.2.1 接口创建第12章 接口与类型 12.2 接口的创建与实现 Go语言接口是方法的集合&#xff0c;使用接口是实现模块化的重要方式。 下面将重点介绍如何创建和实现一个Go语言接口。 12…

Pytest用例执行的先后顺序

[内部资源] 想拿年薪30W的软件测试人员&#xff0c;这份资料必须领取~ 温馨提示 「本篇约1600字&#xff0c;看完需3-5分钟&#xff0c;学习学半小时&#xff0c;加油&#xff01;」 先看普通函数运行顺序 import pytestdef test_one():print("我是清安")def tes…

React学习27(react-redux多组件共享数据)

项目结构 准备工作 1&#xff09;定义一个person组件&#xff0c;和count组件通过redux共享数据 2&#xff09;为person组件编写&#xff1a;reducer &#xff0c;action和contant常量 3&#xff09;重点&#xff1a;Person的reducer和Count的reducer要用combineReducers进行…

深度学习-优化器

优化器 文章目录优化器1. 引言1. SGD1.1 vanilla SGD1.2 SGD with Momentum1.3 SGD with Nesterov Acceleration2. AdaGrad3. RMSProp4. AdaDelta5. Adam优化器选择出处1. 引言 优化算法可以分成一阶优化和二阶优化算法&#xff0c;其中一阶优化就是指的梯度算法及其变种&#…

Linux——vi,vim的使用

三种模式 正常模式 以vi或vim打开一个档案就直接进入一般模式了(这是默认的模式)。在这个模式中&#xff0c;你可以使用 【上下左右】 按键来移动光标&#xff0c;你可以使用 【删除字符】或 【删除整行】来处理档案内容&#xff0c;也可以使用 【复制&#xff0c;粘贴】来处…

3D激光里程计其三:点云畸变补偿

3D激光里程计其三&#xff1a;点云畸变补偿1. 产生原因2. 补偿方法Reference: 深蓝学院-多传感器融合 1. 产生原因 一帧点云&#xff1a;通常指雷达内部旋转一周扫描得到的点的集合。 优点&#xff1a;有足够数量的点云才能进行匹配&#xff0c;且一周正好是周围环境的完整采…

认识Java中的异常处理

文章目录Java异常处理异常体系的介绍常见运行时异常常见编译时异常Java异常处理 异常体系的介绍 什么事异常处理? 异常是程序在“编译”或者“执行”的过程中可能出现的问题&#xff0c;比如: 数组索引越界、空指针异常、 日期格式化异常&#xff0c;等… 注意&#xff1a;语…

常用损失函数

常见损失函数 文章目录常见损失函数引言回归1. 均方差2.平均绝对误差(MAE)3. 均方根误差(RMSE)4. 交叉熵分类二分类多分类引言 无论在机器学习还是深度领域中,损失函数都是一个非常重要的知识点。损失函数&#xff08;Loss Function&#xff09;是用来估量模型的预测值 f(x) 与…

Eslint 8.23 Flat Config 新配置迁移升级指南

前言 直入正题&#xff0c;eslint 目前为止的配置文件格式&#xff08; 如 .eslintrc.js &#xff09; 存在很多无法避免的历史问题&#xff1a; 配置格式混乱&#xff0c;层层不明确的继承&#xff0c;不易理解。 插件配置时不支持实体运用&#xff08;不能传 function / ob…

学完框架后的反思—为什么要使用框架?

学习前端也有一定的时间了,最近在网上看到了一个问题让我反思了很久——为什么要使用前端框架? 我发现自己当初学习框架时并没有想那么多,只是看中了其在业界企业的应用,大部分公司开发页面基本上都是使用框架进行开发的,而最为被大厂广泛接受的就是 React 框架,所以我当…

二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮 DPPE-PEG-N3简介,可用于药物传递、基因转染和生物分子修饰。

二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮 DPPE-PEG-N3 中文名称&#xff1a;二棕榈酰磷酯酰乙醇胺-聚乙二醇-叠氮基 英文名称&#xff1a;DPPE-PEG-N3 英文别名&#xff1a; 1,2-dipalmitoyl-sn-glycero-3-phosphoethanolamine-PEG-Azide 分子量&#xff08;PEG&#xff09;&a…

Linux——任务调度

at定时任务 基本介绍 at命令是一次性定时计划任务&#xff0c;at地守护线程atd会以后台模式运行&#xff0c;检查作业队列来运行默认情况下&#xff0c;atd守护进程没60秒检查作业队列&#xff0c;有作业时&#xff0c;会检查作业运行时间&#xff0c;如果时间于当前时间匹配…

Dubbo 1 分布式系统中的相关概念 1.2 集群和 分布式

Dubbo 【黑马程序员Dubbo快速入门&#xff0c;Java分布式框架dubbo教程】 1 分布式系统中的相关概念 文章目录Dubbo1 分布式系统中的相关概念1.2 集群和 分布式1.2.1 集群和分布式1.2.2 集群和分布式 【互联网 中】1.2 集群和 分布式 1.2.1 集群和分布式 集群&#xff1a;很…