10.RabbitMQ集群
十、集群与高可用
RabbitMQ 的集群分两种模式,一种是默认集群模式,一种是镜像集群模式;
在RabbitMQ集群中所有的节点(一个节点就是一个RabbitMQ的broker服务器) 被归为两类:一类是磁盘节点,一类是内存节点;
磁盘节点会把集群的所有信息(比如交换机、绑定、队列等信息)持久化到磁盘中,而内存节点只会将这些信息保存到内存中,如果该节点宕机或重启,内存节点的数据会全部丢失,而磁盘节点的数据不会丢失;
1、默认集群模式
默认集群模式也叫 普通集群模式、或者 内置集群模式;
10.1.1、默认集群简介
(1)、元数据
队列元数据:队列名称和属性(是否可持久化,是否自动删除)
交换器元数据:交换器名称、类型和属性
绑定元数据:交换器和队列的绑定列表
vhost元数据:vhost内的相关属性,如安全属性等;
当用户访问其中任何一个RabbitMQ节点时,查询到的queue/user/exchange/vhost等信息都是相同的;
(2)、数据同步特点
RabbitMQ默认集群模式只会把交换机、队列、虚拟主机等元数据信息在各个节点同步,而具体队列中的消息内容不会在各个节点中同步,队列的具体信息数据只在队列的拥有者节点保存,其他节点只知道队列的元数据和指向该节点的指针,所以其他节点接收到不属于该节点队列的消息时会将该消息传递给该队列的拥有者节点上;
集群不复制队列内容和状态到所有节点原因
1)节省存储空间;
2)提升性能;
如果消息需要复制到集群中每个节点,网络开销不可避免,持久化消息还需要写磁盘,占用磁盘空间。

(3)、数据访问过程
如果有一个消息生产者或者消息消费者通过amqp-client的客户端连接到节点1进行消息的发送或接收,那么此时集群中的消息收发只与节点1相关,这个没有任何问题;
如果消息生产者所连接的是节点2或者节点3,此时队列1的完整数据不在该两个节点上,那么在发送消息过程中这两个节点主要起了一个路由转发作用,根据这两个节点上的元数据(也就是指向queue的owner node的指针)转发至节点1上,最终发送的消息还是会存储至节点1的队列1上;
同样,如果消息消费者所连接的节点2或者节点3,那这两个节点也会作为路由节点起到转发作用,将会从节点1的队列1中获取消息进行消费;
10.1.2、安装
1、安装三台RabbitMQ机器
安装过程参考前面
注意:这里先安装一台MQ,然后克隆两台就可以了
2、设置IP地址
启动并设置三台机器的IP
修改配置文件方式
略
图形界面方式



3、修改主机名
sudo hostnamectl set-hostname rabbit11
4、修改/etc/hosts 文件
首先需要配置一下hosts文件,因为RabbitMQ集群节点名称是读取hosts文件得到的;
注意三台机机器都需要配置
vim /etc/hosts
192.168.1.11 rabbit11
192.168.1.12 rabbit12
192.168.1.13 rabbit13

5、重启网络
三台机器均重启网络,使节点名生效
sudo systemctl restart NetworkManager
低版本CentOS使用如下命令
systemctl restart network
6、重新连接xshell
重启后三台机器的xshell均退出,然后再重新连接,这样才能刷新主机的名字
7、关闭防火墙
三台机器均需关闭
systemctl stop firewalld ##关闭防火墙
systemctl disable firewalld ##开机不启动防火墙
systemctl status firewalld ##查看防火墙状态

8、修改.erlang.cookie文件
三台机器 .erlang.cookie文件保持一致
由于是clone出的三台机器,所以肯定是一样的
-
如果使用解压缩方式安装的RabbitMQ,那么该文件会在 用户名目录下 , 也就是 {用户名}目录下,也就是 用户名目录下,也就是{用户名}/.erlang.cookie;

