浅谈重要组件Beanshell

news2025/2/24 7:26:17

浅谈重要组件Beanshell

BeanShell是JMeter中一个非常实用的组件,它允许用户通过Java-like的脚本语言执行自定义逻辑,从而极大地扩展了JMeter的功能。本文将详细介绍BeanShell的使用方法、常见用途、以及其在JMeter中的具体应用场景。
BeanShell概述
BeanShell是一种轻量级的Java脚本解释器,它支持即席(adhoc)的脚本编写和快速原型开发。在JMeter中,BeanShell可以用于创建动态且高度定制化的测试计划组件,如采样器、前置处理器、后置处理器、断言、计时器和监听器。相比于JMeter的图形界面操作,BeanShell提供了更高的灵活性和编程控制能力。

BeanShell的组件及用途

  1. BeanShell Sampler(取样器)
    ● 用途:执行自定义的Java代码片段,可以用来发送请求、处理响应或执行任何复杂的业务逻辑。
    ● 示例:模拟复杂请求、动态生成请求参数。
  2. BeanShell PreProcessor(前置处理器)
    ● 用途:在主采样器执行前运行,常用于数据预处理,如修改请求参数、设置变量等。
    ● 示例:根据某些条件动态计算变量值。
  3. BeanShell PostProcessor(后置处理器)
    ● 用途:在采样器执行后运行,用于解析响应数据,提取有用信息存储为变量。
    ● 示例:从HTML或JSON响应中提取数据。
  4. BeanShell Assertion(断言)
    ● 用途:提供更灵活的验证机制,通过脚本判断响应是否符合预期。
    ● 示例:对比响应数据与预期值的复杂逻辑验证。
  5. BeanShell Timer(定时器)
    ● 用途:基于条件控制请求间的延迟时间,提供更灵活的定时控制。
    ● 示例:根据服务器响应时间动态调整下一个请求的等待时间。
  6. BeanShell Listener(监听器)
    ● 用途:监听并处理测试结果,可用于日志记录、数据分析等。
    ● 示例:收集测试期间的特定数据,输出至文件或控制台。

应用实例

在BeanShell组件中,以下是一些常用的内置变量,它们可以帮助你访问JMeter上下文中的信息,首先使用SpringBoot编写一个接口,部分代码如下

 @PostMapping(value = "/login",produces = "application/json;charset=UTF-8")
    public String authenticate(@RequestBody JSONObject request) {

        String validUsername = "admin";
        String validPassword = "password";

        if (request.getString("username").equals(validUsername) && request.getString("password").equals(validPassword)) {
            return "认证成功";
        } else {
            return "认证失败";
        }
    }

log关键字

作用:打印日志信息,如 log.info(“This is an info message.”);
编写如下脚本:
在这里插入图片描述
线程组:保持默认
BeanShell 取样器:编写如下脚本

log.info("This is an info message.");
log.warn("This is an warn message.");
log.error("This is an error message.");

运行脚本,查看日志信息:

2024-07-08 16:05:21,685 INFO o.a.j.u.BeanShellTestElement: This is an info message.
2024-07-08 16:05:21,685 WARN o.a.j.u.BeanShellTestElement: This is an warn message.
2024-07-08 16:05:21,685 ERROR o.a.j.u.BeanShellTestElement: This is an error message.

var关键字

作用:操作JMeter局部变量,例如设置变量 vars.put(“myVar”, “value”); 或获取变量 vars.get(“myVar”);
编写如下脚本:
在这里插入图片描述
线程组:保持默认
BeanShell 取样器1:编写如下脚本

String s = "test";
vars.put("val",s);
String value = vars.get("val");
log.info("value变量的值为:" + value);

BeanShell 取样器2:编写如下脚本

log.info("val变量的值为:${val}");

运行脚本,查看日志信息:
2024-07-08 16:31:28,626 INFO o.a.j.u.BeanShellTestElement: value变量的值为:test
2024-07-08 16:31:28,641 INFO o.a.j.u.BeanShellTestElement: val变量的值为:test

props关键字

作用:操作JMeter全局属性,如设置属性 props.put(“PROP_NAME”, “value”); 或读取属性 props.get(“PROP_NAME”);
测试脚本沿用log关键字的脚本,并且将BeanShell 取样器中的内容代码替换如下

props.put("PROP_NAME", "value");
String value = props.get("PROP_NAME");
log.info("PROP_NAME变量的值为:" + value);

