RocketMQ相关概念与使用入门详解

文章目录

  • RocketMQ 相关概念
    • 消息模型
      • MQ 的简单消息模型
      • RocketMQ 的复杂消息模型
    • RocketMQ 中消息相关概念
      • 消息(Message)
      • 主题(Topic)
      • Tags
      • 队列
      • 消息标识
    • RocketMQ 中的物理对象
      • NameServer
      • Broker
      • Producer
      • Consumer
  • NameServer 与 Broker 在 Windows 本地启动示例:
    • 本地启动 NameServer
    • 本地启动 Broker
    • tools 工具测试消息消费
    • 可视化工具 rocketmq-dashboard
    • 生产者和消费者Java代码示例

RocketMQ 相关概念

消息模型

MQ 的简单消息模型

MQ 是一种提供消息队列服务的中间件(消息中间件),提供了消息生产、存储、消费全过程API的软件系统。消息的发送者(称为发布者、生产者、Producer)会将消息直接发送给特定的接收者(称为订阅者、消费者、Comsumer)。MQ 的基础消息模型就是一个发布/订阅(Pub/Sub)模型。

一个简单的 Pub/Sub 概念模型:包括生产者 (Producer)消费者 (Consumer),中间进行基于**消息主题(Topic)**的消息传送。外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RocketMQ 的复杂消息模型

在实际应用中的消息模型的结构会更复杂。例如为了支持高并发和水平扩展,中间的消息主题需要进行分区,同一个Topic会有多个生产者,同一个信息会有多个消费者,消费者之间要进行负载均衡等。

下图是 RocketMQ 支持的一种扩展后的消息模型,包括两个生产者两个消息Topic,以及两组消费者 Comsumer

  • 为了消息写入能力的水平扩展,RocketMQ 对 Topic进行了分区,这种操作后的分区被称为队列(MessageQueue)。
  • 为了消费能力的水平扩展,引入了 ConsumerGroup 的概念。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RocketMQ 中消息相关概念

消息(Message)

  • 消息是最小数据传输单元,每条消息必须属于一个主题。

  • RocketMQ 中的消息源码:org.apache.rocketmq.common.message.Message

    public class Message implements Serializable {
        private static final long serialVersionUID = 8445773977080406428L;
    
        private String topic;
        private int flag;
        private Map<String, String> properties;
        private byte[] body;
        // .......
        public Message(String topic, String tags, String keys, int flag, byte[] body, boolean waitStoreMsgOK) {
            this.topic = topic;
            this.flag = flag;
            this.body = body;
    
            if (tags != null && tags.length() > 0)
                this.setTags(tags);
    
            if (keys != null && keys.length() > 0)
                this.setKeys(keys);
    
            this.setWaitStoreMsgOK(waitStoreMsgOK);
        }
        // ......
    }
    

    在 RocketMq 中,Message(消息)包括 Topic(主题)、body(消息体)、properties、flag。可以看出在构造消息时,就需要指定消息所属的 Topic。

    1. topic:表示消息的主题(Topic),用于标识消息所属的主题分类。消费者可以根据主题来订阅消息。
    2. body:表示消息的内容(Body),它是一个字节数组(byte[])类型,用于存储消息的实际内容数据。
    3. properties:表示消息的属性(Properties),它是一个键值对(Map<String, String>)类型的对象,用于存储消息的自定义属性信息。常用的 tags、keys 属性键值对就保存在 Properties 中
      1. tags:表示消息的标签(Tags),用于对消息进行更细粒度的分类。消费者可以根据标签来过滤和选择特定类型的消息。
      2. keys:表示消息的关键字(Keys),用于标识消息的唯一性。可以根据关键字来进行消息的检索和查询。
    4. flag:表示消息的标志(Flag),用于标识一些特殊的消息属性。

主题(Topic)

  • 主题是消息传输和存储的顶层容器,用于标识同一类业务逻辑的消息。但主题是一个逻辑概念,并不是实际的消息容器。是 Rocketmq 进行消息订阅的基本逻辑单位。

    • 定义数据的分类隔离:通过主题实现逻辑上的存储隔离性和订阅隔离性。

    • 定义数据的身份和权限:消息本身是匿名无身份的,同一分类的消息使用相同的主题来做身份识别和权限管理。

  • 主题内部由多个队列组成,消息的存储和水平扩展能力最终是由队列实现的;并且针对主题的所有约束和属性设置,最终也是通过主题内部的队列来实现。