-
如果使用rpm安装包方式进行安装,那么这个文件会在/var/lib/rabbitmq目录下;
注意 .erlang.cookie的权限为400,目前已经是400
9、启动MQ
分别启动三台机器上的rabbitmq
rabbitmq-server -detached
10、查看集群状态
-
查看rabbitmq状态
rabbitmqctl status
-
查看集群状态
rabbitmqctl cluster_status
11、构建集群
-
加入节点1
在rabbitmq12机器上执行命令,让12的rabbitmq加入集群
注意:一定要先停止节点,将节点重置之后才能加入集群,否则数据同步会出现混乱
## 先停止rabbitmq rabbitmqctl stop_app ## 重置rabbitmq rabbitmqctl reset ## 节点加入集群:rabbit@rabbit11是主节点的节点名,在集群状态中可以查看到节点名称 rabbitmqctl join_cluster rabbit@rabbit11 --ram ## 启动节点 rabbitmqctl start_app–ram 参数表示让rabbitmq12成为一个内存节点,如果不带参数默认为disk磁盘节点;

-
添加节点2
在rabbit13节点上也执行同样的命令,使rabbit13节点也加入到集群中
## 先停止rabbitmq rabbitmqctl stop_app ## 重置rabbitmq rabbitmqctl reset ## 节点加入集群:rabbit@rabbit11是主节点的节点名,在集群状态中可以查看到节点名称 rabbitmqctl join_cluster rabbit@rabbit11 --ram ## 启动节点 rabbitmqctl start_app当然也可以让rabbit13作为一个磁盘节点
12、添加用户和权限
操作一个节点,添加用户和权限等
#列出用户
rabbitmqctl list_users
# 添加用户
rabbitmqctl add_user admin 123456
#查看权限
rabbitmqctl list_permissions
#设置权限
rabbitmqctl set_permissions admin ".*" ".*" ".*"
#设置角色
rabbitmqctl set_user_tags admin administrator

13、启动web控制台
启动web控制台插件
注意:三台机器都要启动,因为插件不属于元数据,因此需要分别启动
#进入插件目录
cd /usr/local/rabbitmq_server-4.0.7/plugins/
#启动web端插件
rabbitmq-plugins enable rabbitmq_management

14、创建虚拟主机
使用web浏览器添加一个虚拟主机:longdidi

15、再次查看集群状态
当执行完操作以后在浏览器访问web管控台来看看效果;
随便在哪个节点打开web管控台都能看到集群环境各节点的信息;
也可以使用"rabbitmqctl cluster_status"查看集群状态;

以上就是RabbitMQ默认集群模式(普通集群模式)的搭建;
16、验证集群
- 创建队列

-
创建交换机

-
绑定交换机与队列
-
进入交换机

-
绑定交换机与队列

-
-
发布消息

-
查看消息
在任意节点查看消息

-
停止主节点rabbit@rabbit11节点

-
再在其它节点查看消息

17、删除节点