运行脚本,查看日志信息:

2024-07-08 16:33:25,939 INFO o.a.j.u.BeanShellTestElement: PROP_NAME变量的值为:value

prev关键字

作用:访问前一个采样器的响应数据等,如获取响应文本 prev.getResponseDataAsString();
编写脚本如下:
在这里插入图片描述
线程组:保持默认
HTTP信息头管理器:添加信息头,名称:content-type,值:application/json;charset=UTF-8
HTTP请求:协议http,服务器名称或IP为127.0.0.1,端口号为8091,请求方法post,路径/login,内容编号utf-8,消息体数据如下:

{
    "username": "admin",
    "password": "password"
    }

BeanShell 后置处理程序:编写如下代码

log.info("获得响应信息:");
log.info(prev.getResponseMessage());
log.info("获得响应文本内容:");
log.info(prev.getResponseDataAsString());
log.info("获得线程名称:");
log.info(prev.getThreadName());
log.info("获得取样器标签:");
log.info(prev.getSampleLabel());
log.info(prev.getSampleLabel(true));//含线程组
log.info("获得线程取样时间:");
log.info(prev.getTime().toString());
log.info("获得编码方式:");
log.info(prev.getDataEncodingWithDefault());
log.info("设置编码方式:");
prev.setDataEncoding("gbk");
log.info(prev.getDataEncodingWithDefault());
log.info("获得消息头:");
log.info(prev.getResponseHeaders());
log.info("获得Content-Type字段:");
log.info(prev.getContentType());
log.info("获取请求开始时间戳和结束时间戳:");
log.info("开始时间:" + prev.getStartTime());
log.info("结束时间:" + prev.getEndTime());
log.info("获得响应状态码:");
log.info(prev.getResponseCode());
log.info("设置响应状态码为指定值:");
prev.setResponseCode("401");
log.info(prev.getResponseCode());
log.info("设置响应状态码变成200,及时返回的并不是200:");
prev.setResponseCodeOK();
log.info(prev.getResponseCode());
log.info("判断返回值是否是200,如果是则返回true,如果不是则是返回false:");
log.info(prev.isResponseCodeOK().toString());
log.info("获取URL的信息:");
log.info(prev.getUrlAsString());

运行脚本,查看日志信息:

2024-07-08 17:00:18,137 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得响应信息:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得响应文本内容:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 认证成功
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得线程名称:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 线程组 1-1
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得取样器标签:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: HTTP请求
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 线程组:HTTP请求
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得线程取样时间:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 5
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得编码方式:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: UTF-8
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 设置编码方式:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: gbk
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得消息头:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Content-Length: 12
Date: Mon, 08 Jul 2024 09:00:18 GMT
Keep-Alive: timeout=60
Connection: keep-alive
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得Content-Type字段:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: application/json;charset=UTF-8
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获取请求开始时间戳和结束时间戳:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 开始时间:1720429218145
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 结束时间:1720429218150
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 获得响应状态码:
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 200
2024-07-08 17:00:18,153 INFO o.a.j.u.BeanShellTestElement: 设置响应状态码为指定值:
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: 401
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: 设置响应状态码变成200,及时返回的并不是200:
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: 200
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: 判断返回值是否是200,如果是则返回true,如果不是则是返回false:
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: true
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: 获取URL的信息:
2024-07-08 17:00:18,168 INFO o.a.j.u.BeanShellTestElement: http://127.0.0.1:8091/login
2024-07-08 17:00:18,168 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

ctx关键字

作用: 访问JMeter上下文(Context),进行更高级别的操作。
我们沿用prev中的脚本结构,其他不变,只是变更BeanShell 后置处理程序内容
BeanShell 后置处理:编写如下代码

String s = "test";
vars.put("val",s);
log.info("提供对当前线程的变量的访问:");
log.info(ctx.getVariables().get("val"));
log.info("获取相关属性:");
log.info(ctx.getVariables().get("START.YMD"));
log.info("获取取样器结果:");
log.info(ctx.getPreviousResult().toString());
log.info("获取当前取样器内容:");
log.info(ctx.getCurrentSampler().toString());
//这个大家可以自己试试
//log.info("获取前一个取样器内容:");
//log.info(ctx.getPreviousSampler().getName());
log.info("获取当前线程号:");
log.info(ctx.getThreadNum().toString());
log.info("获取线程内容:");
log.info(ctx.getThread().toString());
log.info("获取当前线程组:");
log.info(ctx.getThreadGroup().toString());