Tags

  • Topic 与 Tag 都是业务上用来归类的逻辑标识,区别在于 Topic 是一级分类,而 Tag 可以理解为二级分类。使用 Tag 可以实现对 Topic 中的消息进行过滤。

    • Topic:消息主题,通过 Topic 对不同的业务消息进行分类。

    • Tag:消息标签,用来进一步区分某个 Topic 下的消息分类,消息从生产者发出即带上的属性。

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

队列

  • 队列是中消息存储和传输的实际物理容器,是消息的最小存储单元。
  • 一个 Topic 可能有多个队列,并且可以分布在不同的 Broker 上。
  • 一般来说一条消息,如果没有重复发送(比如因为服务端没有响应而进行重试),则只会存在在 Topic 的其中一个队列中。

消息标识

Rocketmq 中的每个消息拥有唯一的 MessageId,还可以携带具有业务标识的 Keys,以便对消息的查询。对于 MessageId 有两个,在生产者发送消息时会自动生成一个 MessageId(msgId),当消息到达 Broke 后,Broke 也会自动生成一个 MessageId(offsetMsgId)。Key、msgId 和 offsetMsgId 都称为消息标识。

  • msgId:由 producer 端生成,生成规则为:

    produceIp + 进行pid + MessageClientIDSetter 类的 classLoader 的 hashcode + 当前时间 + AutomicInteger 自增计数器。

  • offsetMsgId:由 broke 端生成,生成规则为:brokerIp + 队列 Queue 中的偏移量(offset)。

  • keys:由用户指定与业务相关的唯一标识。

RocketMQ 中的物理对象

NameServer

NameServer 是一个简单的 Topic 路由注册中心,支持 Topic、Broker 的动态注册与发现。

主要包括两个功能:

  • Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;
  • 路由信息管理,每个NameServer将保存关于 Broker 集群的整个路由信息和用于客户端查询的队列信息。Producer和Consumer通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。

NameServer通常会有多个实例部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,客户端仍然可以向其它NameServer获取路由信息。

Broker

Broker主要负责消息的存储、投递和查询以及服务高可用保证。

NameServer几乎无状态节点,因此可集群部署,节点之间无任何信息同步。Broker部署相对复杂。

在 Master-Slave 架构中,Broker 分为 Master 与 Slave。一个Master可以对应多个Slave,但是一个Slave只能对应一个Master。Master 与 Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。

部署模型

  • 每个 BrokerNameServer 集群中的所有节点建立长连接,定时注册 Topic 信息到所有 NameServer。
  • ProducerNameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取Topic路由信息,并向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。Producer 完全无状态。
  • ConsumerNameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Master、Slave 建立长连接,且定时向 Master、Slave发送心跳。Consumer 既可以从 Master 订阅消息,也可以从Slave订阅消息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Producer

RocketMq 中提供一个用于发送消息的核心组件。

生产者组:在 RocketMQ 中,生产者组(Producer Group)是一组具有相同业务逻辑的生产者实例的集合。它们共享相同的身份和配置,并且协同工作以实现高可用和负载均衡。

  • 负载均衡:在同一生产者组下,消息会均匀地分布到不同的生产者实例上,从而实现负载均衡,生产者组负载均衡是通过 Name Server 来协调的。
  • 故障转移:如果生产者组内的某个实例发生故障或停止工作,RocketMQ 会自动将该实例的消息发送任务转移到其他正常工作的实例上,以确保消息发送的可靠性和持续性。这种故障转移机制可以提高系统的可用性和容错性。

启动生产者最基本流程

  1. 配置并初始化:在使用生产者(如:DefaultMQProducer) 之前,需要设置生产者的组名(Group Name)和名称服务器的地址(Name Server Address)。

  2. 启动:调用 start() 方法,可以启动生产者并将其连接到名称服务器。

  3. 之后便可以使用生产者发送消息了。

    public class ProducerExample {
        public static void main(String[] args) throws Exception {
            // 基本配置
            DefaultMQProducer producer = new DefaultMQProducer("your_producer_group");
            producer.setNamesrvAddr("your_nameserver_address");
            // 启动
            producer.start();
            // ......
        }
    }
    

