dolphinscheduler 2.0.6 负载均衡源码

news2025/2/24 9:28:08

目录

  • 🐬官网介绍
  • 🐬负载均衡
    • 🐠加权随机(random)
    • 🐠平滑轮询(roundrobin)
    • 🐠线性负载(lowerweight)
  • 🐵其它

🐬官网介绍


官网资料,从1.3开始到3.1都是一样的,源码将以2.0.6版本为例,官网介绍如下:
在这里插入图片描述

🐬负载均衡


可以修改master.properties,指定负载均衡算法:
在这里插入图片描述
MasterConfig.java默认为线性负载lowerweight
在这里插入图片描述
HostManagerConfig.java根据配置选择算法:
在这里插入图片描述
父类CommonHostManager,获取有效的worker列表:
在这里插入图片描述

🐠加权随机(random)


RandomSelector
RandomHostManager
AbstractSelector

在这里插入图片描述

🐠平滑轮询(roundrobin)


用到了原子类

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
  • AtomicBoolean
    在这里插入图片描述

    /*
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     * Written by Doug Lea with assistance from members of JCP JSR-166
     * Expert Group and released to the public domain, as explained at
     * http://creativecommons.org/publicdomain/zero/1.0/
     */
    
    package java.util.concurrent.atomic;
    import sun.misc.Unsafe;
    
    /**
     * A {@code boolean} value that may be updated atomically. See the
     * {@link java.util.concurrent.atomic} package specification for
     * description of the properties of atomic variables. An
     * {@code AtomicBoolean} is used in applications such as atomically
     * updated flags, and cannot be used as a replacement for a
     * {@link java.lang.Boolean}.
     *
     * @since 1.5
     * @author Doug Lea
     */
    public class AtomicBoolean implements java.io.Serializable {
        private static final long serialVersionUID = 4654671469794556979L;
        // setup to use Unsafe.compareAndSwapInt for updates
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final long valueOffset;
    
        static {
            try {
                valueOffset = unsafe.objectFieldOffset
                    (AtomicBoolean.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
        private volatile int value;
    
        /**
         * Creates a new {@code AtomicBoolean} with the given initial value.
         *
         * @param initialValue the initial value
         */
        public AtomicBoolean(boolean initialValue) {
            value = initialValue ? 1 : 0;
        }
    
        /**
         * Creates a new {@code AtomicBoolean} with initial value {@code false}.
         */
        public AtomicBoolean() {
        }
    
        /**
         * Returns the current value.
         *
         * @return the current value
         */
        public final boolean get() {
            return value != 0;
        }
    
        /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful. False return indicates that
         * the actual value was not equal to the expected value.
         */
        public final boolean compareAndSet(boolean expect, boolean update) {
            int e = expect ? 1 : 0;
            int u = update ? 1 : 0;
            return unsafe.compareAndSwapInt(this, valueOffset, e, u);
        }
    
        /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * <p><a href="package-summary.html#weakCompareAndSet">May fail
         * spuriously and does not provide ordering guarantees</a>, so is
         * only rarely an appropriate alternative to {@code compareAndSet}.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful
         */
        public boolean weakCompareAndSet(boolean expect, boolean update) {
            int e = expect ? 1 : 0;
            int u = update ? 1 : 0;
            return unsafe.compareAndSwapInt(this, valueOffset, e, u);
        }
    
        /**
         * Unconditionally sets to the given value.
         *
         * @param newValue the new value
         */
        public final void set(boolean newValue) {
            value = newValue ? 1 : 0;
        }
    
        /**
         * Eventually sets to the given value.
         *
         * @param newValue the new value
         * @since 1.6
         */
        public final void lazySet(boolean newValue) {
            int v = newValue ? 1 : 0;
            unsafe.putOrderedInt(this, valueOffset, v);
        }
    
        /**
         * Atomically sets to the given value and returns the previous value.
         *
         * @param newValue the new value
         * @return the previous value
         */
        public final boolean getAndSet(boolean newValue) {
            boolean prev;
            do {
                prev = get();
            } while (!compareAndSet(prev, newValue));
            return prev;
        }
    
        /**
         * Returns the String representation of the current value.
         * @return the String representation of the current value
         */
        public String toString() {
            return Boolean.toString(get());
        }
    
    }
    
    
  • AtomicLong
    在这里插入图片描述

    /*
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     * Written by Doug Lea with assistance from members of JCP JSR-166
     * Expert Group and released to the public domain, as explained at
     * http://creativecommons.org/publicdomain/zero/1.0/
     */
    
    package java.util.concurrent.atomic;
    import java.util.function.LongUnaryOperator;
    import java.util.function.LongBinaryOperator;
    import sun.misc.Unsafe;
    
    /**
     * A {@code long} value that may be updated atomically.  See the
     * {@link java.util.concurrent.atomic} package specification for
     * description of the properties of atomic variables. An
     * {@code AtomicLong} is used in applications such as atomically
     * incremented sequence numbers, and cannot be used as a replacement
     * for a {@link java.lang.Long}. However, this class does extend
     * {@code Number} to allow uniform access by tools and utilities that
     * deal with numerically-based classes.
     *
     * @since 1.5
     * @author Doug Lea
     */
    public class AtomicLong extends Number implements java.io.Serializable {
        private static final long serialVersionUID = 1927816293512124184L;
    
        // setup to use Unsafe.compareAndSwapLong for updates
        private static final Unsafe unsafe = Unsafe.getUnsafe();
        private static final long valueOffset;
    
        /**
         * Records whether the underlying JVM supports lockless
         * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
         * method works in either case, some constructions should be
         * handled at Java level to avoid locking user-visible locks.
         */
        static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8();
    
        /**
         * Returns whether underlying JVM supports lockless CompareAndSet
         * for longs. Called only once and cached in VM_SUPPORTS_LONG_CAS.
         */
        private static native boolean VMSupportsCS8();
    
        static {
            try {
                valueOffset = unsafe.objectFieldOffset
                    (AtomicLong.class.getDeclaredField("value"));
            } catch (Exception ex) { throw new Error(ex); }
        }
    
        private volatile long value;
    
        /**
         * Creates a new AtomicLong with the given initial value.
         *
         * @param initialValue the initial value
         */
        public AtomicLong(long initialValue) {
            value = initialValue;
        }
    
        /**
         * Creates a new AtomicLong with initial value {@code 0}.
         */
        public AtomicLong() {
        }
    
        /**
         * Gets the current value.
         *
         * @return the current value
         */
        public final long get() {
            return value;
        }
    
        /**
         * Sets to the given value.
         *
         * @param newValue the new value
         */
        public final void set(long newValue) {
            value = newValue;
        }
    
        /**
         * Eventually sets to the given value.
         *
         * @param newValue the new value
         * @since 1.6
         */
        public final void lazySet(long newValue) {
            unsafe.putOrderedLong(this, valueOffset, newValue);
        }
    
        /**
         * Atomically sets to the given value and returns the old value.
         *
         * @param newValue the new value
         * @return the previous value
         */
        public final long getAndSet(long newValue) {
            return unsafe.getAndSetLong(this, valueOffset, newValue);
        }
    
        /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful. False return indicates that
         * the actual value was not equal to the expected value.
         */
        public final boolean compareAndSet(long expect, long update) {
            return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
        }
    
        /**
         * Atomically sets the value to the given updated value
         * if the current value {@code ==} the expected value.
         *
         * <p><a href="package-summary.html#weakCompareAndSet">May fail
         * spuriously and does not provide ordering guarantees</a>, so is
         * only rarely an appropriate alternative to {@code compareAndSet}.
         *
         * @param expect the expected value
         * @param update the new value
         * @return {@code true} if successful
         */
        public final boolean weakCompareAndSet(long expect, long update) {
            return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
        }
    
        /**
         * Atomically increments by one the current value.
         *
         * @return the previous value
         */
        public final long getAndIncrement() {
            return unsafe.getAndAddLong(this, valueOffset, 1L);
        }
    
        /**
         * Atomically decrements by one the current value.
         *
         * @return the previous value
         */
        public final long getAndDecrement() {
            return unsafe.getAndAddLong(this, valueOffset, -1L);
        }
    
        /**
         * Atomically adds the given value to the current value.
         *
         * @param delta the value to add
         * @return the previous value
         */
        public final long getAndAdd(long delta) {
            return unsafe.getAndAddLong(this, valueOffset, delta);
        }
    
        /**
         * Atomically increments by one the current value.
         *
         * @return the updated value
         */
        public final long incrementAndGet() {
            return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;
        }
    
        /**
         * Atomically decrements by one the current value.
         *
         * @return the updated value
         */
        public final long decrementAndGet() {
            return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L;
        }
    
        /**
         * Atomically adds the given value to the current value.
         *
         * @param delta the value to add
         * @return the updated value
         */
        public final long addAndGet(long delta) {
            return unsafe.getAndAddLong(this, valueOffset, delta) + delta;
        }
    
        /**
         * Atomically updates the current value with the results of
         * applying the given function, returning the previous value. The
         * function should be side-effect-free, since it may be re-applied
         * when attempted updates fail due to contention among threads.
         *
         * @param updateFunction a side-effect-free function
         * @return the previous value
         * @since 1.8
         */
        public final long getAndUpdate(LongUnaryOperator updateFunction) {
            long prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsLong(prev);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
        /**
         * Atomically updates the current value with the results of
         * applying the given function, returning the updated value. The
         * function should be side-effect-free, since it may be re-applied
         * when attempted updates fail due to contention among threads.
         *
         * @param updateFunction a side-effect-free function
         * @return the updated value
         * @since 1.8
         */
        public final long updateAndGet(LongUnaryOperator updateFunction) {
            long prev, next;
            do {
                prev = get();
                next = updateFunction.applyAsLong(prev);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
        /**
         * Atomically updates the current value with the results of
         * applying the given function to the current and given values,
         * returning the previous value. The function should be
         * side-effect-free, since it may be re-applied when attempted
         * updates fail due to contention among threads.  The function
         * is applied with the current value as its first argument,
         * and the given update as the second argument.
         *
         * @param x the update value
         * @param accumulatorFunction a side-effect-free function of two arguments
         * @return the previous value
         * @since 1.8
         */
        public final long getAndAccumulate(long x,
                                           LongBinaryOperator accumulatorFunction) {
            long prev, next;
            do {
                prev = get();
                next = accumulatorFunction.applyAsLong(prev, x);
            } while (!compareAndSet(prev, next));
            return prev;
        }
    
        /**
         * Atomically updates the current value with the results of
         * applying the given function to the current and given values,
         * returning the updated value. The function should be
         * side-effect-free, since it may be re-applied when attempted
         * updates fail due to contention among threads.  The function
         * is applied with the current value as its first argument,
         * and the given update as the second argument.
         *
         * @param x the update value
         * @param accumulatorFunction a side-effect-free function of two arguments
         * @return the updated value
         * @since 1.8
         */
        public final long accumulateAndGet(long x,
                                           LongBinaryOperator accumulatorFunction) {
            long prev, next;
            do {
                prev = get();
                next = accumulatorFunction.applyAsLong(prev, x);
            } while (!compareAndSet(prev, next));
            return next;
        }
    
        /**
         * Returns the String representation of the current value.
         * @return the String representation of the current value
         */
        public String toString() {
            return Long.toString(get());
        }
    
        /**
         * Returns the value of this {@code AtomicLong} as an {@code int}
         * after a narrowing primitive conversion.
         * @jls 5.1.3 Narrowing Primitive Conversions
         */
        public int intValue() {
            return (int)get();
        }
    
        /**
         * Returns the value of this {@code AtomicLong} as a {@code long}.
         */
        public long longValue() {
            return get();
        }
    
        /**
         * Returns the value of this {@code AtomicLong} as a {@code float}
         * after a widening primitive conversion.
         * @jls 5.1.2 Widening Primitive Conversions
         */
        public float floatValue() {
            return (float)get();
        }
    
        /**
         * Returns the value of this {@code AtomicLong} as a {@code double}
         * after a widening primitive conversion.
         * @jls 5.1.2 Widening Primitive Conversions
         */
        public double doubleValue() {
            return (double)get();
        }
    
    }
    
    

真正的源码RoundRobinSelector…神马玩意!!!!
在这里插入图片描述

🐠线性负载(lowerweight)


默认的负载均衡算法,估计也是真正使用的,另外两个就是凑数的,select方法都是单独写的
在这里插入图片描述
ExecutorDispatcher:只有LowerWeightHostManager重写了select(ExecutionContext context)
在这里插入图片描述

  • LowerWeightRoundRobin
    在这里插入图片描述
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *    http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.apache.dolphinscheduler.server.master.dispatch.host.assign;
    
    import java.util.Collection;
    import java.util.Comparator;
    import java.util.List;
    import java.util.stream.Collectors;
    
    import com.google.common.collect.Lists;
    
    /**
     * lower weight round robin
     */
    public class LowerWeightRoundRobin extends AbstractSelector<HostWeight> {
    
        /**
         * select
         *
         * @param sources sources
         * @return HostWeight
         */
        @Override
        public HostWeight doSelect(Collection<HostWeight> sources) {
            double totalWeight = 0;
            double lowWeight = 0;
            HostWeight lowerNode = null;
            List<HostWeight> weights = canAssignTaskHost(sources);
            for (HostWeight hostWeight : weights) {
                totalWeight += hostWeight.getWeight();
                hostWeight.setCurrentWeight(hostWeight.getCurrentWeight() + hostWeight.getWeight());
                if (lowerNode == null || lowWeight > hostWeight.getCurrentWeight()) {
                    lowerNode = hostWeight;
                    lowWeight = hostWeight.getCurrentWeight();
                }
            }
            lowerNode.setCurrentWeight(lowerNode.getCurrentWeight() + totalWeight);
            return lowerNode;
        }
    
        private List<HostWeight> canAssignTaskHost(Collection<HostWeight> sources) {
            List<HostWeight> zeroWaitingTask = sources.stream().filter(h -> h.getWaitingTaskCount() == 0).collect(Collectors.toList());
            if (!zeroWaitingTask.isEmpty()) {
                return zeroWaitingTask;
            }
            HostWeight hostWeight = sources.stream().min(Comparator.comparing(HostWeight::getWaitingTaskCount)).get();
            List<HostWeight> waitingTask = Lists.newArrayList(hostWeight);
            List<HostWeight> equalWaitingTask = sources.stream().filter(h -> !h.getHost().equals(hostWeight.getHost()) && h.getWaitingTaskCount() == hostWeight.getWaitingTaskCount())
                .collect(Collectors.toList());
            if (!equalWaitingTask.isEmpty()) {
                waitingTask.addAll(equalWaitingTask);
            }
            return waitingTask;
        }
    }
    
    

🐵其它


@Bean注解官网

Spring的@Bean注解用于告诉方法,产生一个Bean对象,然后这个Bean对象交给Spring管理。产生这个Bean对象的方法Spring只会调用一次,随后将这个Bean对象放在自己的IOC容器中。

SpringIOC
容器管理一个或者多个bean,这些bean都需要在@Configuration注解下进行创建,在一个方法上使用@Bean注解就表明这个方法需要交给Spring进行管理。

在这里插入图片描述

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

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

相关文章

【计算机网络】网络层:虚拟专用网

由于IP地址的紧缺&#xff0c;一个机构能够申请到的IP地址数往往远小于本机构拥有的主机数。 如果一个机构内部的计算机通信也采用TCP/IP协议&#xff0c;那么这些仅字机构内部使用的计算机就可以由本机构自行分配其IP地址。 本地地址&#xff08;专用地址&#xff0c;互联网对…

Java培训教程给bean的属性赋值

依赖注入的方式 1. 通过bean的setXxx()方法赋值 Hello World中使用的就是这种方式 2. 通过bean的构造器赋值 Spring自动匹配合适的构造器<bean id“book” class“com.atguigu.spring.bean.Book” > <constructor-arg value “10010”/> …

有位p8终于把珍藏多年的算法视频给分享出来了,总共3.81G

大厂面试都开始问算法了&#xff0c;要是你不会算法只能与大厂失之交臂。为了解决大家算法方面的缺失&#xff0c;小编特此分享算法的学习路线和学习视频&#xff0c;希望大家能够喜欢&#xff01;&#xff01;&#xff01; 左神算法-KMP算法及其扩展 左神算法-Morris遍历及其…

S2B2C供应链系统将引领商业模式!S2B2C供应链电商系统实现订单管理数智化

近年来随着5G、人工智能、区块链、大数据、物联网等技术的快速发展&#xff0c;带动了数字经济的升级发展&#xff0c;疫情的不断反复更是加速推动了数字经济新发展&#xff0c;产业数字化和数字产业化进程加快&#xff0c;促进了各行各业快速发展&#xff0c;S2B2C供应链系统模…

17【redux】

17 【redux】 引言 我们现在开始学习了 Redux &#xff0c;在我们之前写的案例当中&#xff0c;我们对于状态的管理&#xff0c;都是通过 state 来实现的&#xff0c;比如&#xff0c;我们在给兄弟组件传递数据时&#xff0c;需要先将数据传递给父组件&#xff0c;再由父组件…

[附源码]Python计算机毕业设计大学生志愿者管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

软件工程经济学期末复习

1、利润 收入-成本费用 2、资产 流动资产非流动资产 3、显性成本可以用货币计量&#xff0c;是可以在会计的帐目上反映出来的 4、领取什么保险应缴纳个人所得税 商业保险 某企业一项固定资产的原价为800 0000元&#xff0c;预计使用年限为6年&#xff0c;预计净残值为5 0…

软件测试linux面试相关的知识

一、常用的命令 ls&#xff08;查看目录下的内容&#xff0c;-a显示隐藏目录&#xff09; cd&#xff08;进入某个目录&#xff0c;cd .. 返回上一层目录&#xff0c;cd - 返回上一次的目录&#xff0c;cd / 返回根目录&#xff09; pwd&#xff08;显示当前绝对路径&#x…

阿里云易立:以增效促降本,容器服务全面进入智能化时代

容器技术已经跨越鸿沟&#xff0c;广泛应用于金融、通讯、制造、交通等千行百业。Kubernetes支撑的工作负载也从早期单一的互联网应用发展到数据库、AI、大数据等等&#xff0c;并覆盖了公共云、专有云、边缘云等多样化、动态的云环境。 11月5日&#xff0c;2022杭州 云栖大会…

在Windows7在部署Hadoop+Hbase

0. 准备工作 0.1 电脑上现在没有jdk 0.1 提前准备好文件 1. 现在开始安装jdk 1.8.0_60 安装成功&#xff0c;没啥问题 小疑问&#xff1a;自动配置好了环境变量? 1.1 小记 在安装jdk的时候&#xff0c;有三种小工具&#xff0c;可以根据需要选择性安装 JDKjre源代码 虽…

牛客网语法篇练习基础语法(二)

1.牛牛正在给他的朋友们买电影票&#xff0c;已知一张电影票价是100元&#xff0c;计算 x 位朋友的总票价是多少&#xff1f; x int(input()) a x*100 print(a) 2.给定两个整数a和b (0 < a,b < 10,000)&#xff0c;计算a除以b的整数商和余数。 a,b map(int,input().…

【深入浅出Java并发编程指南】「剖析篇」Fork/Join框架的实战开发和原理探究指南

前提概述 Java 7开始引入了一种新的Fork/Join线程池&#xff0c;它可以执行一种特殊的任务&#xff1a;把一个大任务拆成多个小任务并行执行。 我们举个例子&#xff1a;如果要计算一个超大数组的和&#xff0c;最简单的做法是用一个循环在一个线程内完成&#xff1a; 算法原理…

使用Typora+EasyBlogImageForTypora写博客,无图床快速上传图片

Typora下载 Typora以前都是免费的&#xff0c;自去年开始竟然要收费&#x1f914;&#xff08;不过也能理解&#xff0c;毕竟真心好用&#x1f60a;&#xff09;&#xff0c;在这里给大家提供的是免费的版本&#xff08;免安装&#xff0c;下载即可使用&#xff09;&#xff0…

【密码学篇】(商密)密码算法分析理论知识

【密码学篇】&#xff08;商密&#xff09;密码算法分析理论知识 密码算法分析理论—【蘇小沐】 文章目录【密码学篇】&#xff08;商密&#xff09;密码算法分析理论知识&#xff08;一&#xff09;密码系统安全性1.实际安全性2.无条件安全性&#xff08;二&#xff09;密码算…

干货丨如何开启TiDB集群中的节点通信加密?

笔者在一个银行项目中&#xff0c;费尽千辛万苦&#xff0c;好不容易通过PoC测试。 就当一切就绪&#xff0c;准备正式上线时&#xff0c;突然传来了噩耗&#xff1a;未通过银行内部的漏洞扫描&#xff0c;发现存在高危漏洞&#xff0c;需要马上进行修复。 这可给我吓坏了&am…

Vue-axios的get、post请求

直接在控制台上打印axios会报错&#xff0c;打印fetch就不会&#xff1b; 因为fetch是标准&#xff0c;axios是第三方&#xff0c;要想用axios&#xff0c;就必须引入想应的js文件&#xff1b;axios-js文件下载&#xff1a;npm 搜索axios&#xff0c;点进去&#xff0c;往下找&…

智云通CRM:如何清除销售前被拒绝的怀疑和猜测?

在做CRM销售时&#xff0c;经常遇到被客户拒绝的情况&#xff0c;没有人喜欢被拒绝&#xff0c;因为拒绝辉让人痛苦、难过&#xff0c;但现实中又无法避免被拒绝&#xff0c;尤其是销售人员&#xff0c;对销售人员来说&#xff0c;被拒绝是家常便饭。遭到拒绝后&#xff0c;经常…

基于51单片机pwm调光护眼台灯智能检测光强光控灯设计proteus仿真原理图PCB

功能&#xff1a; 0.本系统采用STC89C52作为单片机 1.LCD1602液晶实时显示当前时间/模式/亮度等级 2.按’切换’键可切换四种不同的模式 a) 自动开关&#xff0c;自动调节亮度 b) 手动开关&#xff0c;自动调节亮度 c) 自动开关&#xff0c;手动调节亮度 d) 手动开关&#xff0…

arthas诊断工具

1.安装 linux: curl -o https://alibaba.github.io/arthas/arthas-boot.jar //是O不是零 浏览直接访问https://alibaba.github.io/arthas/arthas-boot.jar 在运行程序之前,需要运行一个java进程在内存种 java -jar arthas-boot.jar 按序号选择诊断的进程 选择序号回车 2.卸载…

​生成图片并添加文字Image.new()与ImageDraw.drawer.text()方法​

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 生成图片并添加文字 Image.new()与ImageDraw.drawer.text()方法 [太阳]选择题 以下python代码表述错误的一项是? from PIL import Image,ImageDraw,ImageFont imgImage.new(modeRGB,…