运行脚本,查看日志信息:

2024-07-09 10:30:08,580 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:30:08,599 INFO o.a.j.u.BeanShellTestElement: 提供对当前线程的变量的访问:
2024-07-09 10:30:08,600 INFO o.a.j.u.BeanShellTestElement: test
2024-07-09 10:30:08,616 INFO o.a.j.u.BeanShellTestElement: 获取相关属性:
2024-07-09 10:30:08,617 INFO o.a.j.u.BeanShellTestElement: 20240705
2024-07-09 10:30:08,620 INFO o.a.j.u.BeanShellTestElement: 获取取样器结果:
2024-07-09 10:30:08,625 INFO o.a.j.u.BeanShellTestElement: HTTP请求
2024-07-09 10:30:08,628 INFO o.a.j.u.BeanShellTestElement: 获取当前取样器内容:
2024-07-09 10:30:08,631 INFO o.a.j.u.BeanShellTestElement: http://127.0.0.1:8091/login
Query Data:
2024-07-09 10:30:08,632 INFO o.a.j.u.BeanShellTestElement: 获取当前线程号:
2024-07-09 10:30:08,636 INFO o.a.j.u.BeanShellTestElement: 0
2024-07-09 10:30:08,639 INFO o.a.j.u.BeanShellTestElement: 获取线程内容:
2024-07-09 10:30:08,640 INFO o.a.j.u.BeanShellTestElement: org.apache.jmeter.threads.JMeterThread@41d9ee4c
2024-07-09 10:30:08,644 INFO o.a.j.u.BeanShellTestElement: 获取当前线程组:
2024-07-09 10:30:08,645 INFO o.a.j.u.BeanShellTestElement: org.apache.jmeter.threads.ThreadGroup@54aac53d
2024-07-09 10:30:08,645 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

SamplerData关键字
作用:获取请求的数据
编写脚本如下:
在这里插入图片描述

线程组:保持默认
HTTP信息头管理器:添加信息头,名称:content-type,值:application/json;charset=UTF-8
HTTP请求:协议http,服务器名称或IP为127.0.0.1,端口号为8091,请求方法post,路径/login,内容编号utf-8,消息体数据如下:

{
    "username": "admin",
    "password": "password"
    }

BeanShell断言:编写如下代码

log.info("获取请求数据:");
String reuest = new String(SamplerData);
log.info(reuest);

运行脚本,查看日志信息:

2024-07-09 10:36:54,071 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:36:54,080 INFO o.a.j.u.BeanShellTestElement: 获取请求数据:
2024-07-09 10:36:54,081 INFO o.a.j.u.BeanShellTestElement: POST http://127.0.0.1:8091/login
POST data:
{
“username”: “admin”,
“password”: “password”
}
[no cookies]
2024-07-09 10:36:54,082 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

Label关键字

作用:获取本组件名称
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容
BeanShell断言:编写如下代码

log.info("获取组件名称:");
log.info(Label);

运行脚本,查看日志信息:

2024-07-09 10:45:25,313 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:45:25,323 INFO o.a.j.u.BeanShellTestElement: 获取组件名称:
2024-07-09 10:45:25,323 INFO o.a.j.u.BeanShellTestElement: BeanShell断言
2024-07-09 10:45:25,323 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

SampleLabel关键字

作用:获取父取样器名称
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容
BeanShell断言:编写如下代码

log.info("获取组件名称:");
log.info(SampleLabel);

运行脚本,查看日志信息:

2024-07-09 10:47:51,087 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:47:51,094 INFO o.a.j.u.BeanShellTestElement: 获取父取样器名称:
2024-07-09 10:47:51,094 INFO o.a.j.u.BeanShellTestElement: HTTP请求
2024-07-09 10:47:51,094 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

ResponseData关键字

作用:获取响应数据
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容
BeanShell断言:编写如下代码

log.info("获取响应数据:");
String response = new String(ResponseData,"utf-8");
log.info(response);

运行脚本,查看日志信息:

2024-07-09 10:49:26,066 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:49:26,074 INFO o.a.j.u.BeanShellTestElement: 获取响应数据:
2024-07-09 10:49:26,076 INFO o.a.j.u.BeanShellTestElement: 认证成功
2024-07-09 10:49:26,086 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

