【性能测试】ChaosTesting(混沌测试)ChaosBlade(混沌实验工具)(五)-jvm混沌实验

6. chaosblade-jvm实验场景

6.1 挂载 java agent

        blade prepare jvm

6.1.1 介绍

挂载 java agent,执行 java 实验场景必要步骤

6.1.2 参数

-j, --javaHome string: 指定 JAVA_HOME 路径,用于指定 java bin 和 tools.jar,如果不添加此参数,默认会优先获取 JAVA_HOME 环境变量,如果获取失败,会解析指定进程参数获取 JAVA_HOME,获取失败,会使用 chaosblade 自带的 tools.jar
–pid string: java 进程ID
-P, --port int: java agent 暴露服务的本地端口,用于下发实验命令
-p, --process string: java 进程关键词,用于定位 java 进程
-d, --debug: 开启 debug 模式

6.1.3 案例

# 指定 pid 执行 java agent 挂载
blade prepare jvm --pid 26652
# 命令也可简写为
blade p jvm --pid 26652

执行成功,会返回实验准备的 UID,例如:

{"code":200,"success":true,"result":"2552c05c6066dde5"}

2552c05c6066dde5 就是实验准备对象的 UID,执行卸载操作需要用到此 UID,例如

blade revoke 2552c05c6066dde5
# 命令也可简写为
blade r 2552c05c6066dde5

如果 UID 忘记,可通过以下命令查询

blade status --type prepare --target jvm
# 命令也可简写为:
blade s --type p --target jvm

挂载 java agent 操作是个比较耗时的过程,在未返回结果前请耐心等待

6.0 创建jvm

        blade create jvm

6.0.1 介绍

jvm 本身相关场景,以及可以指定类,方法注入延迟、返回值、异常故障场景,也可以编写 groovy 和 java 脚本来实现复杂的场景。目前支持的场景如下

  1. [blade create jvm CodeCacheFilling](blade create jvm CodeCacheFilling.md) 填充 jvm code cache
  2. [blade create jvm OutOfMemoryError](blade create jvm OutOfMemoryError.md) 内存溢出,支持堆、栈、metaspace 区溢出
  3. [blade create jvm cpufullload](blade create jvm cpufullload.md) java 进程 CPU 使用率满载
  4. [blade create jvm delay](blade create jvm delay.md) 方法延迟
  5. [blade create jvm return](blade create jvm return.md) 指定返回值
  6. [blade create jvm script](blade create jvm script.md) 编写 groovy 和 java 实现场景
  7. [blade create jvm throwCustomException](blade create jvm throwCustomException.md) 抛自定义异常场景

6.0.2 参数

此处列举 jvm 支持的通用参数:
–pid string: 指定 java 进程号
–process string: 指定 java 进程名,如果同时填写
–timeout string:
设定运行时长,单位是秒,通用参数
JVM 方法级别的故障场景通用参数:
–classname string: 指定类名,必须是实现类,带全包名,例如 com.xxx.xxx.XController (必填项)
–methodname string: 指定方法名,注意相同方法名的方法都会被注入相同故障 (必填项)
–after: 方法执行完成返回前注入故障,比如修改复杂的返回对象
–effect-count string: 限制影响数量
–effect-percent string: 限制影响百分比
各场景还有自身所独有的参数,可以在每个场景文档中查看

6.0.3 案例

此处举个简单的例子:当前 Java 进程 CPU 使用率满载

# 先执行 prepare 操作
blade prepare jvm --process tomcat
{"code":200,"success":true,"result":"af9ec083eaf32e26"}

# 执行进程内 CPU 满载
blade create jvm cpufullload --process tomcat
{"code":200,"success":true,"result":"2a97b8c2fe9d7c01"}
# 验证结果:见下图
-w461
Copy
# 停止实验
blade destroy 2a97b8c2fe9d7c01

# 卸载 agent
blade revoke af9ec083eaf32e26

在这里插入图片描述

6.2 指定类方法调用延迟

        blade create jvm delay

