RabbitMQ之快速入门、上手

前言

学习一样新技术、新框架,最重要的是学习其思想、原理。即原理性思维。

如果是因为工作原因,需要快速上手RabbitMQ,本篇或许适合你。

核心概念

  • Connection:publisher/consumer 和 broker 之间的 TCP 连接
  • Channel: 消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务
  • Exchange: 消息交换机,它指定消息按什么规则,路由到哪个队列
  • Queue: 消息队列载体,每个消息都会被投入到一个或多个队列
  • VHost: 虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离

image.png

安装

  • 修改host,添加下面数据

192.168.204.179 rabbit

  • 拉取镜像

docker pull rabbitmq:3.8.2-management

  • 启动容器
docker run -d --restart=always \--hostname rabbit \--name=rabbitmq \-p 5671:5617 -p 5672:5672 -p4369:4369 -p 15671:15671 -p 15672:15672 -p 25672:25672 \rabbitmq:3.8.2-management 

5671:开启管理插件时,管理界面接口
5671、5672:AMQP
4369:守护进程
25672:

用户、Virtual Host管理

用户角色

访问管理界面:192.168.204.179:15672
默认账号密码:guest

角色列表:

  • 超级管理员(administrator)可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
  • 监控者(monitoring)可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
  • 策略制定者(policymaker)可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
  • 普通管理者(management)仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
  • 其他无法登陆管理控制台,通常就是普通的生产者和消费者。

image.png

Virtual Hosts配置

每个虚拟主机就相当于一个独立的MQ服务器,虚拟主机之间相互隔离。

  • 创建虚拟主机,主机名称一般以/开头:

image.png

  • 权限设置:

image.png

添加队列

image.png

添加交换机

  • 添加交换机

image.png

  • 绑定Queue

image.png

整合SpringBoot

		<!--amqp协议的起步依赖坐标--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!--rabbit测试依赖坐标--><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency><!--SpringBoot测试依赖坐标--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>

# RabbitMQ 服务host地址
spring.rabbitmq.host=rabbit
# 端口
spring.rabbitmq.port=5672
# 虚拟主机地址
spring.rabbitmq.virtual-host=/mytest
# rabbit服务的用户名
spring.rabbitmq.username=test
# rabbit服务的密码
spring.rabbitmq.password=123456

五种工作模式

1.简单模式

image.png

  • 先添加一个Queue

image.png

  • 生产者
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class)
public class MQTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void contextLoads() {/*** 参数1:消息队列名称* 参数2:消息内容*/rabbitTemplate.convertAndSend("/myqueue", "hello 小兔子!");}}
  • 消费者
@Component
@RabbitListener(queues = "/myqueue")
public class SimpleListener {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====接收消息====>"+msg);}
}

2.工作队列模式

image.png
相比于简单模式,这个模式下会存在多个消费者。

  • 在普通模式基础上,增加订阅者即可:
@Component
@RabbitListener(queues = "/myqueue")
public class SimpleListener2 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====222接收消息====>"+msg);}
}
  • 测试:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class)
public class MQTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void contextLoads() {/*** 参数1:消息队列名称* 参数2:消息内容*/for (int i = 0; i < 10000; i++) {rabbitTemplate.convertAndSend("/myqueue", "hello 小兔子!" + i);}}}

交换机类型

image.png

消息将发给交换机,交换机的类型决定了它会怎么处理这个消息:

  • Direct(直连交换机):使用消息的 Routing Key 与队列的 Binding Key 进行精确匹配,只有消息的 Routing Key 与队列的 Binding Key 完全相同时,消息才会被路由到该队列。非广播
  • Fanout(扇形交换机):忽略消息的 Routing Key,直接将消息发送到所有与交换机绑定的队列。广播消息
  • Topic(主题交换机):使用通配符匹配的方式将消息路由到多个队列。通配符由字符 “#” 和 “” 组成,其中 “#” 表示匹配零个或多个单词,“” 表示匹配一个单词。支持灵活的消息路由。
  • Headers(头交换机):使用消息的 Headers 属性来匹配队列的 Binding Headers,从而确定消息的路由。较少使用,一般情况下使用 Direct、Fanout 或 Topic 类型的交换机就能满足大部分场景。

符号 “#” 匹配一个或多个词,符号""匹配不多不少一个词。因此“audit.#” 能够匹配到“audit.irs.corporate”,但是“audit.” 只会匹配到 “audit.irs”。

总结就是交换机负责消息转发,不进行数据存储,如果没有找到绑定的队列或匹配的队列,消息将会丢失。

3.广播模式

将同一个消息广播到订阅的多个消费者手中。