ResponseCode关键字

作用:获取响应码
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容
BeanShell断言:编写如下代码

log.info("获取响应码:");
log.info(ResponseCode);

运行脚本,查看日志信息:

2024-07-09 10:51:15,850 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:51:15,896 INFO o.a.j.u.BeanShellTestElement: 获取响应码:
2024-07-09 10:51:15,902 INFO o.a.j.u.BeanShellTestElement: 200
2024-07-09 10:51:15,903 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

ResponseMessage关键字

作用:获取响应信息
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容
BeanShell断言:编写如下代码

log.info("获取响应码:");
log.info(ResponseMessage);

运行脚本,查看日志信息:

2024-07-09 10:51:54,218 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 10:51:54,225 INFO o.a.j.u.BeanShellTestElement: 获取响应码:
2024-07-09 10:51:54,225 INFO o.a.j.u.BeanShellTestElement:
2024-07-09 10:51:54,227 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

我们可以看到上述内容打印是空,主要是在查看结果树中我们可以看到HTTP请求的取样器结果中的Response message也为空

Thread Name: 线程组 1-1
Sample Start: 2024-07-09 10:51:54 CST
Load time: 3
Connect Time: 1
Latency: 3
Size in bytes: 180
Sent bytes:243
Headers size in bytes: 168
Body size in bytes: 12
Sample Count: 1
Error Count: 0
Data type (“text”|“bin”|“”): text
Response code: 200
Response message:
HTTPSampleResult fields:
ContentType: application/json;charset=UTF-8
DataEncoding: UTF-8

Failure和FailureMessage关键字:

作用:设置断言失败或者成功,并且打印错误信息
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容

BeanShell断言:编写如下代码
log.info("设置断言失败:");
Failure = true;
log.info("设置断言失败信息:");
FailureMessage = "断言失败";

运行脚本,查看结果树:
在这里插入图片描述
查看HTTP请求下面BeanShell断言的Assertion result,结果内容如下

Assertion error: false
Assertion failure: true
Assertion failure message: 断言失败

Response关键字:

作用:响应相关信息内容获取
我们沿用SamplerData中的脚本结构,其他不变,只是变更BeanShell断言程序内容
BeanShell断言:编写如下代码

log.info("获取响应消息信息:");
log.info(Response.getResponseDataAsString());
log.info("获取响应对应线程名称:");
log.info(Response.getThreadName());
log.info("获取响应码:");
log.info(Response.getResponseCode());

运行脚本,查看日志信息

2024-07-09 11:11:21,241 INFO o.a.j.t.JMeterThread: Thread started: 线程组 1-1
2024-07-09 11:11:21,251 INFO o.a.j.u.BeanShellTestElement: 获取响应消息信息:
2024-07-09 11:11:21,261 INFO o.a.j.u.BeanShellTestElement: 认证成功
2024-07-09 11:11:21,261 INFO o.a.j.u.BeanShellTestElement: 获取响应对应线程名称:
2024-07-09 11:11:21,261 INFO o.a.j.u.BeanShellTestElement: 线程组 1-1
2024-07-09 11:11:21,261 INFO o.a.j.u.BeanShellTestElement: 获取响应码:
2024-07-09 11:11:21,261 INFO o.a.j.u.BeanShellTestElement: 200
2024-07-09 11:11:21,261 INFO o.a.j.t.JMeterThread: Thread is done: 线程组 1-1

IsSuccess关键字

作用:设置取样器成功还是失败
我们编写如下脚本
在这里插入图片描述
线程组:保持默认
HTTP信息头管理器:添加信息头,名称:content-type,值:application/json;charset=UTF-8
HTTP请求:协议http,服务器名称或IP为127.0.0.1,端口号为8091,请求方法post,路径/login,内容编号utf-8,消息体数据如下:

{
    "username": "admin",
    "password": "password"
    }

BeanShell 取样器:编写如下代码

log.info("设置取样器成功还是失败:");
IsSuccess = false;

运行脚本,结果树中查看BeanShell 取样器结果:
在这里插入图片描述当BeanShell 取样器:编写如下代码

log.info("设置取样器成功还是失败:");
IsSuccess = true;

运行脚本,结果树中查看BeanShell 取样器结果:
在这里插入图片描述

BeanShell的最佳实践