6.2.1 参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
–effect-count string: 影响的请求条数
–effect-percent string: 影响的请求百分比
–time string: 延迟时间,单位是毫秒,必填项
–offset string: 延迟时间上下偏移量,比如 --time 3000 --offset 1000,则延迟时间范围是 2000-4000 毫秒

6.2.2 案例

业务方法通过 future 获取返回值,代码如下:

@RequestMapping(value = "async")
@ResponseBody
public String asyncHello(final String name, long timeout) {
    if (timeout == 0) {
        timeout = 3000;
    }
    try {
        FutureTask futureTask = new FutureTask(new Callable() {
            @Override
            public Object call() throws Exception {
                return sayHello(name);
            }
        });
        new Thread(futureTask).start();
        return (String)futureTask.get(timeout, TimeUnit.MILLISECONDS);
    } catch (TimeoutException e) {
        return "timeout, " + e.getMessage() + "\n";
    } catch (Exception e) {
        return e.getMessage() + "\n";
    }
}

我们对 sayHello 方法调用注入 4 秒延迟故障,futureTask.get(2000, TimeUnit.MILLISECONDS) 会发生超时返回:

blade c jvm delay --time 4000 --classname=com.example.controller.DubboController --methodname=sayHello --process tomcat
{"code":200,"success":true,"result":"d6ebea0dc28b6ab3"}

注入故障前:
在这里插入图片描述

注入故障后:
在这里插入图片描述

停止实验:

blade d d6ebea0dc28b6ab3

6.3 指定类方法的返回值

        blade create jvm return

6.3.1 介绍

指定类方法的返回值,仅支持基本类型、null 和 String 类型的返回值。

6.3.2 参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
–effect-count string: 影响的请求条数
–effect-percent string: 影响的请求百分比
–value string: 返回指定值,仅支持基本类型和字符串类型,如果想返回 null,可以设置为 --value null 。必选项

6.3.3 案例

指定com.example.controller.DubboController类,下面业务方法返回 “hello-chaosblade”

@RequestMapping(value = "hello")
@ResponseBody
public String hello(String name, int code) {
    if (name == null) {
        name = "friend";
    }
    StringBuilder result = null;
    try {
        result = new StringBuilder(sayHello(name));
    } catch (Exception e) {
        return e.getMessage() + "\n";
    }
    return result.toString() + "\n";
}

故障注入命令如下:

blade c jvm return --value hello-chaosblade --classname com.example.controller.DubboController --methodname hello --process tomcat

故障注入之前:
在这里插入图片描述
故障注入之后:
在这里插入图片描述
停止实验:

blade d d31e24dea782a275

上述代码调用 sayHello 方法,我们对 sayHello 方法注入返回 null 故障,sayHello 方法如下:

private String sayHello(String name) throws BeansException {
    demoService = (DemoService)SpringContextUtil.getBean("demoService");
    StringBuilder result = new StringBuilder();
    result.append(demoService.sayHello(name));
    return result.toString();
}

执行以下命令:

blade c jvm return --value null --classname com.example.controller.DubboController --methodname sayHello --process tomcat

故障注入之后:
在这里插入图片描述

6.4 编写 java 或者 groovy 脚本实现复杂的故障场景

        ** blade create jvm script**

6.4.1 介绍

编写 java 或者 groovy 脚本实现复杂的故障场景,比如篡改参数、修改返回值、抛自定义异常等

6.4.2 参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
–effect-count string: 影响的请求条数
–effect-percent string: 影响的请求百分比
–script-content string: 脚本内容,是 Base64 编码后的内容,相关工具类 Base64Util。注意,不能和 script-file 同时使用。
–script-file string: 脚本文件,文件绝对路径
–script-name string: 脚本名称,日志记录用,可不填写。
–script-type string: 脚本类型,取值为 java 或 groovy,默认为 java。
使用 script-content 指定演练脚本内容,不添加 script-type 参数,默认为 java 脚本,将调用 java 引擎解析器。