10.1.3、节点原理
RabbitMQ底层是通过Erlang架构来实现的,所以rabbitmqctl会启动Erlang节点,并基于Erlang节点来使用Erlang系统连接RabbitMQ节点,在连接过程中需要正确的Erlang Cookie和节点名称,Erlang节点通过交换Erlang Cookie以获得认证;
2、镜像集群模式
10.2.1、镜像模式简介
镜像模式是基于默认集群模式加上一定的配置得来的;
在默认模式下的RabbitMQ集群,它会把所有节点的交换机、绑定、队列的元数据进行复制确保所有节点都有一份相同的元数据信息
但是队列数据分为两种
- 一种是队列的元数据信息(比如队列的最大容量,队列的名称等配置信息)
- 一种是队列里面的消息
镜像模式则是把所有的队列数据完全同步,包括元数据信息和消息数据信息,当然这对性能肯定会有一定影响,当对数据可靠性要求较高时,可以使用镜像模式;
10.2.2、镜像模式配置
实现镜像模式也非常简单,它是在普通集群模式基础之上搭建而成的
3.X版本设置
镜像队列配置语法:
rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]
-
rabbitmqctl set_policy:固定写法
-
-p Vhost: 可选参数,设置虚拟主机的名字(针对指定vhost下的queue进行设置)
-
Name: 设置策略的名称(自己取个名字就可以)
-
Pattern: queue的匹配模式(正则表达式);^表示所有的队列都是镜像队列
-
Definition:镜像定义(json格式),包括三个部分ha-mode、ha-params、ha-sync-mode
-
ha-mode
指明镜像队列的模式,有效值为 all/exactly/nodes
all:表示在集群中所有的节点上进行镜像 exactly:表示在指定个数的节点上进行镜像,节点的个数由ha-params指定 nodes:表示在指定的节点上进行镜像,节点名称通过ha-params指定 -
ha-params
ha-mode模式需要用到的参数
-
ha-sync-mode
队列中消息的同步方式,有效值为automatic(自动向master同步数据)和manual(手动向master同步数据)
-
-
priority:可选参数,指的是policy策略的优先级;
在默认集群模式的基础上执行上面这个命令就可以把一个默认的集群模式变成镜像集群模式
比如想配置所有名字开头为policy_的队列进行镜像,镜像数量为2,那么命令如下(在任意节点执行如下命令):
rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]
rabbitmqctl set_policy -p longdidi my_policy "^policy_" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
(1)、同步所有数据
所有节点、所有虚拟主机、所有队列 都进行镜像
如果要在所有节点所有队列上进行镜像则在任意节点执行如下命令
语法:rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]
rabbitmqctl set_policy my-all "^" '{"ha-mode":"all"}'
(2)、同步指定数据
针对某个虚拟主机进行镜像
语法:rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority]
rabbitmqctl set_policy -p longdidi my-all "^" '{"ha-mode": "exactly", "ha-params": 2, "ha-sync-mode": "automatic"}'
在默认集群模式的基础上执行上面这个命令就可以把一个默认的集群模式变成镜像集群模式
4.X版本设置

