RocketMQ源码 Broker-TopicConfigManager 元数据管理组件源码分析

前言

ConsumerOffsetManager负责管理Broker端的topicConfig元数据信息,它继承了ConfigManager组件,且定时将内存中维护的topic元数据信息,注册到远程NameServer集群,并持久化到磁盘文件。

源码版本:4.9.3

源码架构图

核心数据结构

topic元数据管理组件最核心的数据结构是,它所维护的topicConfigTable topic元数据表,key是topicName,value是topic元数据对象。

public class TopicConfigManager extends ConfigManager {private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);// 锁超时时间3秒private static final long LOCK_TIMEOUT_MILLIS = 3000;// 调度队列数量 18个队列private static final int SCHEDULE_TOPIC_QUEUE_NUM = 18;// topic元数据锁private transient final Lock topicConfigTableLock = new ReentrantLock();// 核心,topic元数据表,key是topicName, value是topic元数据private final ConcurrentMap<String, TopicConfig> topicConfigTable =new ConcurrentHashMap<String, TopicConfig>(1024);// 数据版本private final DataVersion dataVersion = new DataVersion();private transient BrokerController brokerController;
}

深入看一下TopicConfig元数据对象,主要包含了主题名称、队列数量、权限、过滤类型等核心结构。

public class TopicConfig {private static final String SEPARATOR = " ";// 默认读写队列数量,都是16个public static int defaultReadQueueNums = 16;public static int defaultWriteQueueNums = 16;// 主题名称private String topicName;private int readQueueNums = defaultReadQueueNums;private int writeQueueNums = defaultWriteQueueNums;// 权限private int perm = PermName.PERM_READ | PermName.PERM_WRITE;// 过滤类型private TopicFilterType topicFilterType = TopicFilterType.SINGLE_TAG;// 系统标识private int topicSysFlag = 0;private boolean order = false;
}

接下来,看一下,topic元数据管理组件的核心行为。在创建对象实例阶段,初始化了大量系统级topic元数据,且继承了ConfigManager的数据持久化与加载磁盘文件能力。并且提供了大量可以自动创建topic的方法,在创建和更新内存中的topic元数据后,会更新将元数据信息并发注册到远程所有NameServer集群节点(使用到了countDownLatch、oneWay通信),且持久化到磁盘文件。

下面是topic元数据管理组件所有的方法行为:


public class TopicConfigManager extends ConfigManager {private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);// 锁超时时间3秒private static final long LOCK_TIMEOUT_MILLIS = 3000;// 调度队列数量 18个队列private static final int SCHEDULE_TOPIC_QUEUE_NUM = 18;// topic元数据锁private transient final Lock topicConfigTableLock = new ReentrantLock();// 核心,topic元数据表,key是topicName, value是topic元数据private final ConcurrentMap<String, TopicConfig> topicConfigTable =new ConcurrentHashMap<String, TopicConfig>(1024);// 数据版本private final DataVersion dataVersion = new DataVersion();private transient BrokerController brokerController;public TopicConfigManager() {}public TopicConfigManager(BrokerController brokerController) {this.brokerController = brokerController;// 初始化系统元数据{// 系统测试topicString topic = TopicValidator.RMQ_SYS_SELF_TEST_TOPIC;TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(1);topicConfig.setWriteQueueNums(1);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}{// 自动创建topicif (this.brokerController.getBrokerConfig().isAutoCreateTopicEnable()) {String topic = TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC;TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(this.brokerController.getBrokerConfig().getDefaultTopicQueueNums());topicConfig.setWriteQueueNums(this.brokerController.getBrokerConfig().getDefaultTopicQueueNums());int perm = PermName.PERM_INHERIT | PermName.PERM_READ | PermName.PERM_WRITE;topicConfig.setPerm(perm);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}}{// 性能测试topicString topic = TopicValidator.RMQ_SYS_BENCHMARK_TOPIC;TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(1024);topicConfig.setWriteQueueNums(1024);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}{// 集群topicString topic = this.brokerController.getBrokerConfig().getBrokerClusterName();TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);int perm = PermName.PERM_INHERIT;if (this.brokerController.getBrokerConfig().isClusterTopicEnable()) {perm |= PermName.PERM_READ | PermName.PERM_WRITE;}topicConfig.setPerm(perm);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}{// broker topicString topic = this.brokerController.getBrokerConfig().getBrokerName();TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);int perm = PermName.PERM_INHERIT;if (this.brokerController.getBrokerConfig().isBrokerTopicEnable()) {perm |= PermName.PERM_READ | PermName.PERM_WRITE;}topicConfig.setReadQueueNums(1);topicConfig.setWriteQueueNums(1);topicConfig.setPerm(perm);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}{// offset moved event topicString topic = TopicValidator.RMQ_SYS_OFFSET_MOVED_EVENT;TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(1);topicConfig.setWriteQueueNums(1);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}{// schedule topicString topic = TopicValidator.RMQ_SYS_SCHEDULE_TOPIC;TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(SCHEDULE_TOPIC_QUEUE_NUM);topicConfig.setWriteQueueNums(SCHEDULE_TOPIC_QUEUE_NUM);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}{// trace topicif (this.brokerController.getBrokerConfig().isTraceTopicEnable()) {String topic = this.brokerController.getBrokerConfig().getMsgTraceTopicName();TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(1);topicConfig.setWriteQueueNums(1);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}}{// reply topicString topic = this.brokerController.getBrokerConfig().getBrokerClusterName() + "_" + MixAll.REPLY_TOPIC_POSTFIX;TopicConfig topicConfig = new TopicConfig(topic);TopicValidator.addSystemTopic(topic);topicConfig.setReadQueueNums(1);topicConfig.setWriteQueueNums(1);this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);}}// 查询topic元数据public TopicConfig selectTopicConfig(final String topic) {return this.topicConfigTable.get(topic);}// 在发送消息时,自动创建topicpublic TopicConfig createTopicInSendMessageMethod(final String topic, final String defaultTopic,final String remoteAddress, final int clientDefaultTopicQueueNums, final int topicSysFlag) {TopicConfig topicConfig = null;boolean createNew = false;try {// 获取一把全局锁,防止并发创建topic,超时时间3秒if (this.topicConfigTableLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {try {// 如果存在topic元数据,直接返回topic元数据topicConfig = this.topicConfigTable.get(topic);if (topicConfig != null)return topicConfig;// 获取默认topic元数据TopicConfig defaultTopicConfig = this.topicConfigTable.get(defaultTopic);if (defaultTopicConfig != null) {// 如果默认topic元数据是允许自动创建if (defaultTopic.equals(TopicValidator.AUTO_CREATE_TOPIC_KEY_TOPIC)) {// 如果禁止自动创建,则默认topic元数据权限为只读if (!this.brokerController.getBrokerConfig().isAutoCreateTopicEnable()) {defaultTopicConfig.setPerm(PermName.PERM_READ | PermName.PERM_WRITE);}}// 如果默认topic元数据是允许继承,根据默认topic创建if (PermName.isInherited(defaultTopicConfig.getPerm())) {topicConfig = new TopicConfig(topic);int queueNums = Math.min(clientDefaultTopicQueueNums, defaultTopicConfig.getWriteQueueNums());if (queueNums < 0) {queueNums = 0;}topicConfig.setReadQueueNums(queueNums);topicConfig.setWriteQueueNums(queueNums);int perm = defaultTopicConfig.getPerm();perm &= ~PermName.PERM_INHERIT;topicConfig.setPerm(perm);topicConfig.setTopicSysFlag(topicSysFlag);topicConfig.setTopicFilterType(defaultTopicConfig.getTopicFilterType());} else {log.warn("Create new topic failed, because the default topic[{}] has no perm [{}] producer:[{}]",defaultTopic, defaultTopicConfig.getPerm(), remoteAddress);}} else {log.warn("Create new topic failed, because the default topic[{}] not exist. producer:[{}]",defaultTopic, remoteAddress);}if (topicConfig != null) {log.info("Create new topic by default topic:[{}] config:[{}] producer:[{}]",defaultTopic, topicConfig, remoteAddress);// 将topic元数据添加到topicConfigTable中this.topicConfigTable.put(topic, topicConfig);// 升级版本号this.dataVersion.nextVersion();// 创建topiccreateNew = true;// 持久化元数据this.persist();}} finally {this.topicConfigTableLock.unlock();}}} catch (InterruptedException e) {log.error("createTopicInSendMessageMethod exception", e);}if (createNew) {this.brokerController.registerBrokerAll(false, true, true);}return topicConfig;}public TopicConfig createTopicInSendMessageBackMethod(final String topic,final int clientDefaultTopicQueueNums,final int perm,final int topicSysFlag) {TopicConfig topicConfig = this.topicConfigTable.get(topic);if (topicConfig != null)return topicConfig;boolean createNew = false;try {// 获取一把全局锁,防止并发创建topic,超时时间3秒if (this.topicConfigTableLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {try {// 如果存在元数据,直接返回topicConfig = this.topicConfigTable.get(topic);if (topicConfig != null)return topicConfig;topicConfig = new TopicConfig(topic);topicConfig.setReadQueueNums(clientDefaultTopicQueueNums);topicConfig.setWriteQueueNums(clientDefaultTopicQueueNums);topicConfig.setPerm(perm);topicConfig.setTopicSysFlag(topicSysFlag);// 如果不存在,则创建log.info("create new topic {}", topicConfig);this.topicConfigTable.put(topic, topicConfig);createNew = true;// 升级版本号this.dataVersion.nextVersion();// 持久化元数据this.persist();} finally {// 释放锁this.topicConfigTableLock.unlock();}}} catch (InterruptedException e) {log.error("createTopicInSendMessageBackMethod exception", e);}if (createNew) {// 注册所有broker信息到nameServerthis.brokerController.registerBrokerAll(false, true, true);}return topicConfig;}// 创建事务消息检查最大时间的topicpublic TopicConfig createTopicOfTranCheckMaxTime(final int clientDefaultTopicQueueNums, final int perm) {TopicConfig topicConfig = this.topicConfigTable.get(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);if (topicConfig != null)return topicConfig;boolean createNew = false;try {if (this.topicConfigTableLock.tryLock(LOCK_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) {try {topicConfig = this.topicConfigTable.get(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);if (topicConfig != null)return topicConfig;topicConfig = new TopicConfig(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC);topicConfig.setReadQueueNums(clientDefaultTopicQueueNums);topicConfig.setWriteQueueNums(clientDefaultTopicQueueNums);topicConfig.setPerm(perm);topicConfig.setTopicSysFlag(0);log.info("create new topic {}", topicConfig);this.topicConfigTable.put(TopicValidator.RMQ_SYS_TRANS_CHECK_MAX_TIME_TOPIC, topicConfig);createNew = true;this.dataVersion.nextVersion();this.persist();} finally {this.topicConfigTableLock.unlock();}}} catch (InterruptedException e) {log.error("create TRANS_CHECK_MAX_TIME_TOPIC exception", e);}if (createNew) {this.brokerController.registerBrokerAll(false, true, true);}return topicConfig;}// 更新topic的unit flagpublic void updateTopicUnitFlag(final String topic, final boolean unit) {TopicConfig topicConfig = this.topicConfigTable.get(topic);if (topicConfig != null) {// 更新单元标int oldTopicSysFlag = topicConfig.getTopicSysFlag();if (unit) {topicConfig.setTopicSysFlag(TopicSysFlag.setUnitFlag(oldTopicSysFlag));} else {topicConfig.setTopicSysFlag(TopicSysFlag.clearUnitFlag(oldTopicSysFlag));}log.info("update topic sys flag. oldTopicSysFlag={}, newTopicSysFlag={}", oldTopicSysFlag,topicConfig.getTopicSysFlag());// 存入内存数元数据tablethis.topicConfigTable.put(topic, topicConfig);// 更新数据版本号this.dataVersion.nextVersion();// 持久化this.persist();// 注册所有broker信息到nameServerthis.brokerController.registerBrokerAll(false, true, true);}}// 更新topic的unit sub flagpublic void updateTopicUnitSubFlag(final String topic, final boolean hasUnitSub) {TopicConfig topicConfig = this.topicConfigTable.get(topic);if (topicConfig != null) {int oldTopicSysFlag = topicConfig.getTopicSysFlag();if (hasUnitSub) {topicConfig.setTopicSysFlag(TopicSysFlag.setUnitSubFlag(oldTopicSysFlag));} else {topicConfig.setTopicSysFlag(TopicSysFlag.clearUnitSubFlag(oldTopicSysFlag));}log.info("update topic sys flag. oldTopicSysFlag={}, newTopicSysFlag={}", oldTopicSysFlag,topicConfig.getTopicSysFlag());this.topicConfigTable.put(topic, topicConfig);this.dataVersion.nextVersion();this.persist();this.brokerController.registerBrokerAll(false, true, true);}}// 更新topic元数据public void updateTopicConfig(final TopicConfig topicConfig) {TopicConfig old = this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);if (old != null) {log.info("update topic config, old:[{}] new:[{}]", old, topicConfig);} else {log.info("create new topic [{}]", topicConfig);}// 更新数据版本号this.dataVersion.nextVersion();// 持久化元数据到磁盘this.persist();}// 更新顺序 topic元数据public void updateOrderTopicConfig(final KVTable orderKVTableFromNs) {if (orderKVTableFromNs != null && orderKVTableFromNs.getTable() != null) {boolean isChange = false;Set<String> orderTopics = orderKVTableFromNs.getTable().keySet();for (String topic : orderTopics) {TopicConfig topicConfig = this.topicConfigTable.get(topic);if (topicConfig != null && !topicConfig.isOrder()) {// 在顺序topic列表中,更新topic为顺序topictopicConfig.setOrder(true);isChange = true;log.info("update order topic config, topic={}, order={}", topic, true);}}for (Map.Entry<String, TopicConfig> entry : this.topicConfigTable.entrySet()) {String topic = entry.getKey();if (!orderTopics.contains(topic)) {// 不在顺序topic列表中,更新为非顺序topicTopicConfig topicConfig = entry.getValue();if (topicConfig.isOrder()) {topicConfig.setOrder(false);isChange = true;log.info("update order topic config, topic={}, order={}", topic, false);}}}if (isChange) {// 更新数据版本号this.dataVersion.nextVersion();// 持久化元数据到磁盘this.persist();}}}public boolean isOrderTopic(final String topic) {TopicConfig topicConfig = this.topicConfigTable.get(topic);if (topicConfig == null) {return false;} else {return topicConfig.isOrder();}}// 删除topic元数据,并持久化public void deleteTopicConfig(final String topic) {TopicConfig old = this.topicConfigTable.remove(topic);if (old != null) {log.info("delete topic config OK, topic: {}", old);this.dataVersion.nextVersion();this.persist();} else {log.warn("delete topic config failed, topic: {} not exists", topic);}}public TopicConfigSerializeWrapper buildTopicConfigSerializeWrapper() {TopicConfigSerializeWrapper topicConfigSerializeWrapper = new TopicConfigSerializeWrapper();topicConfigSerializeWrapper.setTopicConfigTable(this.topicConfigTable);topicConfigSerializeWrapper.setDataVersion(this.dataVersion);return topicConfigSerializeWrapper;}@Overridepublic String encode() {return encode(false);}@Overridepublic String configFilePath() {return BrokerPathConfigHelper.getTopicConfigPath(this.brokerController.getMessageStoreConfig().getStorePathRootDir());}// 解码json字符串,解析为topic元数据结构@Overridepublic void decode(String jsonString) {if (jsonString != null) {TopicConfigSerializeWrapper topicConfigSerializeWrapper =TopicConfigSerializeWrapper.fromJson(jsonString, TopicConfigSerializeWrapper.class);if (topicConfigSerializeWrapper != null) {this.topicConfigTable.putAll(topicConfigSerializeWrapper.getTopicConfigTable());this.dataVersion.assignNewOne(topicConfigSerializeWrapper.getDataVersion());this.printLoadDataWhenFirstBoot(topicConfigSerializeWrapper);}}}// 将核心数据结构内容编码为json字符串public String encode(final boolean prettyFormat) {TopicConfigSerializeWrapper topicConfigSerializeWrapper = new TopicConfigSerializeWrapper();topicConfigSerializeWrapper.setTopicConfigTable(this.topicConfigTable);topicConfigSerializeWrapper.setDataVersion(this.dataVersion);return topicConfigSerializeWrapper.toJson(prettyFormat);}private void printLoadDataWhenFirstBoot(final TopicConfigSerializeWrapper tcs) {Iterator<Entry<String, TopicConfig>> it = tcs.getTopicConfigTable().entrySet().iterator();while (it.hasNext()) {Entry<String, TopicConfig> next = it.next();log.info("load exist local topic, {}", next.getValue().toString());}}public DataVersion getDataVersion() {return dataVersion;}public ConcurrentMap<String, TopicConfig> getTopicConfigTable() {return topicConfigTable;}
}

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

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