blade c jvm script --classname com.example.controller.DubboController --methodname call --script-content aW1wb3J0IGphdmEudXRpbC5NYXA7CgppbXBvcnQgY29tLmV4YW1wbGUuY29udHJvbGxlci5DdXN0b21FeGNlcHRpb247CgovKioKICogQGF1dGhvciBDaGFuZ2p1biBYaWFvCiAqLwpwdWJsaWMgY2xhc3MgRXhjZXB0aW9uU2NyaXB0IHsKICAgIHB1YmxpYyBPYmplY3QgcnVuKE1hcDxTdHJpbmcsIE9iamVjdD4gcGFyYW1zKSB0aHJvd3MgQ3VzdG9tRXhjZXB0aW9uIHsKICAgICAgICBwYXJhbXMucHV0KCIxIiwgMTExTCk7CiAgICAgICAgLy9yZXR1cm4gIk1vY2sgVmFsdWUiOwogICAgICAgIC8vdGhyb3cgbmV3IEN1c3RvbUV4Y2VwdGlvbigiaGVsbG8iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgIH0KfQo=  --script-name exception

使用 script-file 参数指定文件演练:

blade c jvm script --classname com.example.controller.DubboController --methodname call --script-file /Users/Shared/IdeaProjects/Workspace_WebApp/dubbodemo/src/main/java/com/example/controller/ExceptionScript.java --script-name exception

执行 groovy 脚本实验场景,参数同上,但必须添加 --script-type groovy 参数。如

blade c jvm script --classname com.example.controller.DubboController --methodname call --script-file /Users/Shared/IdeaProjects/Workspace_WebApp/dubbodemo/src/main/java/com/example/controller/GroovyScript.groovy --script-name exception --script-type groovy 

脚本规范
必须创建一个类,对类名和包名没有要求,其中所依赖的类,必须是目标应用所具备的类。

同包下的类引用,必须写全包名,比如故障脚本类是 com.example.controller.ExceptionScript,类中引入了同包下的 DubboController 类,则 DubboController 必须添加 com.example.controller.DubboController。引入非同包下的类,无需写全包名。

必须添加 public Object run(Map<String, Object> params) 方法,其中 params 对象中包含目标方法参数,key 是参数索引下标,从 0 开始,比如目标方法是 public String call(Object obj1, Object obj2){},则 params.get(“0”)则返回的是 obj1 对象,可以执行params.put(“0”, ) 来修改目标方法参数(目标方法及 --classname 和 --methodname 所指定的类方法)。

上述方法返回的对象如果不为空,则会根据脚本中返回的对象来修改目标方法返回值,注意类型必须和目标方法返回值一致。如果上述方法返回 null,则不会修改目标方法返回值。

6.4.3 案例

对以下业务类做修改返回值实验场景:

@RestController
@RequestMapping("/pet")
public class PetController {

    @GetMapping("/list")
    public Result<List<PetVO>> getPets() {
        Map<Long, Discount> petDiscount = discountManager
            .getPetDiscounts()
            .stream()
            .filter(discount -> discount.getExpired() == 0)
            .collect(Collectors.toMap(
                Discount::getPetId,
                Function.identity()
            ));

        List<PetVO> pets = petManager
            .getPets()
            .stream()
            .map(pet -> {
                PetVO petVO = PetVO.from(pet);
                Discount discount = petDiscount.get(pet.getId());

                if (null != discount && null != discount.getDiscountPrice() && discount.getDiscountPrice() > 0L) {
                    petVO.setDiscountPrice(discount.getDiscountPrice());
                }

                return petVO;
            })
            .collect(Collectors.toList());

       return Result.success(pets);
    }

则编写 Java 脚本,实现对 getPets 方法做返回值修改:

package com.alibaba.csp.monkeyking.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.alibaba.csp.monkeyking.demo.model.Pet;
import com.alibaba.csp.monkeyking.model.PetVO;
import com.alibaba.csp.monkeyking.model.Result;

public class ChaosController {

    public Object run(Map<String, Object> params) {
        ArrayList<PetVO> petVOS = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Pet pet = new Pet();
            pet.setName("test_" + i);
            PetVO petVO = PetVO.from(pet);
            petVOS.add(petVO);
        }
        Result<List<PetVO>> results = Result.success(petVOS);
        return results;
    }
}

保存文件后,通过上面 使用方式 部分的命令来调用,也可以将其进行 Base64 编码,通过指定 script-content 参数来指定编码后的内容。