RocketMq 消息发送的三种方式

  • 可靠同步发送,一个消息发送后收到 Broker 响应再发送下一个消息,使用 send(Message) 方法。
  • 可靠异步发送,一个消息发送后不需要收到 Broker 响应便可再发送下一个消息,通过回调函数处理消息发送结果,使用 send(Message, SendCallback) 方法。
  • 单向发送,一个消息单向发送到 Broker,不需要等待 Broker 服务器的响应,使用 sendOneway(Message) 方法。

Consumer

消费者是 Apache RocketMQ 中用来接收并处理消息的运行实体。

消费者分组(ConsumerGroup)是一组具有相同业务逻辑的消费者者实例的集合。通过消费者分组内初始化多个消费者实现消费性能的水平扩展以及高可用容灾,同一分组下的多个消费者将按照分组内统一的消费行为和负载均衡策略消费消息。

RocketMq 中有两种消费模式

  1. 集群(Clustering)模式:在集群模式下,多个消费者可以组成一个消费者组(Consumer Group)。每个消费者组内的消费者协同消费消息,每个消息只被消费者组内的一个消费者消费。可以通过扩缩消费者数量,来提升或降低消费能力。
  2. 广播(Broadcasting)模式:在广播模式下,消息推送给消费组所有的消费者,每个消费者都会独立消费消息。扩缩消费者数量无法提升或降低消费能力。

RocketMq 中有两种消费方式(消费者模型)

  1. 推模式:主动推送消息给消费者。默认的消息者实现类为 DefaultMQPushConsumer。
  2. 拉模式:消费者主动拉取消息。默认的消息者实现类为 DefaultMQPullConsumer。

