当前位置: 首页 > news >正文

RabbitMQ 消息队列

1. 消息队列是什么?

当用户注册成功后,就发送邮件。当邮件发送成功了,接口才会提示注册成功信息。但由于发送邮件,依赖于其他厂商的服务,有可能他们的接口会非常耗时。那么用户就一直要等着邮件发送成功了,才提示注册成功。因为耗时很长,这样就会造成很糟糕的体验。

然后大家想一想,我们到底有没有必要等着邮件发送完成呢?就好比大家去邮局寄信,当你把信丢入邮筒里,你需要一直等着信送到别人手里,然后你再离开吗?

当然不需要,只要将信丢入邮筒,我们人就可以离开了。因为你知道,在将来的某个时候,你的信就会被寄到收件人手里。

消息队列,就好比是这里寄信的过程!消息队列由三部分构成:

在这里插入图片描述

  • 生产者(Producer):创建并发送消息,相当于去邮局寄信的人。
  • 队列(Queue):用来存放消息的,将消息从生产者传递到消费者,就相当于邮局了。邮局收到你的任务后,它去处理是需要排队的。按照先进先出的原则,需要等其他先来的任务处理完了,才会处理你的任务。
  • 消费者(Consumer):接收并处理消息的人。当邮局把信送到他手里了,收到消息了,最终处理任务的人。

还是以我们注册功能为例。当用户注册成功了,我们就通知RabbitMQ,你去发个邮件,然后就直接提示用户注册成功。我们完全没有必要等待邮件发送完成。

接着再写一个程序去接收消息,当它收到消息了,就去执行发邮件任务了。

所以,生产者、消费者,都是我们要写的程序。一个负责提交任务,另一个负责处理任务。互相之间通信,就靠中间的RabbitMQ。

2. 安装

2.1. 使用 Docker

当然,我最推荐的还是用Docker,因为太方便了,大家打开docker-compose.yml。增加RabbitMQ的配置,注意缩进非常重要,一定要和之前的MySQL和Redis的配置对齐

services:mysql:# ....redis:# ....rabbitmq:image: rabbitmq:4.0-managementports:- "5672:5672"- "15672:15672"volumes:- ./data/rabbitmq:/var/lib/rabbitmq # 持久化数据environment:RABBITMQ_DEFAULT_USER: adminRABBITMQ_DEFAULT_PASS: xw
  • 我们这里使用的RabbitMQ版本号是:4.0
  • 将RabbitMQ运行的默认端口567215672,映射到本机上。
  • 其中15672RabbitMQ自带的管理后台端口号
  • 接着将RabbitMQ的用来持久化数据的备份数据映射到项目根目录的data/rabbitmq目录中。
  • 最下面的是RabbitMQ用来连接的账号密码,大家可以根据需要自己设置。
    完成后,命令行,再次运行
docker-compose up -d

这样Docker,就会自动下载,并启动好RabbitMQ。
在这里插入图片描述

2.2. 直接安装

对于部分Windows上用不了Docker的同学,那就有点麻烦了。因为既要安装Erlang,又要安装RabbitMQ。这里附上下载地址:

  • Erlang下载地址:https://www.erlang.org/downloads
    -在这里插入图片描述

  • RabbitMQ下载地址:https://www.rabbitmq.com/docs/install-windows#downloads

  • 在这里插入图片描述
    对于这种安装方式,如果在安装过程出现了各种问题,请来讨论群中和我讨论。总而言之,我还是推荐大家尽可能,想办法将Docker跑通。

2.3.1 安装完ErlangRabbitMQ后,添加环境变量

打开环境变量设置窗口: 右键点击 “此电脑”,选择 “属性”。 在弹出的窗口中,点击 “高级系统设置”。 在 “系统属性” 窗口中,点击 “环境变量” 按钮。 添加 RabbitMQ 命令路径到系统的 Path 变量: 在 “系统变量” 列表中找到 “Path” 变量,选中它并点击 “编辑” 按钮。 在弹出的 “编辑环境变量” 窗口中,点击 “新建”,然后将 RabbitMQ 的 sbin目录路径添加进去,
例如 C:\Program Files\RabbitMQServer\rabbitmq_server-<version>\sbin。注意要将 替换为你实际安装的 RabbitMQ 版本号。 点击 “确定” 保存设置,依次关闭所有窗口 具体选择你自己安装的路径>。

2.3.2 通过命令行(管理员)安装rabbitmq_management 插件

RabbitMQ 的管理界面依赖于rabbitmq_management 插件