相关文章

12.15

写这段代码改了好几个小时&#xff0c;从有这个想法到完成花费了比较久的时间&#xff0c;也很有成就感。速成课给的伪代码思路漏掉了需要判断最小数是否正好是这个数本身这个条件&#xff0c;所以一直报错。所以写代码要把每种可能性都涵盖&#xff0c;不然程序就会出问题。之…

【渗透测试】常用的8种火狐插件

1、Max HacKBar 推荐理由&#xff1a;免费的hackbar插件&#xff0c;可快速使用SQL注入、XSS和Bypass等payload进行测试&#xff0c;可进行多种编码和解码&#xff0c;安装后F12即可使用。 2、FoxyProxy Standard 推荐理由&#xff1a;FoxyProxy是一个高级的代理管理工具&am…

jmeter,csv文件参数化+断言 实现一个接口的case

1、case 及其 测试数据 注意保存文件的编码格式 id,name,limit,status,address,start_time,assert_status,assert_message 100,小米100,1000,1,某某会展中心101,2023-8-20 14:20,200,add event success ,,,,,,10021,parameter error 100,小米102,1002,1,某某会展中心103,2023-…

十五、YARN辅助架构

1、学习内容 &#xff08;1&#xff09;了解什么是代理服务器 &#xff08;2&#xff09;了解什么是历史服务器 2、辅助架构 &#xff08;1&#xff09;辅助架构的由来 对于YARN架构来讲&#xff0c;除了ResourceManager集群资源总管家、NodeManager单机资源管家两个核心角…