blade c jvm script --classname com.alibaba.csp.monkeyking.controller.PetController --methodname getPets --script-file /Users/Shared/IdeaProjects/Workspace_WebApp/dubbodemo/src/main/java/com/alibaba/csp/monkeyking/controller/ChaosController --script-name specifyReturnObj

未执行实验之前页面:
在这里插入图片描述
执行实验之后:
在这里插入图片描述

6.5 指定 java 进程 CPU 满载

        blade create jvm cpufullload

6.5.1 介绍

指定 java 进程 CPU 满载,可以简写为 blade c jvm cfl

6.5.2 参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
–cpu-count string: 绑定的 CPU 核数,即指定几个核满载

6.5.3 案例

指定全部核满载

blade c jvm cfl --process tomcat 
{"code":200,"success":true,"result":"48d70f01e65f68f7"}

查看该进程 CPU 使用率:
-w454
停止实验:

blade d 48d70f01e65f68f7

指定两个核满载(测试机器是 8 个核)

blade c jvm cfl --cpu-count 2 --process tomcat
{"code":200,"success":true,"result":"a929157644688b15"}

查看进程 CPU 使用率是满核的四分之一:
在这里插入图片描述

6.6 内存溢出场景

        blade create jvm OutOfMemoryError

6.6.1 介绍

内存溢出场景,命令可以简写为:blade c jvm oom

6.6.2 参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
–area string: JVM 内存区,目前支持 [HEAP, NOHEAP, OFFHEAP],必填项。用Heap来表示Eden+Old,,用NOHEAP来表示metaspace,用OFFHEAP来表示堆外内存
–block string: 指定对象大小,仅支持 HEAP 和 OFFHEAP 区,单位是 MB
–interval string: 单位ms,默认500两次oom异常间的时间间隔,只有在非暴力模式才生效,可以减缓gc的频率,不用担心进程会无响应
–wild-mode string: 默认false,是否开启暴力模式,如果是暴力模式,在OOM发生之后也不会释放之前创建的内存,可能会引起应用进程无响应

6.6.3 案例

堆内存占用:

blade c jvm oom --area HEAP --wild-mode true --process tomcat

{"code":200,"success":true,"result":"99b9228b9632e043"}

故障注入之前: 在这里插入图片描述
故障注入之后:在这里插入图片描述

停止 HEAP 内存占用:

blade d 99b9228b9632e043

创建 Metaspace 区内存占用,注意,执行完此场景后,需要重启应用!!!!:

blade c jvm oom --area NOHEAP --wild-mode true --process tomcat

{"code":200,"success":true,"result":"93264dd07149cf54"}

故障注入后:在这里插入图片描述

6.6.4 实现原理

根据不同区注入
java.lang.OutOfMemoryError: Java heap space
创建 Heap的话分为Young,Old,这块区域的oom是最好重现,只需要不断的创建对象就可以,如果内存使用达到了 Xmx或者Xmn所规定的大小,并且gc回收不了,就会触发oom错误。

检查 • 可以通过 jmap -heap pid 来查看当前堆占用情况是否到了100% • 可以通过jstat -gcutil pid 来查看是否发生了gc,因为会一直创建新的对象,所以会频繁触发gc操作

恢复 当演练终止后,会停止产生新的对象,但此时不一定heap就恢复了,因为恢复需要触发gc才可以进行回收,当然也可以通过手动调用 System.gc()来强行触发gc,但是如果你的启动参数里面有 -XX:+DisableExplicitGC 那么这个命令就无法生效了.

注意 触发OOM的时候可能会导致进程被操作系统所kill,这个原因是因为你的Xmx设置的不合理,比如操作系统内存只有3G,但是你Xmx会设置了3G甚至更多,那么就会因为系统内存不足,而被os kill掉进程,所以这里务必要注意Xmx大小

java.lang.OutOfMemoryError: Metaspace
创建 Metaspace可以通过不断的加载类对象来创建,当大小超过了 -XX:MaxMetaspaceSize 并且无法进行gc回收就会抛出 oom错误了