启动消费者最基本流程

  1. 配置并初始化:在使用消费者(如:DefaultMQPushConsumer) 之前,需要设置消费者的组名(Group Name)和名称服务器的地址(Name Server Address)。这里是启动消费者最基本配置,但是启动消费者是为了订阅消息消费,所以还需要配置一些消费消息的信息。

    • 配置要订阅消息的主题(Topic);
    • 配置消费者消费模型(不指定默认为集群模式 CLUSTERING);
    • 配置并注册消息监听器(MessageListenerConcurrentlyMessageListenerOrderly),并在监听器中实现消息消费的处理逻辑。
  2. 启动:调用 start() 方法,可以启动消费者并将其连接到名称服务器。

  3. 之后便可以使用消费者者监听消息消费了。

    public class ConsumerExample {
        public static void main(String[] args) throws Exception {
            // 基本配置
            DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("your_consumer_group");
            consumer.setNamesrvAddr("your_nameserver_address");
    
            // 设置消费起始位置为最新位置
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
            // 设置订阅主题和标签
            consumer.subscribe("your_topic", "your_tag");
            // 注册消息监听器
            consumer.registerMessageListener((MessageListenerConcurrently) (msgs, context) -> {
                for (MessageExt msg : msgs) {
                    // 处理接收到的消息
                    System.out.println("Received message: " + new String(msg.getBody()));
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            });
            // 启动
            consumer.start();
            // ......
        }
    }
    

NameServer 与 Broker 在 Windows 本地启动示例:

官网下载 RocketMq 二进制包压缩包并解压:https://rocketmq.apache.org/download/,这里下载 4.9.6 版本。

这里提供已经下载好的源码和二进制压缩包,请关注微信公众号【Qin的学习营地】,回复【RocketMq安装包】。

配置环境变量

  1. 编辑环境变量:ROCKETMQ_HOME = F:\rocketmq\rocketmq-4.9.6
  2. 添加到环境路径下:Path = %ROCKETMQ_HOME%\bin

本地启动 NameServer

进入 cmd 命令窗口,启动命令:

start mqnamesrv.cmd

如下代表启动成功:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

本地启动 Broker

进入 cmd 命令窗口,启动命令:

mqbroker.cmd -n 127.0.0.1:9876 autoCreateTopicEnable=true
  • -n 参数指定 NameServer 的地址和端口号,NameServer默认启动端口是 9876。
  • autoCreateTopicEnable=true 表示自动创建主题。

如下代表启动成功:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

tools 工具测试消息消费

在使用测试工具测试之前需要配置环境变量

  1. 编辑环境变量:NAMESRV_ADDR = localhost:9876 或 NAMESRV_ADDR = 127.0.0.1:9876
  2. 添加到环境路径下:Path = %NAMESRV_ADDR%\bin

启动消费者:

进入命令行执行以下命令:

start tools.cmd org.apache.rocketmq.example.quickstart.Consumer

如下代表启动成功:等待消费消息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

启动发送者:

进入命令行执行以下命令:

start tools.cmd org.apache.rocketmq.example.quickstart.Producer

可以看到发送的消息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同时也可以看到消费者消费消息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可视化工具 rocketmq-dashboard

可视化源码下载:https://github.com/apache/rocketmq-dashboard,这里下载的是最新版的控制台,支持 RocketMq 5.x 版本。

对于 RocketMq 4.x 版本存在不兼容场景,需要去提交历史中找旧版本的控制台,如:https://github.com/apache/rocketmq-externals/tree/d8f1cb444c5ed4455d5d7f62e636f3fe9a8c8824,找 rocketmq-externals 工程下的 rocketmq-console 模块。

这里提供已经下载好的旧版本控制台(支持 RocketMq 4.x 版本)和新版本控制台(支持 RocketMq 5.x 版本)压缩包,请关注微信公众号【Qin的学习营地】,回复【RocketMq控制台】。

Maven spring-boot run 启动:

mvn spring-boot:run

或 Maven build and run 编译运行:

mvn clean package -Dmaven.test.skip=true
java -jar target/rocketmq-dashboard-1.0.1-SNAPSHOT.jar

或 将源码在 IDEA 打开,本地运行。

启动后输入便看进入 dashboard 界面: http://127.0.0.1:8080,dashboard 默认应用程序端口为 8080。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

生产者和消费者Java代码示例

引入依赖包

<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client</artifactId>
    <version>4.9.6</version>
</dependency>

消费者代码示例

public class ConsumerService {

    private static final String TOPIC_TEST = "topic_test";
    private static final String TAGS_TEST = "tags_test";

    /**
     * 1、配置消费者分组
     * 2、配置 NamesrvAddr 地址
     * 3、配置Topic、Tags路由信息
     * 4、注册监听器
     * 5、启动消费者
     */
    public static void main(String[] args)  throws MQClientException {
        DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer();
        pushConsumer.setConsumerGroup("TEST_CONSUMER_GROUP");
        pushConsumer.setNamesrvAddr("127.0.0.1:9876");
        pushConsumer.subscribe(TOPIC_TEST, TAGS_TEST);
        pushConsumer.registerMessageListener(new MessageListenerConcurrently() {
            @Override
            public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                for (MessageExt messageExt : list) {
                    System.out.println(messageExt);
                }
                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
            }
        });
        pushConsumer.start();
    }

}

生产者代码示例

public class ProducerService {
    
    private static final String TOPIC_TEST = "topic_test";
    private static final String TAGS_TEST = "tags_test";
    private static final String KEYS_TEST = "keys_test";

    public static void main(String[] args) throws Exception {
        /**
         * 1、配置生产者者分组
         * 2、配置 NamesrvAddr 地址
         * 3、启动生产者
         * 4、发送消息
         * 5、关闭生产者
         */
        DefaultMQProducer mqProducer = new DefaultMQProducer();
        mqProducer.setProducerGroup("TEST_PRODUCER_GROUP");
        mqProducer.setNamesrvAddr("127.0.0.1:9876");
        mqProducer.start();
        SendResult sendResult = mqProducer.send(new Message(TOPIC_TEST, TAGS_TEST, KEYS_TEST, "body test".getBytes()));
        System.out.println(sendResult);
        mqProducer.shutdown();
    }
}

运行上述代码,再启动可视化控制台观察

可以看到消费者相关信息,但在点击消费详情时,右上角报异常:

org.apache.rocketmq.client.exception.MQBrokerException: CODE: 3 DESC: request type 351 not supported For more information, please visit the url, https://rocketmq.apache.org/docs

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