3、SpringBoot集成集群
重点连接配置
spring:rabbitmq:# 连接单台rabbitmq 服务器的地址# host: 192.168.1.101# 连接单台rabbitmq 服务器的端口# port: 5672username: adminpassword: 123456virtual-host: longdidipublisher-confirm-type: correlated # 开启生产者的确认模式,设置关联模式publisher-returns: true #开启return模式# 开启消费者手动确认listener:simple:acknowledge-mode: manualaddresses: 192.168.1.11:5672,192.168.1.12:5672,192.1.13:5672
测试模块:rabbitmq-10-cluster-01
引入依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies>
配置MQ
server:port: 8080spring:application:name: cluster-learn01rabbitmq:# 连接单台rabbitmq 服务器的地址# host: 192.168.1.101# 连接单台rabbitmq 服务器的端口# port: 5672username: adminpassword: 123456virtual-host: longdidipublisher-confirm-type: correlated # 开启生产者的确认模式,设置关联模式publisher-returns: true #开启return模式# 开启消费者手动确认listener:simple:acknowledge-mode: manualaddresses: 192.168.1.11:5672,192.168.1.12:5672,192.1.13:5672data:redis:host: 192.168.1.4port: 6379#password: 123456database: 0 # 0号数据库
定义MQ队列
package com.longdidi.config;import com.longdidi.constants.RabbitMQConstant;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RabbitConfig {/*** 正常交换机* 使用durable()方法设置持久化** @return*/@Beanpublic DirectExchange normalExchange() {return ExchangeBuilder.directExchange(RabbitMQConstant.EXCHANGE_NAME).durable(true).build();}/*** 正常队列* durable()方法就是持久化** @return*/@Beanpublic Queue normalQueue() {return QueueBuilder.durable(RabbitMQConstant.QUEUE_NAME1).build();}/*** 正常交换机和正常队列绑定** @param normalExchange* @param normalQueue* @return*/@Beanpublic Binding bindingNormal(DirectExchange normalExchange, Queue normalQueue) {return BindingBuilder.bind(normalQueue).to(normalExchange).with(RabbitMQConstant.ROUTING_NAME1);}}
生产者
package com.longdidi.service;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.longdidi.constants.RabbitMQConstant;
import com.longdidi.vo.Orders;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.Date;@Service
@Slf4j
public class SendMessageService {@Resourceprivate RabbitTemplate rabbitTemplate;//这个对象可以进行序列化和反序列化(json格式)@Resourceprivate ObjectMapper objectMapper;/*** 构造方法执行后自动执行*/@PostConstructpublic void init() {//开启生产者的确定模式rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {if (!ack) {log.error("消息没有到达交换机,原因为:{}", cause);//TODO 重发消息或者记录错误日志}});rabbitTemplate.setReturnsCallback(returnedMessage -> {log.error("消息没有从交换机正确的投递(路由)到队列,原因为:{}", returnedMessage.getReplyText());//TODO 记录错误日志,给程序员发短信或者或者邮件});}public void sendMsg() throws JsonProcessingException {{//创建订单Orders orders1 = Orders.builder().orderId("order_12345").orderName("买的手机").orderMoney(new BigDecimal(2356)).orderTime(new Date()).build();//转成jsonString strOrders1 = objectMapper.writeValueAsString(orders1);MessageProperties messageProperties = new MessageProperties();//设置单条消息的持久化,默认就是持久化messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);Message message = MessageBuilder.withBody(strOrders1.getBytes()).andProperties(messageProperties).build();rabbitTemplate.convertAndSend(RabbitMQConstant.EXCHANGE_NAME, RabbitMQConstant.ROUTING_NAME1, message);}{Orders orders2 = Orders.builder().orderId("order_12345").orderName("买的手机").orderMoney(new BigDecimal(2356)).orderTime(new Date()).build();String strOrders2 = objectMapper.writeValueAsString(orders2);MessageProperties messageProperties = new MessageProperties();//设置单条消息的持久化,默认就是持久化messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);Message message = MessageBuilder.withBody(strOrders2.getBytes()).andProperties(messageProperties).build();rabbitTemplate.convertAndSend(RabbitMQConstant.EXCHANGE_NAME, RabbitMQConstant.ROUTING_NAME1, message);}log.info("消息发送完毕,发送时间为:{}", new Date());}
}
消费者
package com.longdidi.service;import com.fasterxml.jackson.databind.ObjectMapper;
import com.longdidi.constants.RabbitMQConstant;
import com.longdidi.vo.Orders;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.io.IOException;import com.rabbitmq.client.Channel;@Component
@Slf4j
public class ReceiveMessageService {@Resourceprivate ObjectMapper objectMapper;@Resourceprivate StringRedisTemplate stringRedisTemplate;@RabbitListener(queues = {RabbitMQConstant.QUEUE_NAME1})public void receiveMsg(Message message, Channel channel) throws IOException {//获取消息的唯一标识long deliveryTag = message.getMessageProperties().getDeliveryTag();//使用objectmapper把字节数组反序列化成对象Orders orders = objectMapper.readValue(message.getBody(), Orders.class);try {log.info("接收到的消息为:{}", orders.toString());//如果不存在就在redis中存储Boolean setResult = stringRedisTemplate.opsForValue().setIfAbsent("idempotent:" + orders.getOrderId(), orders.getOrderId());if (setResult) {// TODO 向数据库插入订单等log.info("向数据库插入订单");}//手动确认channel.basicAck(deliveryTag, false);} catch (Exception e) {log.error("消息处理出现问题");try {channel.basicNack(deliveryTag, false, true);} catch (IOException ex) {throw new RuntimeException(ex);}throw new RuntimeException(e);}}
}
定义常量
package com.longdidi.constants;public class RabbitMQConstant {// 正常交换机public static final String EXCHANGE_NAME = "exchange.idempotent.normal.1";// 队列public static final String QUEUE_NAME1 = "queue.idempotent.normal.1";// 路由keypublic static final String ROUTING_NAME1 = "key.idempotent.normal.1";
}
定义实体类
package com.longdidi.vo;import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Orders implements Serializable {private String orderId;private String orderName;private BigDecimal orderMoney;private Date orderTime; //下单时间
}
发送消息
package com.longdidi;import com.longdidi.service.SendMessageService;
import jakarta.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Rabbitmq10Cluster01Application implements ApplicationRunner {public static void main(String[] args) {SpringApplication.run(Rabbitmq10Cluster01Application.class, args);}@Resourceprivate SendMessageService sendMessageService;/*** 程序一启动就会运行该方法** @param args* @throws Exception*/@Overridepublic void run(ApplicationArguments args) throws Exception {sendMessageService.sendMsg();}
}
测试

相关文章:
10.RabbitMQ集群
十、集群与高可用 RabbitMQ 的集群分两种模式,一种是默认集群模式,一种是镜像集群模式; 在RabbitMQ集群中所有的节点(一个节点就是一个RabbitMQ的broker服务器) 被归为两类:一类是磁盘节点,一类是内存节点; 磁盘节点会把集群的所有信息(比如交换机、绑…...
Web网页开发——水果忍者
1.介绍 复刻经典小游戏——水果忍者 2.预览 3.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…...
信息安全访问控制、抗攻击技术、安全体系和评估(高软42)
系列文章目录 信息安全访问控制、抗攻击技术、安全体系和评估 文章目录 系列文章目录前言一、信息安全技术1.访问控制2.抗攻击技术 二、欺骗技术1.ARP欺骗2.DNS欺骗3.IP欺骗 三、抗攻击技术1.端口扫描2.强化TCP/IP堆栈 四、保证体系和评估1.保证体系2.安全风险管理 五、真题在…...
【算法】009、单双链表反转
【算法】009、单双链表反转 文章目录 一、单链表反转1.1 实现思路1.2 多语言解法 二、双链表反转2.1 实现思路2.2 多语言解法 一、单链表反转 1.1 实现思路 维护 pre 变量。 从前向后遍历 head,首先记录 next head.next,其次反转指针使 head.next pr…...
物联网设备接入系统后如何查看硬件实时数据?
要在软件中实时查看硬件设备的信息,通常需要结合前后端技术来实现。以下是设计思路和实现步骤: 1. 系统架构设计 实时查看硬件设备信息的系统通常采用以下架构: 数据采集层: 硬件设备通过传感器采集数据,发送到InfluxDB。数据存…...
【Linux系统编程】初识系统编程
目录 一、什么是系统编程1. 系统编程的定义2. 系统编程的特点3. 系统编程的应用领域4. 系统编程的核心概念5. 系统编程的工具和技术 二、操作系统四大基本功能1. 进程管理(Process Management)2. 内存管理(Memory Management)3. 文…...
解决stylelint对deep报错
报错如图 在.stylelintrc.json的rules中配置 "selector-pseudo-class-no-unknown": [true,{"ignorePseudoClasses": ["deep"]} ]...
React基础之useInperativehandlle
通过ref调用子组件内部的focus方法来实现聚焦 与forwardRef类似,但是forwardRef是通过暴露整个Ref来实现,而useInperativehandle是通过对外暴露一个方法来实现的 import { forwardRef, useImperativeHandle, useRef, useState } from "react";…...
使用joblib 多线程/多进程
文章目录 1. Joblib 并行计算的两种模式多进程(Multiprocessing,适用于 CPU 密集型任务)多线程(Multithreading,适用于 I/O 密集型任务)2. Joblib 的基本用法3. Joblib 多进程示例(适用于 CPU 密集型任务)示例:计算平方4. Joblib 多线程示例(适用于 I/O 密集型任务)…...
⭐算法OJ⭐N-皇后问题 II【回溯剪枝】(C++实现)N-Queens II
⭐算法OJ⭐N-皇后问题【回溯剪枝】(C实现)N-Queens 问题描述 The n-queens puzzle is the problem of placing n n n queens on an n n n \times n nn chessboard such that no two queens attack each other. Given an integer n, return the num…...
【数据结构初阶】---堆的实现、堆排序以及文件中的TopK问题
1.树的概念及结构 1.1树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 有一个特殊的结点&…...
ubuntu20系统下conda虚拟环境下安装文件存储位置
在 Conda 虚拟环境中执行 pip install 安装软件后,安装的文件会存储在该虚拟环境专属的 site-packages 目录中。具体路径取决于你激活的 Conda 环境路径。以下是定位步骤: 1. 确认 Conda 虚拟环境的安装路径 查看所有环境: conda info --env…...
鸿蒙开发:RelativeContainer 相对布局详解【全套华为认证学习资料分享(考试大纲、培训教材、实验手册等等)】
前言 在最新版本的 DevEco Studio 中,官方在创建新项目时,默认使用 RelativeContainer 组件作为根布局。这足以证明 RelativeContainer 的重要性。相比其他容器组件,它极大地简化了复杂 UI 布局中的元素对齐问题。 例如,在没有 R…...
基于SpringBoot实现旅游酒店平台功能一
一、前言介绍: 1.1 项目摘要 随着社会的快速发展和人民生活水平的不断提高,旅游已经成为人们休闲娱乐的重要方式之一。人们越来越注重生活的品质和精神文化的追求,旅游需求呈现出爆发式增长。这种增长不仅体现在旅游人数的增加上࿰…...
HttpServletRequest 和 HttpServletResponse 区别和作用
一、核心作用对比 对象HttpServletRequest(请求对象)HttpServletResponse(响应对象)本质客户端发给服务器的 HTTP 请求信息(输入)服务器返回客户端的 HTTP 响应信息(输出)生命周期一…...
树莓派学习(一)——3B+环境配置与多用户管理及编程实践
树莓派学习(一)——3B环境配置与多用户管理及编程实践 一、实验目的 掌握树莓派3B无显示器安装与配置方法。学习Linux系统下多用户账号的创建与管理。熟悉在树莓派上使用C语言和Python3编写简单程序的方法。 二、实验环境 硬件设备:树莓派…...
Mysql安装方式
方式一:安装包安装 下载安装包 官网直接下载:https://dev.mysql.com/downloads/ 安装配置 2.1、双击刚刚下载好的msi文件,开始安装MySQL。 2.2、选择自定义模式Custom安装 2.3、点击选择自己电脑对应的mysql安装目录 2.5、继续点击下一步&…...
Vue3实战学习(Vue3的基础语法学习与使用(超详细))(3)
目录 (1)Vue3工程环境准备、项目基础脚手架搭建详细教程。(博客链接) (2)Vue3的基础语法学习与使用。 (1)"{{}}"绑定数据。 <1>ref()函数定义变量——绑定数据。 <2>reactive({...})…...
使用websocket,注入依赖service的bean为null
问题:依赖注入失败,service获取不到,提示null 这是参考代码 package com.shier.ws;import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.google.gson.Gson; import com.s…...
批量在 Word 的指定位置插入页,如插入封面、末尾插入页面
我们经常会碰到需要在 Word 文档中插入新的页面的需求,比如在 Word 文档末尾插入一个广告页、给 Word 文档插入一个说明封面,在 Word 文档的中间位置插入新的页面等等。相信这个操作对于大部分小伙伴来说都不难,难的是同时给多个 Word 文档插…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