● 优化性能:尽管BeanShell提供了灵活性,但其执行速度通常慢于Java代码。对于性能关键的场景,考虑使用JSR223 Samplers(尤其是Groovy),因为Groovy拥有更快的执行效率。
● 代码简洁性:保持脚本简洁、可读性强,使用注释来提高可维护性。
● 异常处理:合理使用try-catch语句来捕获并处理异常,避免脚本因未预料的错误中断。
● 安全考量:避免在脚本中硬编码敏感信息,使用JMeter的属性或变量管理敏感数据。

总结

BeanShell为JMeter用户提供了一种强大的手段来定制和扩展测试计划,使得应对复杂测试需求成为可能。通过熟练掌握BeanShell的使用,测试工程师能够设计出更加贴近实际应用场景的测试案例,从而提高测试的准确性和效率。然而,在追求定制化的同时,也应关注脚本的性能和安全性,确保测试的有效性和可靠性。

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

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

相关文章

使用vllm部署大语言模型

vLLM是一个快速且易于使用的库,用于LLM(大型语言模型)推理和服务。通过PagedAttention技术,vLLM可以有效地管理注意力键和值内存,降低内存占用和提高计算效率。vLLM能够将多个传入的请求进行连续批处理,从而…

Java语言程序设计——篇二(2)

Java语言基础 运算符与表达式运算符1、算术运算符2、关系运算符3、逻辑运算符&#xff08; &&、||、 !、&、| 、^&#xff09;4、位运算符&#xff08; >>、<<、>>>、&、|、^、~&#xff09;5、赋值运算符6、条件运算符7、字符串运算符8、…

基于Tkinter GUI库的ARP欺骗攻击工具

基于Tkinter GUI库的ARP欺骗攻击工具 程序提供了一个简单易用的GUI界面,让用户可以方便地进行ARP欺骗攻击。但ARP欺骗是一种黑客攻击手段,可能会造成严重的网络安全问题,请谨慎使用,仅限于合法的网络安全测试和研究目的。 这个ARP欺骗工具需要用户输入目标主机的IP和MAC地址,…

去中心化时代的到来:区块链如何重新定义权力和控制

随着区块链技术的迅猛发展&#xff0c;我们正逐步进入一个去中心化的新时代。区块链不仅仅是一种技术&#xff0c;更是一种理念&#xff0c;它通过去除中心化的权威和控制节点&#xff0c;重新定义了数据管理、交易验证和权力分配的方式。本文将深入探讨区块链如何在去中心化时…

【软件测试】 1+X初级 功能测试试题

登录模块需求说明书 人力资源管理系统 Web 端分为系统管理员、人资管理员、普通职员三个角色。系统登录模块 需求包括用户&#xff08;UI&#xff09;页面、业务规则两部分。 UI 页面 登录页 业务规则 【登录】 人资管理员、普通职员需要通过登录页面进入系统&#xff08;We…

Python项目结构和组织

1、问题背景 在Python中&#xff0c;如何将项目中的代码逻辑地组织到不同的文件/类中&#xff1f;这种情况在C#/Java等语言中很常见&#xff0c;想要了解Python项目中如何实现类似的结构。另外&#xff0c;在Python中是否存在“命名空间”&#xff0c;“项目”和“面向对象原则…

Hadoop-20 Flume 采集数据双写至本地+HDFS中 监控目录变化 3个Agent MemoryChannel Source对比

章节内容 上一节完成了如下的内容&#xff1a; 编写Agent Conf配置文件收集Hive数据汇聚到HDFS中测试效果 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学习。 之前已经在 VM 虚拟机上搭建过一次&#xff0…

springboot+vue+mybatis图书销售管理系统+PPT+论文+讲解+售后

在Internet高速发展的今天&#xff0c;我们生活的各个领域都涉及到计算机的应用&#xff0c;其中包括图书销售管理系统的网络应用&#xff0c;在外国图书销售管理系统已经是很普遍的方式&#xff0c;不过国内的管理网站可能还处于起步阶段。图书销售管理系统具有网上图书信息管…

基础跟张宇,强化用36讲还是高数辅导讲义?

基础跟的张宇老师&#xff0c;强化阶段跟谁要看基础学的怎么样&#xff01; 因为张宇老师今年课程大改版&#xff0c;和以往的课程一点也不一样&#xff01; 具体变动是&#xff1a; 张宇老师把往年强化阶段的知识前移&#xff0c;也就是说现在的基础阶段要讲的内容是以往基…