点击消息编辑项,可以查看消息消费情况。在这里我的 idea 消费者控制台打印出消息信息,也就是消息已经消费了,但是下面的 trackType 还是为 UNKNOWN,不是 CONSUMED 已消费状态。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以上出现的问题主要是 RocketMq 和控制台版本不兼容导致的,这里使用的 RocketMq 是 4.9.6 版本,而这里使用的控制台是新版本,支持 RocketMq 5.x 以上的版本,可以在控制台源码的 pom.xml 中看引入 RocketMq 的版本为 5.1.0。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以这里需要使用旧版本的控制台,前面提供了下载地址和已经下载好的压缩包。下载旧版本控制台,可以看到这里下载的旧版本控制台的 pom.xml 中引入 RocketMq 的版本为 4.9.0。启动控制台(配置文件中记得配置 namesrvAddr),上面的问题就能解决了,消息消费后,trackType 为 CONSUMED 已消费状态。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

​ RocketMQ 相关概念
与使用入门

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

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

相关文章

MATLAB 和 Simulink 官方文档下载地址

MATLAB 官方文档中文版下载网址&#xff1a; https://ww2.mathworks.cn/help/pdf_doc/matlab/index.html 如图&#xff1a; MATLAB 官方文档英文版下载网址&#xff1a; https://ww2.mathworks.cn/help/pdf_doc/matlab/index.html?langen 如图&#xff1a; Simulink 官…

Xilinx Zynq-7000系列FPGA实现视频拼接显示,提供两套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐FPGA图像处理方案FPGA视频拼接叠加融合方案推荐 3、设计思路详解Video Mixer介绍 4、工程代码1&#xff1a;2路视频拼接 HDMI 输出PL 端 FPGA 逻辑设计PS 端 SDK 软件设计 5、工程代码2&#xff1a;4路视频拼接 HDMI 输出PL 端 FPGA 逻辑设…

Kotlin学习——kt入门合集博客 kt里的委派模式Delegation kt里的特性

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

OpenCV检测圆形东西是否存在缺口?

文章目录 前言一、试过的方法二、最终使用的方法1.先极坐标变换2.计算斜率 总结 前言 想了挺久&#xff0c;一直没解决这个问题。后面勉强解决了。 一、试过的方法 1.想用圆度来解决&#xff0c;后来发现圆度差值很小&#xff0c;完整的圆圆度0.89&#xff0c;然后有缺角的圆圆…

emu8086汇编语言输出“Hello World!“

输出Hello world 首先我们尝试用C语言来实现该功能&#xff1a; #include <stdio.h>int main() {printf("Hello World!"); // 输出“Hello World!”return 0; } 将这行代码翻译成汇编语言... ; DS 数据段定义 DATA SEGMENTZIFU DB Hello World!,$ ;字符串…

LeetCode198.打家劫舍

打家劫舍和背包问题一样是一道非常经典的动态规划问题&#xff0c;只要做过几道动态规划的题&#xff0c;这道题简直就非常容易做出来。我应该花了10来分钟左右就写出来了&#xff0c;动态规划问题最重要的就是建立状态转移方程&#xff0c;就是说如何从上一个状态转移到下一个…

CentOS 7 安装 Weblogic 14 版本

安装JDK程序 注意&#xff1a;安装weblogic前&#xff0c;先安装JDK&#xff01;&#xff08;要求jdk(1.7以上)&#xff09;&#xff1a; 一、创建用户组weblogic及用户weblogic groupadd weblogic useradd -g weblogic weblogic二、将下载好的jdk及weblogic上传至/home/webl…

重量级消息,微软将ThreadX RTOS全家桶贡献给Eclipse基金会,免费供大家商用,宽松的MIT授权方式

从明年第1季度开始&#xff0c;任何人&#xff0c;任何厂家的芯片都可以免费商用&#xff0c;MIT授权就这点好。 贡献出来后&#xff0c;多方可以一起努力开发&#xff0c;当前首批兴趣小组AMD, Cypherbridge, Microsoft, NXP, PX5, Renesas, ST Microelectronics, Silicon Lab…

速记:一个TL431应用电路

一个TL431应用电路 仿真结果 输出电压为&#xff1a;5V 负载电阻为&#xff1a; R4 50Ω 如果负载R4加重 显然负载加重&#xff0c;输出就达不到5V. 三极管T1 的作用 没有三极管的情况 同样是保持负载 R 50Ω 可见三极管的作用就是用来放大电流