创建队列和交换机

添加队列
添加交换机
绑定队列到交换机

生产者
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class)
public class MQSPTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void contextLoads() {/*** 参数1:消息队列名称* 参数2:消息内容*/for (int i = 0; i < 10000; i++) {rabbitTemplate.convertAndSend("/fanout_exchange", null, "hello 小兔子!" + i);}}}
消费者
@Component
@RabbitListener(queues = "/fanout_queue1")
public class SimpleListener_Fanout1 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====222接收消息====>"+msg);}
}@Component
@RabbitListener(queues = "/fanout_queue2")
public class SimpleListener_Fanout2 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====3333接收消息====>"+msg);}
}

4.路由模式

在将队列绑定到交换机的时候,需要指定路由key;发送消息的时候也要指明路由key。
image.png

配置交换机

image.png

生产者

/*** 路由**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class)
public class MQRoutingTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void contextLoads() {/*** 参数1:消息队列名称* 参数2:消息内容*/for (int i = 0; i < 10000; i++) {if (i % 2 == 0) {rabbitTemplate.convertAndSend("/routing_exchange", "info", "hello 小兔子!" + i);} else {rabbitTemplate.convertAndSend("/routing_exchange", "err", "hello 小黑子!" + i);}}}}
消费者
@Component
@RabbitListener(queues = "/routing_err1")
public class Routing_Err1 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====routing_err1接收消息====>"+msg);}
}@Component
@RabbitListener(queues = "/routing_err2")
public class Routing_Err2 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====routing_err2接收消息====>"+msg);}
}@Component
@RabbitListener(queues = "/routing_info1")
public class Routing_info1 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====routing_info1接收消息====>"+msg);}
}

5.主题模式(通配符)

#:匹配零个或多个。
*:匹配一个。
image.png

配置

image.png

生产者

/*** topc**/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class)
public class MQTopicTest {@Autowiredprivate RabbitTemplate rabbitTemplate;@Testpublic void contextLoads() {/*** 参数1:消息队列名称* 参数2:消息内容*/for (int i = 0; i < 10000; i++) {if (i % 2 == 0) {rabbitTemplate.convertAndSend("/topic_exchange", "test.info", "hello 小兔子!" + i);} else {rabbitTemplate.convertAndSend("/topic_exchange", "test.err", "hello 小黑子!" + i);}rabbitTemplate.convertAndSend("/topic_exchange", "my.test.warn", "hello 小白子!" + i);}}}
消费者
@Component
@RabbitListener(queues = "/topic_info")
public class Topic1 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====topic_info接收消息====>"+msg);}
}@Component
@RabbitListener(queues = "/topic_err")
public class Topic2 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====topic_err接收消息====>"+msg);}
}@Component
@RabbitListener(queues = "/topic_warn")
public class Topic3 {@RabbitHandlerpublic void simpleHandler(String msg){System.out.println("=====topic_warn接收消息====>"+msg);}
}

工作模式总结

  • 简单模式:一个生产者和一个消费者,无需交换机。
  • 工作队列模式:一个生产者,多个消费者(竞争消息),无需交换机。
  • 发布订阅模式:fanout类型的交换机。消费广播到每个绑定的queue中。
  • 路由模式:direct类型的交换机。消息发送到路由key精确匹配的队列中。
  • 通配符模式:topic类型的交换机。消息发送到通配符匹配的路由key的队列中。

高级特性

生产者确认

rabbitmq提供了两种方式来保证投递的可靠性:

  • confirm 确认模式:消息发到交换机,不管是否成功,都回调confirmCallback。
  • return 退回模式:投递失败会回调returnCallback。
配置
spring:rabbitmq:password: 123456username: testvirtualHost: /mytestport: 5672host: rabbitpublisherReturns: truepublisherConfirmType: SIMPLE
案例
@Slf4j
public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback{@Overridepublic void confirm(CorrelationData correlationData, boolean ack, String cause) {if (ack) {log.info("消息发送到exchange成功");} else {log.info("消息发送到exchange失败");}}
}@Slf4j
public class RabbitReturnCallback implements RabbitTemplate.ReturnsCallback {@Overridepublic void returnedMessage(ReturnedMessage returnedMessage) {log.info("消息发送失败:{}", returnedMessage.getMessage());}
}@Configuration
public class RabbitCallBackConfig {@Resourceprivate RabbitTemplate rabbitTemplate;@PostConstructpublic void initRabbitTemplate(){rabbitTemplate.setConfirmCallback(new RabbitConfirmCallback());rabbitTemplate.setReturnsCallback(new RabbitReturnCallback());}}@RestController
public class TestController {@Resourceprivate RabbitTemplate rabbitTemplate;@GetMapping("confirmCallBack")public String confirmCallBack() {for (int i = 0; i < 10000; i++) {rabbitTemplate.convertAndSend("/routing_exchange", "err", "hello 小黑子!" + i);}return "ok";}@GetMapping("returnCallBack")public String returnCallBack() {for (int i = 0; i < 10000; i++) {// 不存在的routingkeyrabbitTemplate.convertAndSend("/routing_exchange", "err2", "hello 小黑子!" + i);}return "ok";}}

消费者确认

消费者消息确认有三种类型:

  • 无确认:none。收到生产者的消息之后,直接ACK。
  • 手动确认:manual。消费者需要显式的告诉RabbitMQ消息已经确认。手动确认更安全。
  • 自动确认:auto。客户端收到消息之后,mq自动ACK。

为什么手动确认更安全?
消费者处理消息失败时,可以重新处理消息。其它优势:1.消费者可以根据处理能力控制消费速率;2.批量确认多个信息。


import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;import java.util.concurrent.atomic.AtomicInteger;/*** 自定义监听器,监听到消息之后,立即执行onMessage方法*/
@Component
public class CustomAckConsumerListener implements ChannelAwareMessageListener {private static final AtomicInteger errCount = new AtomicInteger();/*** 监听到消息之后执行的方法** @param message 消息内容* @param channel 消息所在频道*/@Overridepublic void onMessage(Message message, Channel channel) throws Exception {//获取消息内容byte[] messageBody = message.getBody();String msg = new String(messageBody, "UTF-8");System.out.println("接收到消息,执行具体业务逻辑{} 消息内容:" + msg);//获取投递标签MessageProperties messageProperties =message.getMessageProperties();long deliveryTag = messageProperties.getDeliveryTag();// 模拟业务错误if(errCount.getAndIncrement() % 2 == 0) {System.out.println("业务报错,重回队列");channel.basicNack(deliveryTag, false, true);return;}// 签收消息,前提条件,必须在监听器的配置中,开启手动签收模式// 参数1:消息投递标签// 数2:是否批量签收:true一次性签收所有,false,只签收当前消息channel.basicAck(deliveryTag, false);System.out.println("手动签收完成:{}");}
}

import cn.lsj.consumer.listener.CustomAckConsumerListener;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ListenerConfiguration {/*** 注入消息监听器适配器** @param customAckConsumerListener 自定义监听器对象*/@Beanpublic MessageListenerAdapter messageListenerAdapter(CustomAckConsumerListener customAckConsumerListener) {//创建自定义监听器适配器对象return new MessageListenerAdapter(customAckConsumerListener);}/*** 注入消息监听器容器** @param connectionFactory      连接工厂* @param messageListenerAdapter 自定义的消息监听器适配器*/@Beanpublic SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory, MessageListenerAdapter messageListenerAdapter) {//简单的消息监听器容器对象SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();//绑定消息队列container.setQueueNames("/routing_err3");//设置连接工厂对象container.setConnectionFactory(connectionFactory);//设置消息监听器适配器container.setMessageListener(messageListenerAdapter);//设置手动确认消息:NONE(不确认消息),MANUAL(手动确认消息),AUTO(自 动确认消息)container.setAcknowledgeMode(AcknowledgeMode.MANUAL);return container;}}

消费端限流

应用场景:

  • 宕机恢复之后处理大量的积压消息导致业务系统再次崩溃。
  • 短时间大量请求来到,业务系统不支持同时处理那么多的消息。

要求:必须为手动确认消息。

package cn.lsj.consumer.config;import cn.lsj.consumer.listener.CustomAckConsumerListener;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class ListenerConfiguration {/*** 注入消息监听器适配器** @param customAckConsumerListener 自定义监听器对象*/@Beanpublic MessageListenerAdapter messageListenerAdapter(CustomAckConsumerListener customAckConsumerListener) {//创建自定义监听器适配器对象return new MessageListenerAdapter(customAckConsumerListener);}/*** 注入消息监听器容器** @param connectionFactory      连接工厂* @param messageListenerAdapter 自定义的消息监听器适配器*/@Beanpublic SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory, MessageListenerAdapter messageListenerAdapter) {//简单的消息监听器容器对象SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();//绑定消息队列container.setQueueNames("/routing_err3");//设置连接工厂对象container.setConnectionFactory(connectionFactory);//设置消息监听器适配器container.setMessageListener(messageListenerAdapter);//设置手动确认消息:NONE(不确认消息),MANUAL(手动确认消息),AUTO(自 动确认消息)container.setAcknowledgeMode(AcknowledgeMode.MANUAL);//设置消费端限流,每次拉取消息多少条,默认是250条container.setPrefetchCount(1);return container;}}

TTL(消息存活时间)

消息过期时间到未被消费则被自动清楚。

可以针对消息设置,也可以针对队列设置。

消息过期时间
rabbitTemplate.convertAndSend("/routing_exchange", "err", "hello 小黑子!" + count.getAndIncrement(), m -> {// 10秒m.getMessageProperties().setExpiration(String.valueOf(10000L));return m;
});
队列过期时间

参数message-TTL ,单位毫秒,在创建队列的时候添加。
image.png

注意点
  • 消息过期的优先级高于队列;
  • 即使消息已经过期,也要等到前面的消费被消费或删除才进一步处理,所以要注意消息堆积的情况。

死信队列

是什么

当消息过期未消费;当消费者拒接消息且不放回源队列;当队列队列达到最大限度时。

以上三个场景,导致了Dead message(死消息)的产生。
image.png

如何设置死信队列

image.png

延迟队列

是什么

消息到达队列之后,不会马上被消费,而是等待一段时间之后才会被消费。

应用场景
  • 定时任务;
  • 订单超时;
  • 定时通知;
  • 消息重试\错误重试:消息放入延迟队列,过一段时间重试;
如何实现?

死信队列配合过期队列实现延迟队列

如下图,我们不设置过期队列的消费者,让消息过期之后进入死信队列,达到延迟效果。
image.png

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

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

相关文章

Android 理解Context

文章目录 Android 理解ContextContext是什么Activity能直接new吗&#xff1f; Context结构和源码一个程序有几个ContextContext的作用Context作用域获取ContextgetApplication()和getApplicationContext()区别Context引起的内存泄露错误的单例模式View持有Activity应用正确使用…

Springboot2+mybatisplus+多数据源更换mysql数据库为pgsql

前提:Springboot2+mybatisplus+多数据源mysql,现在需要把数据源2更换为pgsql 一、pom文件修改 增加pgsql驱动 <postgresql.version>42.7.1</postgresql.version> <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql --><dependency&…

八数码问题

八数码问题 在3x3的棋盘&#xff0c;摆有八个棋子&#xff0c;每个棋子上标有1至8的某一数字&#xff0c;不同棋子上标的数 字不相同。棋盘上还有一个空格&#xff0c;与空格相邻的棋子可以移到空格中。要求解决的问题 是:给出一个初始状态和一个目标状态&#xff0c;找出一一种…

centos 防火墙 设置 LTS

centos 防火墙 设置 LTS https://blog.csdn.net/m0_58805648/article/details/130671008

详解—数据结构—<常用排序>基本实现和代码分析

目录 一.排序的概念及其运用 1.1排序的概念 1.2排序运用​编辑 1.3 常见的排序算法​编辑 二.常见排序算法的实现 2.1 插入排序 2.1.1基本思想&#xff1a; 2.1.2直接插入排序&#xff1a; 2.1.3 希尔排序( 缩小增量排序 ) 2.2 选择排序 2.2.1基本思想&#xff1a; …

日志记录、跟踪和指标

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版&#xff0c;欢迎购买。点击进入详情 日志记录、跟踪和指标是系统可观察性的三大支柱。 下图显示了它们的定义和典型架构。 记录 日志记录系统中的离散事件。例如&#xff0c;我们可以将传入请求或对…

CentOS 8 上安装 Python 3.10.12

以下是在 CentOS 8 上安装 Python 3.10.12 的全流程&#xff0c;包括下载、编译和安装。请在执行这些步骤之前确保您具有足够的权限。 安装编译依赖项&#xff1a; sudo dnf install -y gcc openssl-devel bzip2-devel libffi-devel zlib-devel readline-devel sqlite-devel下载…

论文阅读——UniRepLKNet

UniRepLKNet: A Universal Perception Large-Kernel ConvNet for Audio, Video, Point Cloud, Time-Series and Image Recognition 当我们将一个33的conv添加到一个小卷积核ConvNet中时&#xff0c;我们预计它会同时产生三种效果——1&#xff09;使感受野更大&#xff0c;2&am…

Linux:多文件编辑

多文件编辑 1.使用vim编辑多个文件 编辑多个文件有两种形式&#xff0c;一种是在进入vim前使用的参数就是多个文件。另一种就是进入vim后再编辑其他的文件。 同时创建两个新文件并编辑 $ vim 1.txt 2.txt默认进入1.txt文件的编辑界面 命令行模式下输入:n编辑2.txt文件&…

从C到C++1

一.思想过渡 前言&#xff1a;明确地说&#xff0c;学了C语言就相当于学了 C 的一半&#xff0c;从C语言转向 C 时&#xff0c;不需要再从头开始&#xff0c;接着C语言往下学就可以&#xff0c;所以我强烈建议先学C语言再学 C。 1.面向过程与面向对象 ​ 从“学院派”的角度来…

Python之自然语言处理库snowNLP

一、介绍 SnowNLP是一个python写的类库&#xff0c;可以方便的处理中文文本内容&#xff0c;是受到了TextBlob的启发而写的&#xff0c;由于现在大部分的自然语言处理库基本都是针对英文的&#xff0c;于是写了一个方便处理中文的类库&#xff0c;并且和TextBlob不同的是&…

在ubuntu上挂载QNX 镜像

步骤 1&#xff0c;将QNX imge转换成android sparse镜像 这个QNX镜像可以是直接从QNX分区读取得到或者你的刷机包中的镜像&#xff1a; rootubuntu:~/workspace/$ file qnx_img.img qnx_img.img: DOS/MBR boot sector使用python tools/mksparse.py $镜像文件 转换为android …

elasticsearch 笔记三:查询建议介绍、Suggester、自动完成

一、查询建议介绍 1. 查询建议是什么&#xff1f; 查询建议&#xff0c;为用户提供良好的使用体验。主要包括&#xff1a; 拼写检查&#xff1b; 自动建议查询词&#xff08;自动补全&#xff09; 拼写检查如图&#xff1a; 自动建议查询词&#xff08;自动补全&#xff09;…

Rust之构建命令行程序(二):读取文件

开发环境 Windows 10Rust 1.74.1 VS Code 1.85.1 项目工程 这次创建了新的工程minigrep. 读取文件 现在&#xff0c;我们将添加读取file_path参数中指定的文件的功能。首先&#xff0c;我们需要一个样本文件来测试它:我们将使用一个包含少量文本的文件&#xff0c;多行包含一…

使用Python实现Linux惠尔顿上网认证客户端

在本文中&#xff0c;我们将展示如何使用Python编写一个简单的脚本来实现Linux下的惠尔顿上网认证。以下是我们需要的参数和值&#xff1a; wholeton_host: 惠尔顿服务器地址&#xff0c;例如 192.168.10.10wholeton_user: 用户名&#xff0c;例如 AABBCCwholeton_pass: 密码&…

【图像分类】【深度学习】【轻量级网络】【Pytorch版本】ShuffleNet_V2模型算法详解

【图像分类】【深度学习】【轻量级网络】【Pytorch版本】ShuffleNet_V2模型算法详解 文章目录 【图像分类】【深度学习】【轻量级网络】【Pytorch版本】ShuffleNet_V2模型算法详解前言ShuffleNet_V2讲解四条实用指导思想G1:相等的通道宽度可以降低存储访问成本G2:大量的分组卷积…

uboot学习及内核更换_incomplete

官方文档 在前面 文章目录 uboot常见命令学习环境变量网络控制台uboot标准启动其他 升级uboot或内核bin和uimg以及booti和bootm的区别制作uImage更换内核更换uboot后续计划 uboot常见命令学习 环境变量 Environment Variables环境变量 autostart 如果值为yes&#xff0c;则会…

labelme将JSON标记文件转换为二值PNG图像

看了好几篇博客。在使用他们的代码时&#xff0c;出现了各种各样的问题&#xff1b;在底下留言时&#xff0c;博主大多是充耳不闻。感觉CSDN的质量越来越次了&#xff0c;有时候真还不如直接问chatGPT呢。 要将labelme生成的JSON标记文件转换为PNG二值图像&#xff0c;只需运行…

【Shell编程练习】监控内存和磁盘容量,小于给定值时报警

系列文章目录 输出Hello World 通过位置变量创建 Linux 系统账户及密码 系列文章目录分析代码实现运行结果 分析 对于磁盘容量&#xff0c;可以使用df命令查看指定指定分区的磁盘使用情况。比如 然后我们需要从这段输出中提取我们想要的信息。在这里就是Available字段的值。…

【wargames】bandit0~9关wp

第1关直接ssh连接&#xff0c;获得密码NH2SXQwcBdpmTEzi3bvBHMM9H66vVXjL&#xff0c;用这个密码连接第2关 第2关&#xff0c;连接之后查看 存在特殊字符的文件 因为使用 - 作为参数是指 STDIN/STDOUT 即 dev/stdin 或 dev/stdout 。所以如果你想打开这种类型的文件&#xff0…