AI日报:谷歌Gemini Pro即将面向企业和开发者

文章目录 总览Gemini介绍 模型能力产品API其他产品Imagen2和其他新闻Duet AI 总览 现在&#xff0c;您可以免费访问Gemini Pro的API&#xff0c;这是谷歌最新大型语言模型的第一个版本。 Gemini 介绍 谷歌通过其API让企业和开发者第一次看到了其最强大的大型语言模型Gemini。…

后端项目操作数据库-中枢组件Service调用Mapper实现增删改查-实例

接上篇 使用MyBatis配置Mapper实现增删改查 1.Service的基本作用 Service在代码中的的作用是调用Mapper、被Controller调用。是后端项目中非常重要的组件。 用于设计业务流程、业务逻辑&#xff0c;以保障数据的完整性、有效性、安全性。 2. Service使用举例——“添加相册”…

C++/语法@初始化列表

目录 初始化列表特征疑惑区别必在初始化列表中初始化的三种成员变量1、引用成员变量程序例子&#xff1a;运行结果&#xff1a; 2、const成员变量程序例子&#xff1a;运行结果&#xff1a; 3、自定义类型成员&#xff08;没有默认构造函数的类&#xff09;程序例子&#xff1a…

mysql:通过INFORMATION_SCHEMA数据库查询表的元信息