rabbitmq-plugins enable rabbitmq_management
2.3.3 通过命令行(管理员)运行
rabbitmq-service start
2.3. RabbitMQ 管理后台

启动好后,稍等个几秒钟,用浏览器访问:http://127.0.0.1:15672/,就能进入RabbitMQ的管理界面了

以游客模式登录 账号:guest 密码:guest

2.3.2.1 新增账号密码

在这里插入图片描述

在这里插入图片描述
输入刚才docker-compose.yml里的设置账号密码,就能进去了。里面的东西很多,先不用管它,一会儿再来看。

在这里插入图片描述

3. 官方案例解析

学习任何东西之前,最好的办法,无疑就是看官方文档了。
直接看JavaScript章节的Hello World部分。很明显,用之前先要装包

npm i amqplib

amqplib官方文档

3.1. 生产者:send.js

public目录里,新建一个send.js,代码大家从讲义文档直接复制过来。

amqplib.connect(‘amqp://admin:xw@localhost’) 参数详解

字段注解
amqp://表示使用 AMQP 协议进行连接
admin连接到 RabbitMQ 服务器时使用的用户名,用于身份验证
xw是与用户名对应的密码,用于验证用户身份。用户名和密码通过冒号 : 分隔
localhost指定了 RabbitMQ 服务器所在的主机地址,这里表示服务器运行在本地机器上。如果 RabbitMQ 服务器部署在其他机器上,需要将 localhost 替换为实际的 IP 地址或域名
const amqplib = require('amqplib');(async () => {try {const connection = await amqplib.connect('amqp://admin:xw@localhost');// 创建一个通道。通道是进行通信的基本单位,通过通道可以发送和接收消息const channel = await connection.createChannel();// 队列的名字是:helloconst queue = 'hello';// 要发送的消息内容是:你好,xw!const msg = '你好,xw!';// 创建一个队列。如果队列不存在,则创建一个队列。如果队列已经存在,则不会创建新的队列// durable: 表示队列是否持久化。如果设置为true,即重启后队列不会消失await channel.assertQueue(queue, { durable: true });// 发送消息到队列// queue: 要发送消息的队列的名字// content: 要发送的消息内容// persistent: true,消息持久化,确保消息在 RabbitMQ 重启后仍然存在。channel.sendToQueue(queue, Buffer.from(msg), { persistent: true });// 打印发送提示信息console.log('[x] 发送了:%s', msg);// 500ms 后关闭连接setTimeout(() => {connection.close();process.exit(0);}, 500);} catch (error) {console.log(error);}
})();

我们一点点分析下,它这里都写了些什么东西。
1、连接 const connection = await amqplib.connect(‘amqp://admin:clwy1234@localhost’)
2、创建一个通道。通道是进行通信的基本单位,只有通过通道,才可以发送和接收消息
3、我们定义了队列的名字是:hello。并定义了要发送的消息内容是:你好,xw!
4、创建了一个队列。但如果队列已经存在,那就直接使用,不会创建新的了。这里要把队列的名字放进去,也就是hello
这里还有个参数:durable: false,它表示队列是否持久化 false:不持久化,true:队列的信息会被写入磁盘,也就是docker-compose里设置的./data/rabbitmq,当RabbitMQ服务重启后,队列会被自动恢复
5、channel.sendToQueue,很明显,这就是将消息发送到队列了。
接着做了个console.log提示,可以显示在命令行里,便于我们观察。
最后面,等500ms后,将连接断开

看完后,我们就先将它跑起来,看看到底有个什么效果。用cd命令,进入public目录中。然后直接用node运行这个文件

cd public
node send.js

打开RabbitMQ的管理后台:http://127.0.0.1:15672/

里面的菜单,依次是:

  • 概览:Overview
  • 连接:Connections
  • 通道:Channels
  • 交换机:Exchanges
  • 队列和流:Queues and Streams
  • 管理用户:Admin

由于代码里,在500ms之后,就将连接关闭了。所以连接和通道里,都看不到东西。大家点击队列这里,里面可以看到hello队列了。这正是我们刚才创建的队列名字。
在这里插入图片描述
点进去看,里面可以看到队列的一些详细内容。

  • 上面有一些统计信息。一共收到了一条信息,准备好的有几条,在内存中的又几条,占有了多少空间、多少内存什么的。
    在这里插入图片描述

  • 再往下看,注意这里有个发送消息(Publish message)获取消息(Get message)

  • 我们先点获取消息,这里就能看到刚才发送的:你好,xw

在这里插入图片描述

4.2. receive.js

刚才是生产者的代码,我们接着继续看消费者的代码。在public目录中新建receive.js

const amqplib = require('amqplib');(async () => {try {// 连接到 RabbitMQconst connection = await amqplib.connect('amqp://admin:clwy1234@localhost');// 创建一个通道。通道是进行通信的基本单位,通过通道可以发送和接收消息const channel = await connection.createChannel();// 队列的名字是:helloconst queue = 'hello';// 创建一个队列。如果队列不存在,则创建一个队列。如果队列已经存在,则不会创建新的队列// durable: 表示队列是否持久化。如果设置为true,即重启后队列不会消失await channel.assertQueue(queue, { durable: true });// 打印等待接收消息的提示信息console.log(' [*] 等待接收消息在 %s 队列中. 按 CTRL+C 退出', queue);// 当接收到消息channel.consume(queue, (msg) => {// 打印接收到的消息内容console.log('[x] 接收到了:%s', msg.content.toString());// 如果不是自动确认,需要手动确认消息// channel.ack(msg);}, {// noAck: 表示是否自动确认消息,设置为true表示自动确认,设置为false表示手动确认// 如果设置为false,需要手动确认消息,否则消息会被重复消费。例如:channel.ack(msg)noAck: true});} catch (error) {console.log(error);}
})();

我们来运行一下,

node receive.js

在这里插入图片描述
再回去刷新页面,也多刷新个几次。因为刚才的两条消息都已经处理完成了,所以现在的准备好的(Ready)和在内存中的(In memory)都是0了。
在这里插入图片描述
点击连接(Connections),因为我们这次的消费者代码,并没有关闭连接,所以一直连在RabbitMQ上
在这里插入图片描述
点击通道(Channels),里面也能看到创建的通道。
在这里插入图片描述

4. noAck 自动、手动确认消息

关于自动确认消息,大家可以改为

noAck: false
ack(确认)当消费者成功处理完一条消息后,会向 RabbitMQ 服务器发送一个确认信号(ack),告知服务器该消息已经被成功消费,服务器可以将该消息从队列中移除
nack(否定确认)当消费者处理消息失败或者遇到某些异常情况时,会向 RabbitMQ 服务器发送一个否定确认信号(nack),表示消息处理未成功。根据不同的配置,服务器会对该消息进行不同的处理,比如重新入队、丢弃等。

channel.nack(message, multiple, requeue); 参数

参数注释
message该参数代表需要进行否定确认的消息对象,也就是消费者从队列中接收到的消息。这个消息对象包含了消息的内容、属性等信息
multiple这是一个布尔类型的参数,用于指定是否批量否定确认消息。当 multiple 为 true 时,表示会将当前消费者已经接收到但还未确认(包括 ack 和 nack)的所有消息进行否定确认。这在需要一次性处理多个未确认消息时很有用,可以提高处理效率。当 multiple 为 false 时,仅对当前传入的这一条消息进行否定确认。
requeue同样是布尔类型的参数,用于控制消息在被否定确认后的去向。当 requeue 为 true 时,消息会被重新放回原队列中,通常会被放置在队列的尾部,之后可能会再次被分发给其他消费者或者当前消费者(取决于 RabbitMQ 的分发策略)。这种方式适用于消息处理失败是由于临时原因导致的情况,例如网络抖动、数据库短暂不可用等,让消息有机会被重新处理。当 requeue 为 false 时,消息不会被重新放回原队列,而是会被丢弃或者根据死信队列(Dead Letter Queue,DLQ)的配置进行处理。死信队列用于存储那些无法被正常消费的消息,方便后续分析和处理

这样就需要手动确认消息了,我们先不确认。将接收消息的终端重启一下,重新发送一次,可以看到收到信息了。
CTRL+C停止后,再次接收消息,发现还能接收到这个消息。这就错了,按道理消息被处理完成后,就不应该重复收到了。

这就是因为,由于我们没有手动确认,所以RabbitMQ,认为消息一直没有被处理成功,就会不断的发过来,让你处理。
在这里插入图片描述
加上

// 当接收到消息
channel.consume(queue, function (msg) {console.log('[x] 接收到了:%s', msg.content.toString());// 如果不是自动确认,需要手动确认消息channel.ack(msg);}, {noAck: false
});

CTRL+C停止后,重新连接,再接收一次。现在的代码里,已经将消息确认了。再次按CTRL+C停止,再连接上去,就不会收到重复的消息了。
在这里插入图片描述
那么ack设计的目的,是让你有更高的灵活度。因为有些任务的执行,有可能失败,需要重试。我这里有个代码示例,大家可以参考一下。

// 模拟处理逻辑
channel.consume(queue, function (msg) {try {// 假设处理成功,手动确认消息channel.ack(msg);} catch (error) {// 处理失败,可以选择拒绝消息,将消息从队列中删除// nack:否定确认):当消费者处理消息失败或者遇到某些异常情况时,会向 RabbitMQ 服务器发送一个否定确认信号(nack),表示消息处理未成功。根据不同的配置,服务器会对该消息进行不同的处理,比如重新入队、丢弃等。channel.nack(msg, false, false);console.error(error);}
}, {noAck: false
});

总结

1、消息队列的组成

基础的消息队列,由三部分组成:生产者、队列和消费者。

名称说明
生产者将消息发送到队列
队列临时存储消息,按照先进先出的原则,在生产者和消费者之间传递消息
消费者监听队列,收到消息后进行处理。
2、RabbitMQ 的方法
方法说明
const connection = amqplib.connect连接到 RabbitMQ
connection.close关闭连接
const channel = connection.createChannel创建通道
channel.assertQueue创建队列
channel.sendToQueue发送消息
channel.consume接收消息
channel.ack确认消息,消息被成功处理。
channel.nack拒绝消息,消息处理失败。
3、nack的参数
参数注释
message该参数代表需要进行否定确认的消息对象,也就是消费者从队列中接收到的消息。这个消息对象包含了消息的内容、属性等信息
multiple这是一个布尔类型的参数,用于指定是否批量否定确认消息。当 multiple 为 true 时,表示会将当前消费者已经接收到但还未确认(包括 ack 和 nack)的所有消息进行否定确认。这在需要一次性处理多个未确认消息时很有用,可以提高处理效率。当 multiple 为 false 时,仅对当前传入的这一条消息进行否定确认。
requeue同样是布尔类型的参数,用于控制消息在被否定确认后的去向。当 requeue 为 true 时,消息会被重新放回原队列中,通常会被放置在队列的尾部,之后可能会再次被分发给其他消费者或者当前消费者(取决于 RabbitMQ 的分发策略)。这种方式适用于消息处理失败是由于临时原因导致的情况,例如网络抖动、数据库短暂不可用等,让消息有机会被重新处理。当 requeue 为 false 时,消息不会被重新放回原队列,而是会被丢弃或者根据死信队列(Dead Letter Queue,DLQ)的配置进行处理。死信队列用于存储那些无法被正常消费的消息,方便后续分析和处理
4、 RabbitMQ 的参数
字段说明
durable: true队列持久化,队列信息将被写入磁盘,在RabbitMQ服务重启后仍然存在。但是队列已经创建过后,这个参数就没法改了,可以删掉队列,重新建一个新的。
persistent: true消息持久化,消息将会被写入磁盘,在RabbitMQ服务重启后仍然存在。
noAck: true自动确认消息,只要收到了就会自动确认。如果设置成false,则需要手动确认。

使用RabbitMQ发送邮件

相关文章:

RabbitMQ 消息队列

1. 消息队列是什么&#xff1f; 当用户注册成功后&#xff0c;就发送邮件。当邮件发送成功了&#xff0c;接口才会提示注册成功信息。但由于发送邮件&#xff0c;依赖于其他厂商的服务&#xff0c;有可能他们的接口会非常耗时。那么用户就一直要等着邮件发送成功了&#xff0c;…...

idea从远程gitee拉取项目

文章目录 从gitee上面拿到项目地址填写远程地址,并且设置项目保存位置拉取成功 从gitee上面拿到项目地址 填写远程地址,并且设置项目保存位置 拉取成功...

PHP集成软件用哪个比较好?

在Windows环境下&#xff0c;使用PHP时&#xff0c;通常需要一个集成开发环境&#xff08;IDE&#xff09;或者集成软件来简化开发和调试过程。以下是几款常用且推荐的PHP集成软件&#xff0c;每款都有其特点&#xff0c;可以根据需求进行选择&#xff1a; 1. XAMPP 特点&…...

Es的text和keyword类型以及如何修改类型

昨天同事触发定时任务发现es相关服务报了一个序列化问题&#xff0c; 今天早上捕获异常将异常堆栈全部打出来看&#xff0c;才发现是聚合的字段不是keyword类型的问题。 到kibbna命令行执行也是一样的错误 使用 /_mapping查看索引的字段类型&#xff0c;才发现userUniqueid是te…...

【找工作】C++和算法复习(自用)

文章目录 C头文件自定义排序函数stl 算法数据结构树状数组 数学 自用随便记录 C 排序 stl 头文件 全能头文件&#xff1a; #include<bits/stdc.h>自定义排序函数 bool compare(const int &odd1,const int &odd2) {return odd1>odd2; }stl 枚举map map&…...

Python VsCode DeepSeek接入

Python VsCode DeepSeek接入 创建API key 首先进入DeepSeek官网&#xff0c;https://www.deepseek.com/ 点击左侧“API Keys”&#xff0c;创建API key&#xff0c;输出名称为“AI” 点击“创建"&#xff0c;将API key保存&#xff0c;复制在其它地方。 在VsCode中下载…...

开放表格式和对象存储架构指南

比较 Apache Iceberg、Delta Lake 和 Apache Hudi&#xff0c;并了解如何为您的数据湖仓一体选择合适的开放表格式。开放表格式和对象存储正在重新定义组织构建其数据系统的方式&#xff0c;为可扩展、高效且面向未来的数据湖仓一体奠定了基础。通过利用对象存储的独特优势&…...

Netty入门详解

引言 Netty 是一个基于 Java 的高性能、异步事件驱动的网络应用框架&#xff0c;用于快速开发可维护的高性能网络服务器和客户端。它提供了一组丰富的 API&#xff0c;使得开发人员能够轻松地处理各种网络协议&#xff0c;如 TCP、UDP 等&#xff0c;并且支持多种编解码方式&a…...

我国首条大型无人机城际低空物流航线成功首航

首航震撼开场&#xff1a;羊肉 “飞” 越 540 公里 在夜色的笼罩下&#xff0c;榆阳马合通用机场的跑道上&#xff0c;一架大型固定翼无人机蓄势待发&#xff0c;机身被灯光照亮&#xff0c;宛如一只即将展翅翱翔的钢铁巨鸟。它的货舱里&#xff0c;满满装载着新鲜的榆林羊肉&a…...

【数据挖掘】--算法

【数据挖掘】--算法 目录&#xff1a;1. 缺失值和数值属性处理1缺失值处理&#xff1a; 2. 用于文档分类的朴素贝叶斯3. 分治法&#xff1a;建立决策树4. 覆盖算法建立规则5. 挖掘关联规则6. 线性模型有效寻找最近邻暴力搜索&#xff08;Brute-Force Search&#xff09;kd树&am…...

C++初阶——简单实现vector

目录 1、前言 2、Vector.h 3、Test.cpp 1、前言 简单实现std::vector类模板。 相较于前面的string&#xff0c;vector要注意&#xff1a; 深拷贝&#xff0c;因为vector的元素可能是类类型&#xff0c;类类型元素可以通过赋值重载&#xff0c;自己实现深拷贝。 迭代器失效…...

三、Three.js模型对象、材质

一、三维向量Vector3与模型位置 点模型Points、线模型Line、网格网格模型Mesh等模型对象的父类都是Object3D&#xff0c;如果想对这些模型进行旋转、缩放、平移等操作&#xff0c;如何实现&#xff0c;可以查询Threejs文档Object3D对相关属性和方法的介绍 1、三维向量Vector3 …...

C# 背景 透明 抗锯齿 (效果完美)

主要是通过 P/Invoke 技术调用 Windows API 函数 gdi32.dll/user32.dll&#xff0c;同时定义了一些结构体来配合这些 API 函数的使用&#xff0c;常用于处理图形绘制、窗口显示等操作。 运行查看效果 局部放大&#xff0c;抗锯齿效果很不错,尾巴毛毛清晰可见。 using System; u…...

Ubuntu 22.04 一键部署MinerU1.1.0

MinerU MinerU是一款将PDF转化为机器可读格式的工具&#xff08;如markdown、json&#xff09;&#xff0c;可以很方便地抽取为任意格式。 MinerU诞生于书生-浦语的预训练过程中&#xff0c;我们将会集中精力解决科技文献中的符号转化问题&#xff0c;希望在大模型时代为科技发…...

10、k8s对外服务之ingress

service和ingress的作用 service的作用 NodePort&#xff1a;会在每个节点开放一个端口&#xff0c;端口号30000-32767。 也是只能用于内网访问&#xff0c;四层转发。实现负载均衡。不能基于域名进行访问。 clusterip&#xff1a;service的默认类型&#xff0c;只能在集群…...

mysql面试题

一、基础概念 什么是主键&#xff08;Primary Key&#xff09;&#xff1f; 答案&#xff1a; 唯一标识表中每行数据的字段或字段组合&#xff0c;不允许 NULL 值&#xff0c;确保数据唯一性。 外键&#xff08;Foreign Key&#xff09;的作用是什么&#xff1f; 答案&#xf…...

什么是关系型数据库?什么是非关系型数据库?

关系型数据库&#xff1a;关系型数据库是基于关系模型的数据库&#xff0c;它将数据组织成二维表格的形式&#xff0c;每个表格称为一个表&#xff08;Table&#xff09;&#xff0c;表中的每一行称为一条记录&#xff08;Record&#xff09;或元组&#xff08;Tuple&#xff0…...

科技云报到:科技普惠潮流渐起,“开源”将带我们走向何方?

科技云报到原创。 开源决定软件未来&#xff0c;已成为全球技术和产业创新的主导模式之一。“开源”思想的诞生&#xff0c;可以说是计算机发展史中极具理想主义和浪漫主义色彩的一页&#xff0c;是科技自由与技术极客思想的延伸。 数字化浪潮奔涌&#xff0c;从软件开发的底…...

校园网架构设计与部署实战

一、学习目标 掌握校园网分层架构设计原则 理解多业务VLAN规划方法 学会部署认证计费系统 实现基础网络安全防护 二、典型校园网场景 需求分析&#xff1a;某中学需建设新型校园网络 覆盖教学楼/宿舍/图书馆三区域 区分教师/学生/访客网络权限 满足2000终端并发接入 …...

【含开题报告+文档+PPT+源码】基于Springboot的乡村老龄居民信息管理系统

开题报告 本文介绍了一个基于Spring Boot框架的乡村老龄居民信息管理系统。该系统旨在通过信息化手段&#xff0c;提高乡村老龄居民的生活质量&#xff0c;并为相关部门提供便捷的数据管理和服务支持。系统主要实现了用户注册登录、个人信息查看、健康数据录入、健康建议查询、…...

前端插件使用xlsx-populate,花样配置excel内容,根据坐添加标替换excel内容,修改颜色,合并单元格...。

需求要求&#xff1a;业务人员有个非常复杂得excel表格&#xff0c;各种表头等&#xff0c;但是模板是固定得。当然也可以实现在excel上搞出各种表格&#xff0c;但是不如直接用已有模板替换其中要动态得内容方便&#xff0c;这里我们用到CSDN得 xlsx-populate 插件。 实列中我…...

Mac m1 连接公司内网

1、创建VPN 1、在系统偏好设置 2、选择网络 3、进行添加 2、添加设置 1、选择VPN 2、类型选择L2TP/IPSec 3、填写服务器IP和账号 4、点击认证设置-填写密码 。然后应用 3、进行特殊配置 网上说苹果系统的问题。 1、创建命令 sudo vim /etc/ppp/options 2、添加内容-主要别…...

Jenkins 部署在 Mac 并在局域网内通过 ip 访问

Jenkins 部署在 Mac 并在局域网内通过 ip 访问 一、修改配置文件 打开文件 ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist 打开文件 /usr/local/opt/jenkins/homebrew.mxcl.jenkins.plist 两个文件目录不同&#xff0c;内容一样 <?xml version"1.0" e…...

臻识相机,华夏相机,芊熠车牌识别相机加密解密

臻识&#xff0c;华夏&#xff0c;芊熠这三种车牌识别相机解密我都试过了&#xff0c;可以正常解密成功&#xff0c;其它品牌我暂时没有测试。超级简单&#xff0c;免费的&#xff0c;白嫖无敌&#xff01; 流程&#xff1a; ①&#xff1a;先导出配置文件&#xff0c;例如我以…...

【Python 专题】数据结构 树

LeetCode 题目104. 二叉树的最大深度(gif 图解)方法一:后序遍历(DFS)方法二:层序遍历(BFS)872. 叶子相似的树(DFS 遍历)1448. 统计二叉树中好节点的数目(DFS 遍历)437. 路径总和 III(前缀和 + DFS 回溯)1372. 二叉树中的最长交错路径(DFS)236. 二叉树的最近公共…...

【飞行器原理学习】——1. 机翼及机翼参数

飞行器原理学习——1.机翼 一、 概述 飞机的各种机翼是飞机的控制面 通过铰链、钢索、液压等方式连接在机身上 操纵面运动时&#xff0c;会改变机翼的弧度和形状&#xff0c;使流经的空气发生偏转&#xff0c;从而影响空气动力的大小。使飞机围绕着3轴运动 二、机翼的操纵面…...

css之display:grid布局改块级元素布局

1.问题&#xff1a; div是块级元素&#xff0c;一个div元素占一行&#xff0c;但是&#xff0c;今天测试样式时&#xff0c;总是会有两个div并占一行&#xff0c;很困惑&#xff0c;结果发现是app这个样式 在main.css里 #app样式布局在main.ts里被应用 2.原因以及样式分析 im…...

如何组织和管理JavaScript文件:最佳实践与策略

在现代Web开发中&#xff0c;JavaScript已经成为不可或缺的一部分。随着项目规模的扩大&#xff0c;JavaScript代码的复杂性也随之增加。如何有效地组织和管理这些文件&#xff0c;不仅影响开发效率&#xff0c;还直接关系到项目的可维护性和可扩展性。本文将深入探讨如何组织和…...

Vue 中组件通信的方式有哪些,如何实现父子组件和非父子组件之间的通信?

一、父子组件通信&#xff08;垂直通信&#xff09; 1. Props 传值&#xff08;父 → 子&#xff09; 实现方案&#xff1a; <!-- Parent.vue --> <template><Child :user"userData" /> </template><script setup> import { ref } …...

伯克利 CS61A 课堂笔记 11 —— Mutability

本系列为加州伯克利大学著名 Python 基础课程 CS61A 的课堂笔记整理&#xff0c;全英文内容&#xff0c;文末附词汇解释。 目录 01 Objects 02 Example: Strings Ⅰ Representing Strings: the ASCII Standard Ⅱ Representing Strings: the Unicode Standard 03 Mutatio…...

MacOS安装Emacs

个人博客地址&#xff1a;MacOS安装Emacs | 一张假钞的真实世界 在MacOS X上可以使用Homebrew 安装Emacs&#xff1a; $ brew install emacs --with-cocoa 或者用MacPorts&#xff1a; $ sudo port install emacs-app OSX Emacs 网站提供了通用的二进制包。 前两种方法安装…...

基于海思soc的智能产品开发(图像处理的几种需求)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 对于一个嵌入式设备来说&#xff0c;如果上面有一个camera&#xff0c;那么就可以有很多的用途。简单的用途就是拍照&#xff0c;比拍照更多一点的…...

百度智能云AI收入增3倍,2025开源引流打赢生态战

免费、开源。在DeepSeek重塑产业价值观念后&#xff0c;百度、OpenAI等AI时代的“领航员”纷纷采取行动。 随着开源以雷霆万钧之势袭来&#xff0c;百度下定决心求变。而其底气&#xff0c;就藏在这份财报中。根据财报&#xff0c;2024年&#xff0c;百度集团总收入为1331亿元…...

[数据结构]顺序表详解

目录 一.线性表 二.顺序表 2.1概念及结构 1. 静态顺序表&#xff1a;使用定长数组存储元素。 2. 动态顺序表&#xff1a;使用动态开辟的数组存储。 2.1按需申请 2.2 接口实现&#xff1a;增删查改 SeqList.h: SeqList.c: test.c 一.线性表 线性表 &#xff08; line…...

力扣hot100 ——搜索二维矩阵 || m+n复杂度优化解法

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 解题思路&#xff1a; 借助行和列有序特性&#xff0c;不断按行或者列缩小范围&#xff1b;途中数字表示每…...

VirtualBox 中使用 桥接网卡 并设置 MAC 地址

在 VirtualBox 中使用 桥接网卡 并设置 MAC 地址&#xff0c;可以按照以下步骤操作&#xff1a; 步骤 1&#xff1a;设置桥接网卡 打开 VirtualBox&#xff0c;选择你的虚拟机&#xff0c;点击 “设置” (Settings)。进入 “网络” (Network) 选项卡。在 “适配器 1” (Adapt…...

ETL工具: Kettle入门(示例从oracle到oracle的数据导入)

kettle介绍 ETL工具,用于对数据的抽取&#xff08;Extract), 转换(Transform),加载 (Load&#xff09; Kettle 是一种ETL工具, 现称为 Pentaho Data Integration (PDI) 特点:纯JAVA语言编写 官方学习文档 网站: https://docs.hitachivantara.com/r/en-us/pentaho-data-int…...

未来AI方向落地场景:小语言模型,super_private_agent

未来AI方向落地场景:小语言模型,super_private_agent 目录 未来AI方向落地场景:小语言模型,super_private_agent小语言模型super - private - agent(注重隐私的智能代理)碳基生命和硅基生命交互界面面向agent的专用交互协议和数据接口从web平台经济到网络平台举例说明社交…...

Oracle RAC数据库单节点轮流重启

0、sqlplus / as sysdba 备份参数文件 create pfile/home/oracle/pfile.ora from spfile; 备份控制文件 Alter database backup controlfile to trace; 1、关闭两节点的监听&#xff1b; 2、操作系统层面kill掉所有LOCALNO的所有进程&#xff0c;即&#xff1a;连接会话。 p…...

渲染101对Blender的支持与硬件配置详解

一、Blender版本与渲染器支持 渲染101全面支持 Blender全版本&#xff08;包括Blender 4.0及早期版本&#xff09;&#xff0c;并适配其内置的 Eevee、Cycles、Workbench 三大渲染器 。此外&#xff0c;平台还兼容 Aces、Realflow、Anima 等40插件&#xff0c;覆盖建模、动画…...

安卓burp抓包,bypass ssl pinning

好久好久没有发东西了。主要是懒。。。 这几天在搞apk渗透&#xff0c;遇到了burp无法抓包问题&#xff0c;觉得可以写下来。 问题描述 1. 一台安卓手机&#xff0c;装了面具&#xff0c;可以拿到root 2. 电脑上有burp&#xff0c;设置代理 3.手机和电脑连同一个网段&…...

植物大战僵尸杂交版v3.2.1最新版本(附下载链接)

B站游戏作者潜艇伟伟迷于12月21日更新了植物大战僵尸杂交版3.2.1版本&#xff01;&#xff01;&#xff01;&#xff0c;有b站账户的记得要给作者三连关注一下呀&#xff01; 不多废话下载链接放上&#xff1a; 夸克网盘链接&#xff1a;&#xff1a;https://pan.quark.cn/s/e5…...

【SQL】多表查询案例

&#x1f4e2;本章节主要学习使用SQL多表查询的案例,多表查询基础概念 请点击此处。 &#x1f384;数据准备 首先我们创建一个新的表也就是薪资等级表&#xff0c;其余两个表(员工表和薪资表)在多表查询章节中已经创建。然后我么根据这三个表完成下面的12个需求。 create tab…...

使用Python结合`stable-baselines3`库(包含PPO和TD3算法)以及`gym`库来实现分层强化学习的示例代码

以下是一个使用Python结合stable-baselines3库&#xff08;包含PPO和TD3算法&#xff09;以及gym库来实现分层强化学习的示例代码。该代码将环境中的动作元组分别提供给高层处理器PPO和低层处理器TD3进行训练&#xff0c;并实现单独训练和共同训练的功能。 代码实现 import g…...

解锁机器学习核心算法|神经网络:AI 领域的 “超级引擎”

一、神经网络&#xff1a;AI 领域的 “超级引擎” 在机器学习的庞大算法体系中&#xff0c;有十种算法被广泛认为是最具代表性和实用性的&#xff0c;它们犹如机器学习领域的 “十大神器”&#xff0c;各自发挥着独特的作用。这十大算法包括线性回归、逻辑回归、决策树、随机森…...

一周学会Flask3 Python Web开发-redirect重定向

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 前面我们学过渲染到模板页面&#xff0c;这个其实是一种内部的转发&#xff0c;浏览器地址栏地址没有变化。如果我们想重定向…...

FFmpeg 源码编译安装

参考&#xff1a; https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu Linux (Ubuntu) 下载 FFmpeg 源码&#xff0c;并将其解压&#xff0c;这里我将它放在 ~/ffmpeg_source 目录下&#xff1b; cd ~/ffmpeg_sources wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org…...

3.Docker常用命令

1.Docker启动类命令 1.启动Docker systemctl start docker 2.停止Docker systemctl stop docker 3.重启Docker systemctl restart docker 4.查看Docker状态 systemctl status docker 5.设置开机自启(执行此命令后每次Linux重启后将自启动Docker) systemctl enable do…...

vue3面试题进阶版

覆盖 Vue3 的核心知识点、高频考点及实战场景 一、基础与核心概念 MVVM 与 MVC 的区别 MVC&#xff1a;Model&#xff08;数据&#xff09;、View&#xff08;视图&#xff09;、Controller&#xff08;控制器&#xff09;&#xff0c;视图更新需手动操作 DOM。MVVM&#xff1…...

深入理解指针

例题1 int main() {int a[5][5];int(*p)[4];p a;printf("%p, %d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0; }由图知第二个打印的是-4 因为%p是直接将内存中的值当作地址打印 而-4在内存中存放的是其二进制的补码,打印以16进制形式…...