检查 • 可以通过jstat -gcutil pid 来查看 M区的使用情况以及gc的次数

恢复 类对象的回收条件在jvm里面比较苛刻,需要满足很多条件,就算满足了条件,触发gc了也不一定回收,只要有下面任何一个条件就无法被回收. • objects of that class are still reachable. • the Class object representing the class is still reachable • the ClassLoader that loaded the class is still reachable • other classes loaded by the ClassLoader are still reachable 因此最好的办法就是重启应用.

java.lang.OutOfMemoryError: Direct buffer memoryDirectBuffer
在这里插入图片描述
创建 堆外内存可以直接通过ByteBuffer.allocateDirect 来产生,并且会一直消耗系统内存.

检查 • 因为堆外内存不属于堆里面,所以你通过jmap命令很难发现,但是可以通过 jstat -gcutil pid 来查看,如果频发出发了fullgc,但是e,O,M区都没发生变化, 那就是进行堆外内存回收 • 可以通过free -m 查看内存使用情况

注意 同样,如果没有设置最大堆外内存大小,同样会因为OS的memory耗尽而导致进程被杀,所以需要配置比如下面的参数: -XX:MaxDirectMemorySize=100M

6.7 调用频率比较高的代码

        blade create jvm CodeCacheFilling

6.7.1 介绍

CodeCache主要用于存放native code,其中主要是JIT编译后的代码。被JIT编译的一般都是“热代码”,简单说就是调用频率比较高的代码,JIT编译后,代码的执行效率会变高,CodeCache满会导致JVM关闭JIT编译且不可再开启,那么CodeCache满会引起系统运行效率降低,导致系统最大负载下降,当系统流量较大时,可表现为RT增高、QPS下降等。 命令可以简写为:blade c jvm ccf

6.7.2 参数

此场景无特有参数,通用参数详见:[blade create jvm](blade create jvm.md)

6.7.3 案例

6.7.3.1 注入 CodeCache 满故障:
blade c jvm CodeCacheFilling --process tomcat                                                                          

{"code":200,"success":true,"result":"f0e896f38c704894"}

在这里插入图片描述

6.7.3.2 实现原理

由于CodeCache主要存放JIT编译的结果,所以填充CodeCache分为两步,第一步是生成用于触发JIT编译的class,方式是通过动态编译生成大量的class;第二步是编译后生成的class进行实例化和频繁调用(“加热”),直到触发JIT编译后进入CodeCache区。通过这样方式不停的填充CodeCache,直到JIT编译关闭

6.7.3.3 常见问题
  1. 由于需要编译和“加热”代码,所以在填充的过程中CPU占用率会很高;并且会持续一段时间(测试中,默认大小的情况下,从无占用到填充满约5分钟,实际情况下,CodeCache都会有一定的使用率,所以时间不会那么长);
  2. 由于“加热”过程中需要实例化大量的class,会有大量对象一直无法被GC回收,有概率导致Metaspace满而产生OOM;
  3. 由于无法直接判断JIT编译是否关闭,所以只能根据CodeCache占用量来判断,但是JIT编译关闭时,CodeCache占用量的阈值并不能精准获取,所以是通过CodeCache的增长来判断的,如果5秒内CodeCache占用量都无变化,即判断JIT编译关闭(JIT编译关闭后,CodeCache占用量不再变化);
  4. 目前是根据CodeCache的默认大小来设计的(生成class数量等),即240M(jdk8 64bit),如果设置更大的CodeCache(-XX:ReservedCodeCacheSize)的话,持续时间会更长,甚至由于动态产生的class数量不够而导致无法填充满;
  5. 由于JIT编译关闭后不可再手工开启,所以该故障无法直接恢复,需要用户手工重启应用系统来恢复;

6.8 指定类方法抛自定义异常

        blade create jvm throwCustomException

6.8.1 介绍

指定类方法抛自定义异常,命令可以简写为 blade c jvm tce

6.8.2 参数

以下是此场景特有参数,通用参数详见:[blade create jvm](blade create jvm.md)
–effect-count string: 影响的请求条数
–effect-percent string: 影响的请求百分比
–exception string: 异常类,带全包名,必须继承 java.lang.Exception 或 java.lang.Exception 本身
–exception-message string: 指定异常类信息,默认值是 chaosblade-mock-exception