使用SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA database_name AND TABLE_NAME table_name;查询某个表的元信息。其中database_name替换为数据库名称&#xff0c;table_name替换为表的名称。 例如&#xff0c;下面语句&#xff0c;查询development数据库中…

Mirrors and reflections for VR

专为虚拟现实而建,但也非常适合非虚拟现实桌面和移动项目 这是URP管道,从Unity2019.4.16一直测试到2023年。 完全工作场景预览,轻松修改着色器材质。着色器支持折射,可以制作很酷的效果。 镜子/反射可以互相反射,而不仅仅是2...想象一下一个电梯,3面镜子都互相反射,直到…

阿木实验室普罗米修斯项目环境配置

引言 普罗米修斯项目其实只是个大ROS功能包&#xff0c; 里面每个模块就是每个ROS功能包&#xff0c;比如控制模块&#xff0c;视觉模块等等。对PX4配置的与这个一样&#xff0c;另外他是使用自己的P系列无人机&#xff08;我个人是&#xff30;450&#xff09;&#xff0c;所…

腾讯科技Hi Tech Day暨2023数字开物大会:智能涌现将通往无数的未来

腾讯科技讯 12月14日&#xff0c;以“智能涌现 数开万物”为主题的腾讯科技Hi Tech Day暨2023数字开物大会在北京国家会议中心召开&#xff0c;腾讯科技邀请知名院士、知名经济学家、知名大学教授、研究院院长、产业大咖、互联网大厂高管、知名科技领域头部企业高管、产业数字化…