第十九章 解读利用pytorch可视化特征图以及卷积核参数(工具)

介绍一种可视化feaature maps以及kernel weights的方法 推荐可视化工具TensorBoard&#xff1a;可以查看整个计算图的数据流向&#xff0c;保存再训练过程中的损失信息&#xff0c;准确率信息等 学习视频&#xff1a; 使用pytorch查看中间层特征矩阵以及卷积核参数_哔哩哔哩…

rdf-file:分布式环境下的文件处理

一&#xff1a;数据量大了以后&#xff0c;单机解析或者生成文件的效率就很低&#xff0c;需要通过集群处理 机构过来的文件&#xff1a;我们先对文件进行分片&#xff0c;在利用集群集群处理分片文件。给机构文件&#xff1a;分库分表数据&#xff0c;每个分表生成一个分片文…

基于SSM的企业订单跟踪管理系统(有报告)。Javaee项目

演示视频&#xff1a; 基于SSM的企业订单跟踪管理系统&#xff08;有报告&#xff09;。Javaee项目 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring SpringM…

只狼 资源分享

版本介绍 v1.06版|容量15GB|官方简体中文|支持键盘.鼠标.手柄|赠官方原声4首BGM|赠多项修改器|赠一周目全义手忍具强化通关存档|2020年01月15号更新 只狼中文设置&#xff1a; https://jingyan.baidu.com/article/cb5d6105bc8556005d2fe048.html 只狼键盘对应按键&#xff1…

vite-性能优化-构建优化-cnd加速优化

CDN 加速优化 - 感觉用不大到 主要作用 &#xff1a; 将引入的依赖&#xff0c;打包部署后&#xff0c;在用户访问的时候&#xff0c; 通过网络CDN的方式进行加载&#xff0c;而非直接从你自己的服务器上加载。优点 &#xff1a; 1、直接降低了你自己的打包的体积&#xff0c…

excel表中慎用合并单元格,多用跨列居中

如下一个excel例表&#xff1a; 要将首行居中&#xff0c;最好的办法如下&#xff1a; 1、选中首行单元格 2、按下ctrl1&#xff0c;调出“设置单元格格式”&#xff0c;选中“对齐”&#xff0c;在“水平对齐”中选择“跨列居中” 3、完成任务 这样居中的好处是&#xff1a;可…

【C++】new和delete

这里是目录 C内存管理方式new/delete操作内置类型new和delete操作自定义类型定位new内存泄漏 前言 我们的程序当中主要有以下类型的数据&#xff08;用途/存储角度&#xff09;&#xff1a; 局部数据、静态数据、全局数据、常量数据、动态申请的数据 内存布局&#xff1a; C内…

KubeVela核心控制器原理浅析

前言 在学习 KubeVela 的核心控制器之前&#xff0c;我们先简单了解一下 KubeVela 的相关知识。 KubeVela 本身是一个应用交付与管理控制平面&#xff0c;它架在 Kubernetes 集群、云平台等基础设施之上&#xff0c;通过开放应用模型来对组件、云服务、运维能力、交付工作流进…

PWM(PulseWidthModulation)控制

PWM&#xff08;Pulse Width Modulation&#xff09;控制就是对脉冲的宽度进行调制的技术&#xff0c;即通过对一系列脉冲的宽度进行调制&#xff0c;来等效的获得所需要的波形&#xff08;含形状和幅值&#xff09;&#xff1b;面积等效原理是PWM技术的重要基础理论&#xff1…

【LabVIEW学习】3.labview制作安装程序

一。生成exe文件 1.创建可执行文件 &#xff08;1&#xff09;创建项目 注意&#xff1a; 1.创建.exe文件&#xff0c;这个文件在labview环境下才可以运行&#xff0c;如果直接传递给其他电脑&#xff08;没有labview环境&#xff09;&#xff0c;他是不可以运行的。 2.如果已…

原生实现底部弹窗效果 h5 小程序

<template><div class"home"><div class"btn" click"showPopupshow">弹出底部蒙层</div><div class"popup " catchtouchmove"true" :class"showPopup" ><div class"mask&q…