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

第十六章-消费者-PUSH方式(一)

16.1 准备阶段

先从一段官方示例代码开始

public class Consumer {public static void main(String[] args) throws InterruptedException, MQClientException {// 初始化consumer,并设置consumer group nameDefaultMQPushConsumer consumer = new DefaultMQPushConsumer("please_rename_unique_group_name");// 设置NameServer地址 consumer.setNamesrvAddr("localhost:9876");//订阅一个或多个topic,并指定tag过滤条件,这里指定*表示接收所有tag的消息consumer.subscribe("TopicTest", "*");//注册回调接口来处理从Broker中收到的消息consumer.registerMessageListener(new MessageListenerConcurrently() {@Overridepublic ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);// 返回消息消费状态,ConsumeConcurrentlyStatus.CONSUME_SUCCESS为消费成功return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;}});// 启动Consumerconsumer.start();System.out.printf("Consumer Started.%n");}
}

更多的介绍,可以直接看官网,咱们这直接上源码,那就从 consumer.start() 这一行代码开始。

DefaultMQPushConsumer.start

public void start() throws MQClientException {// 通过命名空间处理一下消费者组setConsumerGroup(NamespaceUtil.wrapNamespace(this.getNamespace(), this.consumerGroup));// push消费的实现类启动this.defaultMQPushConsumerImpl.start();// 访问日志追踪if (null != traceDispatcher) {try {traceDispatcher.start(this.getNamesrvAddr(), this.getAccessChannel());} catch (MQClientException e) {log.warn("trace dispatcher start failed ", e);}}
}

DefaultMQPushConsumerImpl.start

public synchronized void start() throws MQClientException {switch (this.serviceState) {case CREATE_JUST: // 启动时,看这块log.info("the consumer [{}] start beginning. messageModel={}, isUnitMode={}", this.defaultMQPushConsumer.getConsumerGroup(),this.defaultMQPushConsumer.getMessageModel(), this.defaultMQPushConsumer.isUnitMode());// 先设置成失败的状态this.serviceState = ServiceState.START_FAILED;// 检查配置项this.checkConfig();// 复制订阅信息,这里所做的事就是将订阅信息从 DefaultMQPushConsumerImpl 类的map 复制到 RebalanceImpl 类的map(rebalanceImpl.getSubscriptionInner())中,因为最终做消息处理的是 RebalanceImpl去与服务端打交道this.copySubscription();// 集群模式,实例名改成对应的进程Idif (this.defaultMQPushConsumer.getMessageModel() == MessageModel.CLUSTERING) {this.defaultMQPushConsumer.changeInstanceNameToPID();}// 获取或创建MQClientInstance实例,这个类很重要,同时涵盖了生产者和消费者的操作,具体使用时会讲this.mQClientFactory = MQClientManager.getInstance().getAndCreateMQClientInstance(this.defaultMQPushConsumer, this.rpcHook);//设置消费者组名this.rebalanceImpl.setConsumerGroup(this.defaultMQPushConsumer.getConsumerGroup());//设置消费模式this.rebalanceImpl.setMessageModel(this.defaultMQPushConsumer.getMessageModel());//设置分配mq策略(决定消费哪个mq的内容)       this.rebalanceImpl.setAllocateMessageQueueStrategy(this.defaultMQPushConsumer.getAllocateMessageQueueStrategy());//设置mq客户端实例对象this.rebalanceImpl.setmQClientFactory(this.mQClientFactory);//创建实际拉取消息的对象PullAPIWrapperthis.pullAPIWrapper = new PullAPIWrapper(mQClientFactory,this.defaultMQPushConsumer.getConsumerGroup(), isUnitMode());//注册消息过滤处理器列表this.pullAPIWrapper.registerFilterMessageHook(filterMessageHookList);//先在本地缓存中获取offsetstore,如果没有就去远程broker获取,offsetstore其实就是存放消费者消费mq的偏移量,防止重复消费if (this.defaultMQPushConsumer.getOffsetStore() != null) {this.offsetStore = this.defaultMQPushConsumer.getOffsetStore();} else {switch (this.defaultMQPushConsumer.getMessageModel()) {case BROADCASTING:// 广播模式,不做讲解this.offsetStore = new LocalFileOffsetStore(this.mQClientFactory, this.defaultMQPushConsumer.getConsumerGroup());break;case CLUSTERING://集群模式// 集群模式下,用RemoteBrokerOffsetStore对象来处理消费偏移this.offsetStore = new RemoteBrokerOffsetStore(this.mQClientFactory, this.defaultMQPushConsumer.getConsumerGroup());break;default:break;}this.defaultMQPushConsumer.setOffsetStore(this.offsetStore);}// 加载本机偏移信息,集群模式用的是 RemoteBrokerOffsetStore 类对象,默认load没有实现内容,这是一个钩子函数,子类可自行实现this.offsetStore.load();// 决定消息是顺序的还是并发的消费if (this.getMessageListenerInner() instanceof MessageListenerOrderly) {// 顺序this.consumeOrderly = true;this.consumeMessageService =new ConsumeMessageOrderlyService(this, (MessageListenerOrderly) this.getMessageListenerInner());} else if (this.getMessageListenerInner() instanceof MessageListenerConcurrently) {// 并发this.consumeOrderly = false;this.consumeMessageService =new ConsumeMessageConcurrentlyService(this, (MessageListenerConcurrently) this.getMessageListenerInner());}// 这里主要是对过期消息的任务处理this.consumeMessageService.start();
//将消费实例对象注册到本地内存consumerTable(ConcurrentMap)中,一个消费者组在一个客户端内,只会有一个消费实例对象boolean registerOK = mQClientFactory.registerConsumer(this.defaultMQPushConsumer.getConsumerGroup(), this);if (!registerOK) {//注册失败,恢复状态为创建,并向上抛出异常this.serviceState = ServiceState.CREATE_JUST;this.consumeMessageService.shutdown();throw new MQClientException("The consumer group[" + this.defaultMQPushConsumer.getConsumerGroup()+ "] has been created before, specify another name please." + FAQUrl.suggestTodo(FAQUrl.GROUP_NAME_DUPLICATE_URL),null);}//上面都是一些检查和数据准备工作,这一步才是真正启动服务的工作,启动内部实现,后面也会讲mQClientFactory.start();log.info("the consumer [{}] start OK.", this.defaultMQPushConsumer.getConsumerGroup());this.serviceState = ServiceState.RUNNING;break;case RUNNING:case START_FAILED:case SHUTDOWN_ALREADY:throw new MQClientException("The PushConsumer service state not OK, maybe started once, "+ this.serviceState+ FAQUrl.suggestTodo(FAQUrl.CLIENT_SERVICE_NOT_OK),null);default:break;}// 从namesrv中更新topic的路由信息this.updateTopicSubscribeInfoWhenSubscriptionChanged();// 通过Broker验证客户端的订阅数据合法性this.mQClientFactory.checkClientInBroker();// 发送心跳this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();// 启动完成后,唤醒 RebalanceService 服务this.mQClientFactory.rebalanceImmediately();
}

checkConfig 检查配置项

private void checkConfig() throws MQClientException {// group名 合法性检查Validators.checkGroup(this.defaultMQPushConsumer.getConsumerGroup());// group判空,个人感觉这里的判断完全可以放在前面if (null == this.defaultMQPushConsumer.getConsumerGroup()) {throw new MQClientException("consumerGroup is null"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// group 不能是默认的名字if (this.defaultMQPushConsumer.getConsumerGroup().equals(MixAll.DEFAULT_CONSUMER_GROUP)) {throw new MQClientException("consumerGroup can not equal "+ MixAll.DEFAULT_CONSUMER_GROUP+ ", please specify another one."+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 消息模式不能为空,只有2种:集群和广播if (null == this.defaultMQPushConsumer.getMessageModel()) {throw new MQClientException("messageModel is null"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 判断从哪开始消费,默认从最后一次偏移,包括最后一次偏移、最小偏移、最大偏移等if (null == this.defaultMQPushConsumer.getConsumeFromWhere()) {throw new MQClientException("consumeFromWhere is null"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 时间格式化Date dt = UtilAll.parseDate(this.defaultMQPushConsumer.getConsumeTimestamp(), UtilAll.YYYYMMDDHHMMSS);if (null == dt) {throw new MQClientException("consumeTimestamp is invalid, the valid format is yyyyMMddHHmmss,but received "+ this.defaultMQPushConsumer.getConsumeTimestamp()+ " " + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL), null);}// 消息队列分配策略,默认是平均分配if (null == this.defaultMQPushConsumer.getAllocateMessageQueueStrategy()) {throw new MQClientException("allocateMessageQueueStrategy is null"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 订阅容器map,不为空if (null == this.defaultMQPushConsumer.getSubscription()) {throw new MQClientException("subscription is null"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// push方式是异步的,所以需要一个消息监听器,因此,这里不能为空if (null == this.defaultMQPushConsumer.getMessageListener()) {throw new MQClientException("messageListener is null"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 顺序还是并发类型boolean orderly = this.defaultMQPushConsumer.getMessageListener() instanceof MessageListenerOrderly;boolean concurrently = this.defaultMQPushConsumer.getMessageListener() instanceof MessageListenerConcurrently;// 只能是二者选一,不能两者都不是if (!orderly && !concurrently) {throw new MQClientException("messageListener must be instanceof MessageListenerOrderly or MessageListenerConcurrently"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 判断最小消费者线程数合法性,默认20if (this.defaultMQPushConsumer.getConsumeThreadMin() < 1|| this.defaultMQPushConsumer.getConsumeThreadMin() > 1000) {throw new MQClientException("consumeThreadMin Out of range [1, 1000]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 判断最大消费者线程数合法性,默认20if (this.defaultMQPushConsumer.getConsumeThreadMax() < 1 || this.defaultMQPushConsumer.getConsumeThreadMax() > 1000) {throw new MQClientException("consumeThreadMax Out of range [1, 1000]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// consumeThreadMin 不可能比 consumeThreadMax 更大if (this.defaultMQPushConsumer.getConsumeThreadMin() > this.defaultMQPushConsumer.getConsumeThreadMax()) {throw new MQClientException("consumeThreadMin (" + this.defaultMQPushConsumer.getConsumeThreadMin() + ") "+ "is larger than consumeThreadMax (" + this.defaultMQPushConsumer.getConsumeThreadMax() + ")",null);}// 判断并发消费最大的偏移跨度,默认2000,非法证明消费过程有问题if (this.defaultMQPushConsumer.getConsumeConcurrentlyMaxSpan() < 1|| this.defaultMQPushConsumer.getConsumeConcurrentlyMaxSpan() > 65535) {throw new MQClientException("consumeConcurrentlyMaxSpan Out of range [1, 65535]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 队列级别的流量控制阈值,默认情况下每个消息队列最多缓存1000条消息,考虑{@code pullBatchSize},瞬时值可能超过限制if (this.defaultMQPushConsumer.getPullThresholdForQueue() < 1 || this.defaultMQPushConsumer.getPullThresholdForQueue() > 65535) {throw new MQClientException("pullThresholdForQueue Out of range [1, 65535]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// topic级别的流量控制阈值if (this.defaultMQPushConsumer.getPullThresholdForTopic() != -1) {if (this.defaultMQPushConsumer.getPullThresholdForTopic() < 1 || this.defaultMQPushConsumer.getPullThresholdForTopic() > 6553500) {throw new MQClientException("pullThresholdForTopic Out of range [1, 6553500]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}}// 队列级别的限制拉取大小,默认情况下每个消息队列最多缓存100Mif (this.defaultMQPushConsumer.getPullThresholdSizeForQueue() < 1 || this.defaultMQPushConsumer.getPullThresholdSizeForQueue() > 1024) {throw new MQClientException("pullThresholdSizeForQueue Out of range [1, 1024]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// topic级别的限制拉取大小,默认情况下每个消息队列最多缓存100Mif (this.defaultMQPushConsumer.getPullThresholdSizeForTopic() != -1) {// pullThresholdSizeForTopicif (this.defaultMQPushConsumer.getPullThresholdSizeForTopic() < 1 || this.defaultMQPushConsumer.getPullThresholdSizeForTopic() > 102400) {throw new MQClientException("pullThresholdSizeForTopic Out of range [1, 102400]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}}// 拉取间隔时间if (this.defaultMQPushConsumer.getPullInterval() < 0 || this.defaultMQPushConsumer.getPullInterval() > 65535) {throw new MQClientException("pullInterval Out of range [0, 65535]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 批量消费消息的最大大小if (this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize() < 1|| this.defaultMQPushConsumer.getConsumeMessageBatchMaxSize() > 1024) {throw new MQClientException("consumeMessageBatchMaxSize Out of range [1, 1024]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}// 批量拉取的大小if (this.defaultMQPushConsumer.getPullBatchSize() < 1 || this.defaultMQPushConsumer.getPullBatchSize() > 1024) {throw new MQClientException("pullBatchSize Out of range [1, 1024]"+ FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),null);}
}

MQClientInstance.start

public void start() throws MQClientException {synchronized (this) {switch (this.serviceState) {case CREATE_JUST:this.serviceState = ServiceState.START_FAILED;//这一步就是获取name server的地址,正常都会指定的,否则没有什么意义if (null == this.clientConfig.getNamesrvAddr()) {this.mQClientAPIImpl.fetchNameServerAddr();}/* 启动 request-response channel,具体细节不在这里讲,以后有机会再写netty源码,主要做了以下工作1.设置netty工作线程2.设置netty收发消息时的处理器3.创建延迟3秒且每秒执行一次扫描过期无效的reponse信息的请求4.设置消息远程读取/接收的Netty处理器,NettyClientHandler,重点关注,先记着,后面会用*/this.mQClientAPIImpl.start();/* 启动rocketmq内置的一些定时任务,如下:1.延迟10秒且每2分钟执行一次获取最新name server 地址的任务2.延迟10毫秒且每{this.clientConfig.getPollNameServerInterval()	     (pollNameServerInterval可配置,但默认是30秒)}毫秒执行一次更新topic路由信息的任务MQClientInstance.this.updateTopicRouteInfoFromNameServer()3.延迟1秒且每{this.clientConfig.getHeartbeatBrokerInterval()	     (heartbeatBrokerInterval可配置,但默认是30秒)}毫秒执行一次清除下线的broker和发送心态到所有broker的任务4.延迟10秒且每{this.clientConfig.getPersistConsumerOffsetInterval()	     (persistConsumerOffsetInterval可配置,但默认是5秒)}毫秒执行一次持久化消息者offset值的任务,持久化存放在哪呢?放到broker中5.延迟1毫秒且每1分钟执行一次动态改变消息推送到消费者的工作线程数的任务*/this.startScheduledTask();//启动拉取消息服务this.pullMessageService.start();// 启动负载均衡服务this.rebalanceService.start();//因为MQClientInstance这个类,是生产者和消费都共用的,且消费者也会使用消费生产并发送操作,比如消费失败时重推消息,也需要启动生产者实现类,所以看到这段代码不用奇怪,如果是生产者,就算调用start方法,也不会启动2次,内部有针对状态的判断this.defaultMQProducer.getDefaultMQProducerImpl().start(false);log.info("the client factory [{}] start OK", this.clientId);this.serviceState = ServiceState.RUNNING;break;case RUNNING:break;case SHUTDOWN_ALREADY:break;case START_FAILED:throw new MQClientException("The Factory object[" + this.getClientId() + "] has been created before, and failed.", null);default:break;}}
}

相关文章:

第十六章-消费者-PUSH方式(一)

16.1 准备阶段 先从一段官方示例代码开始 public class Consumer {public static void main(String[] args) throws InterruptedException, MQClientException {// 初始化consumer&#xff0c;并设置consumer group nameDefaultMQPushConsumer consumer new DefaultMQPushCo…...

【C++要哮着学】初识C++,什么是C++?什么是命名空间?什么又是缺省函数?

文章目录 前言1、C简介1.1、什么是C1.2、C起源1.3、C发展 2、C关键字&#xff08;C98&#xff09;3、命名空间3.1、命名空间的定义及使用3.2、命名空间的嵌套3.3、命名空间的三种使用方式3.3.1、加命名空间名称及作用域限定符3.3.2、使用using将命名空间中某个成员引入3.3.3、使…...

Lua 数字格式化

在编程中&#xff0c;对数字进行格式化是一项常见的任务&#xff0c;特别是当我们需要在用户界面中显示数据或生成报告时。在 Lua 中&#xff0c;我们可以使用一些简单而有效的函数来实现数字的格式化。在本文中&#xff0c;我们将介绍一个由几个函数组成的小型 Lua 库&#xf…...

Java入门基础学习笔记13——数据类型

数据类型的分类&#xff1a; 基本数据类型 引用数据类型 基本数据类型&#xff1a;4大类8种类型&#xff1a; 定义整形用int&#xff0c;再大的数用long。 package cn.ensource.variable;public class VariableDemo2 {public static void main(String[] args) {//目标&#x…...

使用Docker+Jar方式部署微服务工程(前后端分离)看着一篇就够了

本篇教程的使用到的技术有springboot、springcloud、Nacos、Docker、Nginx部署前后端分离访问的微服务。 部署一下Nacos 首先我们需要在服务器中&#xff08;或者本地部署启动一下Nacos&#xff09;&#xff0c;这里我采用服务器的方式进行部署&#xff0c;这里有一点不一样的…...

红外遥控和LCD1602

26.1.1 红外线简介 人的眼睛能看到的可见光按波长从长到短排列&#xff0c;依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为 0.62&#xff5e;0.76μm&#xff1b;紫光的波长范围为 0.38&#xff5e;0.46μm。比紫光波长还短的光叫紫外线&#xff0c;比红光波长还长的…...

房屋出租管理系统需求分析及功能介绍

房屋租赁管理系统适用于写字楼、办公楼、厂区、园区、商城、公寓等商办商业不动产的租赁管理及租赁营销&#xff1b;提供资产管理&#xff0c;合同管理&#xff0c;租赁管理&#xff0c; 物业管理&#xff0c;门禁管理等一体化的运营管理平台&#xff0c;提高项目方管理运营效率…...

高精度模拟算法

高精度模拟算法 高精度加法 extern string m,n; extern int a[MAX],b[MAX],ans[MAX]; void addition(){int _mmax(m.size(),n.size());reverse(m.begin(),m.end()),reverse(n.begin(),n.end());//转置原字符串for(int i0;i<m.size();i) a[i]m[i]-0;//字符型以ASCII码存储&…...

Ansible简介版

目录 架构 环境部署 一、Ansible安装部署 1.yum安装Ansible 2.修改主机清单文件 3.配置密钥对验证 4.ansible-doc 5.看被控主机 二、常用模块 1.Command模块 2.Shell模块 3.Cron模块 1.添加 2.删除 4.User模块 5.Group模块 1.创建组 ​编辑 ​编辑 ​编辑…...

卷积通用模型的剪枝、蒸馏---蒸馏篇--RKD关系蒸馏(以deeplabv3+为例)

本文使用RKD实现对deeplabv3+模型的蒸馏;与上一篇KD蒸馏的方法有所不同,RKD是对展平层的特征做蒸馏,蒸馏的loss分为二阶的距离损失Distance-wise Loss和三阶的角度损失Angle-wise Loss。 完整代码放在文末。 一、RKD简介 RKD算法的核心是以教师模型的多个输出为结构单元,取…...

AVL树的完全指南:平衡与性能

文章目录 AVL树简介AVL的操作建立一个AVL树插入操作删除操作 书写代码1.构造函数和析构函数2.获取最大值和最小值3.树的高度和节点个数3.前序中序和后序遍历4.判断树是否为空树5.四个旋转操作6.获取平衡因子7.插入操作8.删除操作9.搜索节点.h文件中的定义 总结 AVL树简介 AVL树…...

itext7 PDF添加水印,获取页面高度,添加到页面右上角

ps: pdf添加水印&#xff0c;内容多的时候会往下跑&#xff0c;修改为获取当前页面高度&#xff0c;进行固定在顶部&#xff0c;其他需要可以自己进行调整&#xff0c;直接贴代码。 public static void main(String[] args) throws IOException {String localFilePath "…...

docker端口映射成功,docker端口不生效的问题解决,外界无法访问docker映射端口

docker端口映射不生效的问题解决 问题 使用docker run -p 88848:8848后&#xff0c;显示容器启动正常&#xff0c;并且使用docker logs –f xxx能够看到容器可以正常启用&#xff0c;docker ps 可以看到容器启动成功&#xff0c;并且端口已经映射,但是在浏览器访问相关地址&am…...

RSA非对称加密解密,前端公钥加密后端私钥解密

RSA非对称加密解密&#xff0c;前端公钥加密后端私钥解密&#xff0c;可以防止陌生人直接通过后端接口篡改数据。有数据泄露的风险。 前端&#xff1a;Vue框架 后端&#xff1a;sprintboot&#xff08;Java&#xff09; 工具类&#xff1a;hutool 前端Vue获取公钥&#xff1a…...

Nginx-01-Nginx 是什么? 能做什么?

nginx 系列 Nginx-01-聊一聊 nginx Nginx-01-Nginx 是什么 Nginx-02-为什么使用 Nginx Nginx-02-Nginx Ubuntu 安装 windows10 WSL ubuntu 安装 nginx 实战笔记 Nginx-02-基本使用 Nginx-03-Nginx 项目架构 Nginx-04-Docker Nginx Nginx-05-nginx 反向代理是什么&…...

最大数字——蓝桥杯十三届2022国赛大学B组真题

问题分析 这道题属于贪心加回溯。所有操作如果能使得高位的数字变大必定优先用在高位&#xff0c;因为对高位的影响永远大于对低位的影响。然后我们再来分析一下&#xff0c;如何使用这两种操作&#xff1f;对于加操作&#xff0c;如果能使这一位的数字加到9则变成9&#xff0…...

查看微信小程序主包大小

前言 略 查看微信小程序主包大小 在微信开发者工具右上角找到“详情->基本信息” 查看微信小程序主包构成 通过微信开发者工具中的“代码依赖分析”工具查看...

B树与B+树的奥秘:原理解析与性能

引言 B树和B树是计算机科学中两个重要的数据结构&#xff0c;它们在数据库和文件系统中扮演着至关重要的角色。在处理大量数据时&#xff0c;高效的数据组织和检索方式是至关重要的&#xff0c;而B树和B树正是为此而设计的。 B树和B树都是多路查找树的变体&#xff0c;它们通…...

Unity组件入门篇目录

Audio AudioChorusFilter......................................点击导航AudioDistortionFilter..................................点击导航AudioEchoFilter.........................................点击导航AudioHighPassFilter..................................点击导…...

【Python技术】使用akshare、pandas高效复盘每日涨停板行业分析

作为一个程序员宝爸&#xff0c;每天的时间很宝贵&#xff0c;工作之余除了辅导孩子作业&#xff0c;就是补充睡眠。 怎么快速高效的进行当天A股涨停板的复盘&#xff0c;便于第二天的跟踪。这里简单写个示例&#xff0c; 获取当天连涨数排序&#xff0c;以及所属行业排序。 …...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...

React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾&#xff1a; 在上一篇《React核心概念&#xff1a;State是什么&#xff1f;》中&#xff0c;我们学习了如何使用useState让一个组件拥有自己的内部数据&#xff08;State&#xff09;&#xff0c;并通过一个计数器案例&#xff0c;实现了组件的自我更新。这很棒&#…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.

报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符&#xff0c;最后运行&#xff1a;npm run lint --fix...

Centos 7 服务器部署多网站

一、准备工作 安装 Apache bash sudo yum install httpd -y sudo systemctl start httpd sudo systemctl enable httpd创建网站目录 假设部署 2 个网站&#xff0c;目录结构如下&#xff1a; bash sudo mkdir -p /var/www/site1/html sudo mkdir -p /var/www/site2/html添加测试…...