vscode创建代码片段 vue3modal

{// Place your 全局 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope// is left empty or omitte…

干货:企业如何讲好品牌故事

品牌故事讲得好&#xff0c;不仅能够体现品牌特色还能向消费者传递品牌精神的重要工具&#xff0c;优秀的品牌故事能够促进产品销量&#xff0c;为品牌带来曝光率&#xff0c;今天媒介盒子就来和大家聊聊&#xff1a;如何讲好品牌故事。 一、 品类历史和故事 品牌虽然是新品牌…

平面腔体谐振计算与仿真

PCB的电源网络是由电介质材料隔开的两个平行金属板所组成&#xff0c;可以通过以下的3种方法对其谐振模式进行分析&#xff1a; 1. 基于腔体模型的计算&#xff1b; 2. 基于SPICE等效电路&#xff1b; 3. 基于全波数值电磁算法的3D模型。 设计得当的前提下&#xff0c;上述3种方…

LVS负载均衡器(nat模式)+nginx(七层反向代理)+tomcat(多实例),实现负载均衡和动静分离

目录 前言 一、配置nfs共享存储 二、配置2个nginx节点服务的网页页面 节点1:192.168.20.10 步骤一&#xff1a;修改网关指向调度器的内网ip地址 步骤二&#xff1a;将nfs共享的目录进行挂载&#xff0c;并修改nginx的配置文件中location的root指向挂载点 步骤三&#xff…

SpringCloud面试题——分布式事务

一&#xff1a;什么是分布式事务? 分布式事务是指在分布式系统中涉及到多个数据库或多个应用程序之间的事务处理&#xff0c;这些数据库或应用程序可能分布在不同的物理节点上&#xff0c;甚至可能位于不同的地理位置。在分布式事务中&#xff0c;需要确保所有参与者的事务操…

PPT插件-好用的插件-图形缩放-大珩助手

图形缩放 包括适合屏幕、适合宽度、适合高度、水平翻转、垂直翻转、指定角度&#xff0c;可同时对多个形状进行操作 适合屏幕 一键设置图像、文本、形状的长宽尺寸与当前幻灯片一致 适合宽度 一键设置图像、文本、形状的宽度尺寸与当前幻灯片一致 适合高度 一键设置图像…

智能优化算法应用:基于驾驶训练算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于驾驶训练算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于驾驶训练算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.驾驶训练算法4.实验参数设定5.算法结果6.参考…

DDOS攻击方式有哪些,要如何防护

DDOS攻击我们也称之为流量攻击&#xff0c;分布式拒绝服务攻击(英文意思是Distributed Denial of Service&#xff0c;简称DDOS&#xff09;于不同位置的多个攻击者同时向一个或数个目标发动攻击&#xff0c;或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者…

Python3开发笔记(简洁版)

一、开发编辑器 1. pycharm 2. IDLE&#xff08;Python自带软件&#xff09; 方法&#xff1a;Microsoft Store搜索 Python 安装 二、数据类型 Python中有以下几种主要的数据类型&#xff1a; 数字&#xff08;Numbers&#xff09;、 字符串&#xff08;Strings&#xff09…