隧道定位导航的解决方案

隧道定位导航是一个复杂但重要的技术领域&#xff0c;主要面临的是隧道内卫星信号受遮挡导致定位困难的问题。以下是对隧道定位导航技术的详细分析&#xff1a; 一、隧道定位导航的挑战 在隧道等封闭环境中&#xff0c;由于山体或建筑物的遮挡&#xff0c;卫星信号往往无法直接…

无线领夹麦克风哪个牌子好,揭秘口碑最好降噪领夹麦排行榜

在这个短视频如日中天的时代&#xff0c;无数自媒体创作者纷纷借助这一媒介&#xff0c;通过直播带货、分享生活点滴、在线卡拉OK等形式&#xff0c;捕捉并分享生活中的美好时刻。一个成功的短视频&#xff0c;不仅需要创意构思和稳定的画面质量&#xff0c;更离不开清晰纯净的…

【CSS in Depth 2 精译】2.6 CSS 自定义属性(即 CSS 变量)+ 2.7 本章小结

文章目录 2.6 自定义属性&#xff08;即 CSS 变量&#xff09;2.6.1 动态变更自定义属性 2.7 本章小结 当前内容所在位置 第一章 层叠、优先级与继承第二章 相对单位 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性 …

【日常记录】【插件】js 获取浏览器信息、操作系统等相关信息

文章目录 1. 原生方式2. 插件的方式2.1 Bowser 的基本使用2.2 UAParser2.3 Platform.js 参考链接 1. 原生方式 原生方式可以通过 navigator.userAgent 来获取 需要写一个正则来匹配&#xff0c;获取相关的信息 2. 插件的方式 获取浏览器版本相关信息的库主要有以下几个 Bowser&…

从零开始做题:easycap

题目 给出一个pcap文件 解题 注&#xff1a;传输控制协议&#xff08;TCP&#xff0c;Transmission Control Protocol&#xff09;是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议 .pcap文件需要用Wireshark打开 用Wireshark打开easycap.pcap文…

leetcode--层数最深叶子节点的和

leetcode地址&#xff1a;层数最深叶子节点的和 给你一棵二叉树的根节点 root &#xff0c;请你返回 层数最深的叶子节点的和 。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,4,5,null,6,7,null,null,null,null,8] 输出&#xff1a;15 示例 2&#xff1a; 输入&#xff…

16张支付牌照将到期,新规落地以来,支付牌照的首次续展。

7月9日&#xff0c;包括瑞银信、乐刷、畅捷支付在内的16家第三方支付机构的支付牌照将到期&#xff0c;这些公司面临续展的重大考验。 这是《非银行支付机构监督管理条例》实施以来&#xff0c;支付牌照的首次续期。 其中&#xff0c;最受瞩目的可能是瑞银信。在范一飞落马后&a…

AI绘画:艺术与科技的交融,创新浪潮与无限可能

在科技日新月异的当下&#xff0c;AI 绘画作为人工智能领域的一颗璀璨新星&#xff0c;正以惊人的速度在国内崭露头角&#xff0c;引发了艺术与技术交融的全新变革。随着人工智能技术的飞速发展&#xff0c;AI绘画已成为艺术与科技交融的新宠。2024年&#xff0c;AI绘画行业在国…

最新版萌新Python看过最好的电子书?

我之前写过一篇 Python 入门看哪些书的文章&#xff0c;文章中罗列了 5 位大佬的书单推荐&#xff0c;在这个基础上我总结了自己看过的书单。你要是不知道学 Python 看什么书好&#xff0c;不妨参考一下&#xff1a; 一晃就到了月末&#xff0c;2020年也过去了 2 个月&#xf…

mysql数据库中的视图view的概念和详细说明

目录 一、定义 二、视图view的分类 &#xff08;一&#xff09;按功能和特性分类 1、普通视图&#xff08;Regular View/Standard View&#xff09; 2、索引视图&#xff08;Indexed View&#xff09; 3、分割视图&#xff08;Partitioned View/Distributed Partitioned …

【pytorch23】MNIST测试实战

理解 训练完之后也需要做测试 为什么要做test&#xff1f; 上图蓝色代表train的accuracy 下图蓝色代表train的loss 基本上符合预期&#xff0c;随着epoch增大&#xff0c;train的accuracy也会上升&#xff0c;loss也会一直下降&#xff0c;下降到一个较小的程度 但是如果只看…