6.8.3 案例

类名:com.example.controller.DubboController,业务代码如下:

private String sayHello(String name) throws BeansException {
    demoService = (DemoService)SpringContextUtil.getBean("demoService");
    StringBuilder result = new StringBuilder();
    result.append(demoService.sayHello(name));
    return result.toString();
}

指定以上方法抛出 java.lang.Exception 异常,影响两条请求,命令如下

blade c jvm throwCustomException --exception java.lang.Exception --classname com.example.controller.DubboController --methodname sayHello --process tomcat --effect-count 2

{"code":200,"success":true,"result":"3abbe6fe97d6bc75"}

验证结果:
注入前: 在这里插入图片描述
注入后: 在这里插入图片描述
第三次请求后恢复正常: 在这里插入图片描述

停止实验:

blade d 3abbe6fe97d6bc75

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《HCIP-openEuler实验指导手册》1.1Apache安装与测试

一、安装httpd 查看软件仓库中apache版本列表 dnf provides http 安装apache dnf install -y httpd 二、启动http并测试 查看apache版本号 httpd -v 检查配置文件是否正确 httpd -t 将如下97行取消注释消除报错 重新测试配置文件 httpd -t 启动并设置为开机启动 syste…

QT中对于QPushButton样式的调整

文章目录 前言1.QPushButton1.1 新建项目导入资源1.2 添加Push Button并定义样式1.3 调整样式1.4 实际需求情况1.5 背景色和边框 2. 一些概念理解2.1 图片2.2 边距 总结 前言 前段时间在调软件的样式&#xff0c;学到了些新的东西&#xff0c;也碰到了些问题&#xff0c;这里做…

光纤、以太网电缆和 DSL 的比较:技术指南

了解光纤、以太网电缆和 DSL 之间的差异对于做出有关互联网连接的明智决策至关重要。本技术指南对这些技术进行了全面比较&#xff0c;讨论了它们的独特功能、性能指标和应用。它旨在为您提供必要的知识&#xff0c;以选择最适合您的特定需求的选项。 光纤、以太网电缆和 DSL …

汇编期末复习知识点

参考文献1 第一章 概述 组成 计算机系统由硬件子系统和软件子系统组成。硬件子系统&#xff1a;组成计算机系统的所有电子的&#xff0c;机械的&#xff0c;光学的和磁性的元部件。 计算机中常用进制数表示 十进制(Decimal):数据尾部加一后缀D&#xff0c;如2355D二进制&a…

FANUC机器人socket通讯硬件配置

一、添加机器人选配包 Fanuc机器人要进行socket通讯&#xff0c;需要有机器人通讯的选配包&#xff0c;1A05B-2600-R648 User Socket Msg&#xff0c;1A05B-2600-R632 KAREL&#xff0c;1A05B-2600-R566 KAREL Diagnostic&#xff0c;1A05B-2600-J971 KAREL Use Sprt FCTN。 二…

初学python,怎样入门?

答案&#xff1a;乌龟绘图。 "乌龟绘图"通常指的是使用Logo语言的变种——Python中的turtle模块来进行图形绘制。在turtle模块中&#xff0c;一只名为“海龟”&#xff08;Turtle&#xff09;的小动物会在屏幕上移动&#xff0c;根据其行进路径来绘制图形。以下是一段…

音视频直播原理解析

直播原理就是一个推流和拉取流的过程&#xff1b; 直播端将直播流推送至服务器&#xff0c;用户端发起请求从服务器拉取直播流然后解码播放 第一部分就是视频直播端的操作&#xff1a;视频采集处理后推流到流媒体服务器。 首先从前端采集设备中获得原始的音频、视频数据&…

Vue页面生成导出PDF文件

第一种&#xff1a; 使用浏览器自带打印方法window.print(); 也可使用print-js插件&#xff08;原理相同&#xff09; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>printDemo</title> </…

助力24五一杯数学建模比赛

完成助力美赛建模&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 完成助力妈妈杯建模&#xff01;&#xff01;&#xff01;&#xff01; 完成助力华中杯建模&#xff01;&#xff01;&#xff01;&#xff01; 这边将在开赛后24小时内发布资料和初步思路 需…

系统思考—啤酒游戏

最近有不少的合作伙伴来询问我啤酒游戏这个来自于MIT&#xff08;麻省理工学院&#xff09;经典的沙盘&#xff0c;上周刚刚结束Midea旗下的一家公司市场运营部《啤酒游戏沙盘-应对动态性复杂的系统思考智慧》的课程。 参与这次沙盘体验的团队成员深刻体会到了全局思考的重要性…

【SpringBoot实战篇】获取用户详细信息-ThreadLocal优化

1 分析问题 对token的解析当初在拦截器中已经写过。期待的是在拦截器里写了&#xff0c;在其他地方就不写了&#xff0c;应该去复用拦截器里面得到的结果 2 解决方式-ThreadLocal 2.1提供线程局部变量 用来存取数据: set()/get()使用ThreadLocal存储的数据, 线程安全 2.2过程图…

【leetcode面试经典150题】71. 对称二叉树(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

Android Studio XML 预览View 底部移动到右边

以前 XML 的预览都是在右边的&#xff0c;最近不知道为什么突然到下面去了&#xff0c;很不习惯 找半天想把 预览view 移动到右边&#xff0c;一直没找到按钮。 误打误撞移回来了&#xff0c;原来只要再点击一次 split&#xff0c;就可以变动位置了&#xff0c;记录一下。

冶金电镀大电流测量BR罗氏线圈电流变送器

安科瑞薛瑶瑶18701709087 BR 系列产品应用电磁感应原理&#xff0c;对电网中的交流大电流进行实时测量&#xff0c;采用真有效值和线性补偿技术&#xff0c;将其隔离变换为标准的直流信号输出。DC24 伏安全电压供电&#xff0c;具有高精度、高隔离、高安全性、低功耗等特点&a…

用友NC Cloud importhttpscer接口任意文件上传漏洞

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、漏洞描述 用友NC Cloud的importhttpscer接口如果存在任意文件上传…

WebStack 导航主题优化版

主题下载地址&#xff1a;WebStack 导航主题优化版.zip 修复记录&#xff1a; 1、修复已知BUG 2、修复手机版兼容问题 3、修复打开速度&#xff0c;原版打开速度太慢 4、优化页面代码&#xff0c;删除冗杂多余的CSS JS代码 环境要求 WordPress 4.4WordPress 伪静态PHP 5.…

LabVIEW专栏八、类

该章目的是可以开发仪器类。 一、类的概述 一般来说类有三大特性&#xff0c;封装&#xff0c;继承和多态。 在实际项目中&#xff0c;最主要是继承和多态&#xff0c;要搞清楚这两者的概念和在LabVIEW中是怎样应用的。在LabVIEW中&#xff0c;面向对象编程用到的就是LabVIE…

huggingface文件下载教程

文章目录 准备工作添加SSH Key生成Access Token 模型下载公开模型下载&#xff08;bert-base-chinese为例&#xff09;非公开模型下载&#xff08;Llama3为例&#xff09;权限申请官网预训练模型下载huggingface仓库下载 准备工作 添加SSH Key # 本地机器生成ssh key # step1…

欢乐钓鱼大师一键钓鱼,解放双手!

《钓鱼欢乐大师》是一款让玩家体验钓鱼乐趣的游戏&#xff0c;在游戏中&#xff0c;玩家可以通过技巧和策略钓到各种各样的鱼。为了提高钓鱼效率&#xff0c;让玩家更快地钓到大鱼&#xff0c;下面将介绍如何利用脚本来优化游戏体验。 第一步&#xff1a;准备工作 创建云机&…

目标检测综述

2D图像的目标检测是深度学习的热门领域&#xff0c; 在学术研究领域取得了巨大的进展&#xff0c;在工程中也被广泛应用。 按照stage划分&#xff0c; 主要可以分为one-stage 和two-stage 算法。 近年来&#xff0c; 随着transformer的流行&#xff0c; 基于transformer的检测…