微服务拆分的原则、时机、方法以及常见问题
前言#
在平常情况下,技术架构会随着业务规模大小、团队人数多少、技术债积累速度等动态变化。当然,引起架构变化最主要的因素还是业务发展速度。
在以前的单体架构到微服务架构演进历程 文章2 等文章中,有一张架构演进的图,如下:
(巨型单体到微服务架构的演进)
这张架构演进图,说明了架构的变化和演进的总方向。演进到微服务架构,它中间有几次架构变迁和发展的过程。
当然,这张架构演进图有一个缺憾,大单体应用架构后面缺一张模块化的单体架构图,也就是说把大单体拆分为模块化的大单体。
上面图中最后面的微服务架构图,里面有很多服务,也叫微服务(拆分为更小的服务)。关于拆分也有很多问题,可以用 5W1H、6why 思考法不断追问思考:
- 为什么要进行微服务拆分?
- 这些微服务要怎么拆分?如果要拆分,按照什么原则拆分?按照什么策略拆分微服务?
- 拆分成多小算合适的微服务?
- 微服务边界如何确定?
- 什么时候进行微服务拆分合适?
等等一系列的问题都是拆分微服务时我们需要思考的问题。
为什么要进行拆分(划分)#
为什么要进行微服务拆分,前面的文章也有讲解,微服务的优势和劣势 文章2 。微服务的优势优点:
- 快速编译,一个微服务代码量更小,易编译部署
- 维护性变高,单个微服务功能少,代码量减少,可快速修改发布,因为每个团队独立负责一块功能。新功能交付变快,可以快速开发与交付,可独立部署
- 扩展性变高,根据业务规模可以随时缩减/增加服务器规模,因为是独立的微服务模块
- 可靠性变强,可以部署很多独立的服务
- 业务边界清晰,按照不同业务功能拆分为多个独立的服务
- 研发效率提升,业务拆分后,服务模块变小,在一个团队内就可以独立编写、测试、发布,加快研发效率。
- 技术异构,满足不同的业务需求。
等等好处。当然拆分后,同样带来了很多挑战,在 微服务的优势和劣势 一文中也有讲解。
微服务拆分的原则有哪些#
为了更加合理的拆分微服务,在拆分微服务过程中需要遵循一些基本原则。
1、单一职责原则#
这个原则不仅在拆分微服务时会遵循,在很多软件设计中也遵循此原则。
单一职责原则指的是一个微服务只负责一个明确的业务能力,专注于做好一件事情。一个服务的内部变化不影响另外一个服务。
比如在电商系统中,订单服务只处理订单生命周期,支付服务只处理支付流程,商品服务处理商品流程。
2、高内聚,低耦合#
高内聚:
产品功能和职责相关度较高的集中在一起,服务内的功能是紧密相关的,数据和行为集中。
服务间尽量减少依赖。
低耦合:
各微服务之间独立存在,尽可能减少彼此依赖,服务间通过 API 或异步事件(比如用 REST API 或 消息队列来通信)来进行服务之间的交互通信,各自数据存储独立。
3、单向依赖#
微服务之间应该避免双向依赖、环形依赖。因为这样会导致服务间关系更加复杂,服务升级影响的服务过多,故障的概率变大。
如果遇到了怎么处理:
- 1、将共同依赖的服务单独出来,做成第三方服务。通用能力下沉。
- 2、异步解耦,比如引入消息中间件来处理。
4、数据库隔离#
每个微服务独立管理自己的数据,拥有自己独立的数据库,避免与其它服务直接共享数据库或数据存储。这样是为了避免共享数据而导致的耦合。但也增加了数据一致性管理的问题。
如果需要共享数据,通过 API 或事件与其它服务交换数据。
但是在拆分过程中往往因为业务的聚合查询需求,有时会为聚合查询独立建立一个数据存储系统。这时要注意多分析业务需求和技术选型匹配情况。
5、康威定律#
微服务划分应该与团队组织结构相匹配,确保团队的独立和自治,减少团队间的耦合工作,降低跨团队协作成本。
一个团队负责一个或多个微服务,不仅做到服务开发自治,而且每个微服务尽量独立自治没有过多依赖,一个微服务功能尽可能在一个团队内完成。
6、演进式原则#
微服务的拆分并不需要一步到位,它是一个渐进的过程,应该根据业务发展情况选择合适的架构风格然后进行拆分。
逐步拆分,持续演进。应该避免一下子拆分太多的服务带来架构复杂度急剧升高。
我们把大单体应用拆分为微服务架构时,可以分阶段分步骤进行拆分。
比如先垂直拆分为多个应用,再把每个应用拆分为比较大的模块,再把大的模块进一步拆分为小的服务。
比如可以先进行粗粒度的划分,然后在根据业务发展、研发情况的需要在进行更细粒度的拆分。
比如可以先从不太重要的业务功能进行服务拆分的实践,然后逐步推广。
比如可以先从最容易拆分的部分开始,如将日志服务或配置服务拆分为独立的微服务,然后逐步拆分其他部分。
中间还可能因为服务拆分过细,会进行服务的合并,合并为更大粒度的服务。所以微服务的拆分有时会是一个反复的过程。
“合久必分,分久必合”。
引入微服务架构和服务拆分的时机#
微服务拆分的时机,其实就是什么情况下引入微服务架构比较合适。我前面有几篇文章可供参考:
-
微服务架构学习与思考(05):微服务架构适用场景分析 一文中的微服务适用场景和什么时候引入微服务的考量因素 2 小节内容
-
微服务架构学习与思考(02):微服务实施的前提条件?有哪些问题需要思考?
-
小公司需要使用微服务架构吗?
划分微服务的时机,什么时候引入微服务架构合适,其实是需要综合考量:
- 第一:业务发展阶段
- 第二:业务复杂度
- 第三:开发人员情况
- 第四:业务形态
具体情况请看上面的 3 篇文章。
微服务拆分的维度和方法#
微服务拆分维度可以从:
-
1、业务、技术、数据、组织结构 这 4 个大维度进行思考。
-
2、功能性 和 非功能性 维度,这个跟上面 1 差不多,功能性纬度就是业务功能、技术功能(比如消息推送系统、监控系统),非功能性一般与技术紧密相关(比如扩展性、高性能、安全性、技术异构等)。
业务维度#
从业务纬度来划分业务领域,界定好业务领域边界。
第一种拆分方法:业务功能和业务流程的分析来进行业务领域的划分#
根据业务功能和业务流程的分析来进行业务领域的划分,从而达到划分微服务的目的。
根据业务流程和功能来划分业务领域。这需要我们熟悉整个业务全貌,每个业务功能,功能的流程 - 业务核心流程、子流程等。如果不熟悉,就需要进行业务分析。
业务分析的一般方法,比如下面这 3 种:
-
场景分析法:从业务的场景入手分析。
-
用例分析法:从处理业务的角色入手分析。
-
流程分析法:从业务流程入手分析。比如从 A 到 B,要经过哪些步骤,先做什么,后做什么,有什么规则。
其中场景分析法和用例分析法有点相似,都是各种角色在各种场景下进行作业或活动的交互过程,区别是入手分析角度不同,一个是场景角度,一个是角色角度。
业务和流程分析完,就要进行业务领域的划分。
比如:大家熟悉的电商购物流程:
用户浏览商品 -> 点击购买 -> 加入购物车(或直接支付) -> 支付 -> 生成订单
根据这个购物的流程,可以划分为用户域、商品域、订单域、支付域等业务领域。
第二种拆分方法:根据DDD领域驱动设计来进行业务领域的划分#
在 DDD(领域驱动设计)方法中,有一些关于对复杂业务领域进行分析的相关概念:
- 领域、核心域、通用域、支撑域、子域
- 界限上下文(Bounded Context)
- 上下文映射(Context Mapping)
- 统一语言(Ubiquitous Language)
- 实体、值对象、聚合、聚合根、领域对象、领域服务
- 领域建模
这些概念对于业务领域的划分能够起到指导作用。当然还需要结合 DDD 领域驱动设计里的其他概念一起使用。
要做好业务领域的划分,最重要的是要建立领域模型。
领域模型是对某个有边界的业务领域的一个抽象,反映了业务、领域内用户和用户活动,不涉及技术。领域模型确保了领域内的业务逻辑都在一个模型内。
怎么建立领域模型,领域建模常用的方法有哪些?
-
事件风暴(Event Storming)
-
四色建模
-
用例分析法
事件风暴介绍
事件风暴是一种以工作坊的方式对复杂业务进行分析探索的高效协作方法,通过快速、可视化的方式梳理业务逻辑,识别领域事件、命令、聚合等关键元素。它起源于 DDD,旨在通过跨职能团队的高效协作快速探索复杂业务逻辑,构建领域并划分系统边界。
“风暴”是让软件开发者和领域专家们聚集在一起进行业务分析的头脑风暴,进行交流讨论。它是以 “领域事件” 为中心来分析梳理业务流程,建立领域模型。
事件风暴通过不同颜色的便签(或卡片)来区分元素,事件风暴的一些核心概念:
-
领域事件:已发生的业务事实,发生有意义的业务事件。以 “名词 + 动词被动式” 命名,反映业务状态变化。例如:订单已创建
-
命令:触发事件的动作。通常由用户或系统事件触发。以“动词+名词”命名 。例如:提交订单
-
聚合/聚合根:业务逻辑的集合,包含实体和值对象,维护业务规则的一致性。例如:订单聚合(含订单详情、用户信息等)
-
外部系统:与当前系统交互的外部依赖,如第三方服务。例如:短信平台
-
执行者:触发命令的主体,与系统交互的人,可以是用户、系统或定时任务。例如:用户、支付网关
-
读模型:支持决策的信息视图,为执行者提供所需的数据。例如:订单追踪视图(显示状态、时间)
-
策略:业务规则,定义事件触发时响应逻辑,可能生成新的命令。例如:支付成功后通知用户
-
界限上下文:业务领域的边界,划分不同领域模型的范围,通常对应微服务边界
可以看出这里的概念和DDD中的很多概念相似或相同。
事件风暴实施的简易步骤:
1、准备工作:
- 参与者:领域专家、开发人员、产品经理等,业务和技术相关人员参加
- 工具:多种颜色便签、白板、白板笔
- 场地:会议室墙面,便于协作和可视化流程
2、识别领域事件
- 流程:团队围绕业务流程头脑风暴,列出关键事件,按照时间轴来排列
- 规则:事件需要满足 “已发生”“影响业务状态变化”等条件,需排出技术事件或查询操作
3、关联命令与执行者
- 为每个事件标注触发命令(比如用户已注册),并确定执行者(比如用户、系统等)
- 处理异常或相反的情况,讨论产品发生失败的场景,比如支付失败
4、划分界限上下文与聚合
- 界限上下文:根据业务语义将事件分组(如用户管理、订单处理),形成独立领域
- 聚合设计:从命令和事件中提取名词(比如“订单” “用户”),组合为聚合,确定聚合根的边界
5、构建领域模型
- 细化模型:定义实体、值对象、领域服务,验证模型是否支持所有业务流程
- 输出:上下文映射图、通用或统一语言表
其余的 2 个建模方法,四色建模和用例分析,读者可自行了解。
第三种拆分方法:根据业务稳定性、变动频率#
在业务系统中,区分变和不变的部分。
不变的部分,就是稳定性相对来说比较高,可以作为通用的服务。
将频繁变动的部分也可以独立出来,作为独立的服务。
比如电商系统中的用户信息、商品信息等模块一般稳定性高。而运营类的活动和页面变动比较频繁。
第四种拆分方法:核心业务和非核心业务#
核心业务就是主要的服务,保证高可用,非核心业务遇到堵塞时可以降级处理。
这是一种比较大的粗略的划分方法,可以作为服务划分的一种思考角度。
有的也叫链路服务中的主链路服务(核心业务的服务流程)、次级链路服务。
比如电商系统:搜索商品 -> 查看商品详情 -> 加入购物车 -> 下单结算 -> 支付服务,这就是一条商品交易的主链路服务,也是商品交易最核心的服务流程,必须高可靠的运行。
比如订单查看详情就是非核心业务。
技术纬度#
如果从技术维度来划分,有哪些纬度可以考虑呢?
从高性能、可靠性、完全性、扩展性、异构性、通用性、稳定性等方面来进行考虑。
还可以技术为业务提供的功能,比如消息推送系统、分布式缓存系统、监控系统等,当然这些都是比较大的系统。
高性能
将性能要求高或性能压力大的功能或模块进行拆分,避免因为性能影响其它服务,造成整个链路服务的阻塞。
比如电商应用中瞬间访问量特别大的系统:抢购系统、秒杀系统等系统。
可靠性
将可靠性要求比较高的功能或模块进行拆分,并定义为核心服务,与链路中其它非核心服务隔离开,保证核心服务的高可用性。
比如电商应用的用户购物流程中,商品交易是核心服务,交易后的查看订单详情可以作为非核心服务。商品交易的核心服务提供高可用性。
通用性
将多数业务经常用到的功能进行提炼,独立为基础服务、通用性的服务。
比如微服务中的限流、鉴权、隔离、日志收集、安全等功能。
还有一些比较大的通用性的系统,比如消息推送系统、缓存系统、监控系统等。
稳定性
将变动不大的服务、比较稳定的服务拆分为独立的服务,或频繁变动的服务也可以作为独立的服务。
组织结构纬度#
这个是拆分的纬度是根据,康威定律:
“设计系统的组织,其产生的设计等同于组织之间的沟通结构。”
简单来说,一个公司的软件架构往往会反映该公司的组织结构。例如:
- 如果一家公司有多个独立的团队各自开发业务功能模块,最终的系统可能是多个独立模块服务的组合(如微服务架构,它也可以理解为用技术的手段匹配组织协作方式)。
- 如果一家公司是一个高度集中的团队,系统可能倾向于单体架构。
> 康威定律强调:“如果你想改变系统架构,应该先调整组织结构。”
微服务团队人数通常控制在「两个披萨团队」(6-10人),微服务的开发、测试、部署、运行都可以在一个团队内完成,微服务自治,微服务团队也独立、自治。
数据纬度#
这个数据纬度联动业务拆分,数据随着业务拆分而拆分,拆分的业务有自己独立的数据库。
微服务拆分过程中常见问题#
1、服务粒度拆分过度、过细#
微服务“微”字,这个汉字容易让人想到很小的服务,这个“微”字只是一个形容服务粒度大小的形容词,它的含义可以是 小、中、大,拆分的服务必须与技术、业务发展、团队相适配。
问题:
在微服务拆分过程中,如果过度追求“微”,将单一类或简单的功能都拆分为独立的服务,会导致大量的小型服务,服务数量会爆炸,部署、调试、维护都将变得复杂,运维成本激增,跨服务调用频繁、性能下降、团队要维护服务数量多等等问题。
服务拆分过粗,未能解耦相关业务领域,单个服务臃肿,难以独立扩展。
必须平衡好服务拆分粒度与系统复杂性之间的关系。
解决方法:
-
1、遵循高内聚原则:避免服务拆分过细,一个服务应覆盖一个完整的业务领域、业务子域。
-
2、逐步拆分和迭代改进:不必一次性拆分完成,可以从比较大的粒度开始拆分然后在演进到合适的小的粒度、或从非核心业务开始拆分,并及时的反馈调整。
2、跨服务共享数据或代码#
问题:
拆分的多个服务直接读取同一个数据库表或共享代码库(比如公共 JAR 包),导致高耦合,破坏了服务的独立性和服务自治。
解决方法
- 1、独立数据库:每个服务独立拥有自己的数据库,数据隔离。
- 2、API访问数据:如果需要其它服务数据,通过 API 获取数据或事件订阅获取数据。
3、过早拆分或盲目的采用微服务架构#
问题
不是所有的系统都适合微服务架构。在业务需求不明确或业务发展规模还不大情况下,过早引入微服务,会造成业务交付变慢、团队负责服务数量过多造成团队负担等问题。
解决方法
-
1、渐进式拆分:一般从单体起步,渐进式拆分。大单体->多个应用->微服务架构。
-
2、引入微服架构的时机:看上面的一节:引入微服务架构和服务拆分的时机。
4、分布式单体(服务边界划分不清)
问题
服务虽然物理上分离了,但是逻辑上高度耦合,如共享数据、频繁同步调用,导致部署依赖多,失去了微服务的独立部署和扩展优势,维护成本不降反而增加。
解决方法
-
1、采用领域驱动设计 DDD:在拆分服务前,采用 DDD,通过领域建模和业务流程梳理,明确服务的边界和职责,确保服务自治。
-
2、异步通信:使用事件驱动(如Kafka)解耦服务,减少直接依赖。
5、一次性拆分和忽略架构演进
问题
试图一步到位完成所有服务的拆分,或拆分后就以为万事大吉,不需要进行适当的调整了。因为后续业务会有变化,团队规模会有变化,可能导致服务边界失效。
解决方法
- 1、演进式拆分:从核心业务开始(如电商的订单、支付),逐步细化。或从非核心业务开始实践。
- 2、绞杀者模式:在旧系统外围逐步构建新服务,逐步替换旧功能。
相关文章:
微服务拆分的原则、时机、方法以及常见问题
前言# 在平常情况下,技术架构会随着业务规模大小、团队人数多少、技术债积累速度等动态变化。当然,引起架构变化最主要的因素还是业务发展速度。 在以前的单体架构到微服务架构演进历程 文章2 等文章中,有一张架构演进的图,如下…...
第十八天 - ELK日志体系集成 - 自定义Logstash插件 - 练习:分布式日志分析平台
前言 在分布式系统和微服务架构中,日志管理是监控系统健康、排查故障的核心环节。ELK(Elasticsearch、Logstash、Kibana)作为业界领先的日志分析解决方案,能够实现日志采集、处理、存储与可视化的全链路管理。本文将手把手带你掌…...
HBuilderX中uni-app打包Android(apk)全流程超详细打包
一、Android生成打包证书 1、Android平台签名证书(.keystore)生成指南_android 签名生成-CSDN博客(如果不上架应用商店可以跳过,可以使用云端证书) 二、打开manifest.json配置基础设置 三、配置安卓应用图标 四、配置安卓启动页图片 五、…...
CTF web入门之命令执行
web29 文件名过滤 由于flag被过滤,需要进行文件名绕过,有以下几种方法: 1.通配符绕过 fla?.* 2.反斜杠绕过 fl\ag.php 3.双引号绕过 fl’‘ag’.php 还有特殊变量$1、内联执行等 此外 读取文件利用cat函数,输出利用system、passthru 、echo echo `nl flag.php`; ec…...
安宝特案例 | 某户外机房制造企业应用AR+作业流,规范制造过程,记录施工节点,保障交付质量
行业特点:产品客制化、依赖人工,工程量大、细节多,验收困难 户外通讯机房无疑是现代工业社会的“信息心脏”,承载着信息交换、传输与处理的重任。建设一座质量过关的户外通讯机房是保障通信稳定运行的基石。 通常建设一个户外通信…...
学习MySQL的第八天
海到无边天作岸 山登绝顶我为峰 一、数据库的创建、修改与删除 1.1 引言 在经过前面七天对于MySQL基本知识的学习之后,现在我们从基本的语句命令开始进入综合性的语句的编写来实现特定的需求,从这里开始需要我们有一个宏观的思想&…...
ESP8266 采集 DHT11 和 DS18B20 温湿度数据 MQTT 上传至 Home Assistant
ESP8266 采集 DHT11 和 DS18B20 温湿度数据 MQTT 上传至 Home Assistant DHT11 采集 DHT11 温湿度数据并通过 MQTT 联网上传至 Home Assistant 智能家居平台; Arduino 代码 #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <Ardui…...
三、TorchRec中的Optimizer
TorchRec中的Optimizer 文章目录 TorchRec中的Optimizer前言一、嵌入后向传递与稀疏优化器融合如下图所示:二、上述图片的关键步骤讲解:三、优势四、与传统优化器对比总结 前言 TorchRec 模块提供了一个无缝 API,用于在训练中融合后向传递和…...
操作系统 4.1-I/O与显示器
外设工作起来 操作系统让外设工作的基本原理和过程,具体来说,它概括了以下几个关键步骤: 发出指令:操作系统通过向控制器中的寄存器发送指令来启动外设的工作。这些指令通常是通过I/O指令(如out指令)来实现…...
Qt 5.14.2 入门(三)基本知识理解
目录 一、新建项目后生成的三个文件的作用和内容1、.h文件:头文件(如mainwindow.h)2、.cpp文件:源文件(如mainwindow.cpp)3、main.cpp:主程序 二、信号和槽机制1、信号(Signal)2、槽(Slot)3、连…...
Java中常见的设计模式
Java中常见的设计模式 Java 中有 23 种经典设计模式,通常被分为三大类:创建型、结构型和行为型。每个设计模式都解决了不同类型的设计问题。以下是几种常见设计模式的总结,并附带了实际应用场景、示例代码和详细的注释说明。 一、创建型设计…...
nltk 是怎么和 Transformers(比如 BERT 模型)联动来处理文本的
🧠 一句话解释nltk: nltk 是一个用于自然语言处理(NLP)的 Python 库,功能包括分词、词性标注、命名实体识别、文本分类等。 全称是:Natural Language Toolkit(自然语言工具包) &…...
项目日志配置模板示例
1.新增application.properties配置 logging.configclasspath:logback-spring.xml spring.profiles.activedev 将项目部署到服务器时需要将dev修改为test后再进行打包部署 2.新增logback-spring.xml <?xml version"1.0" encoding"UTF-8"?> <…...
sql server统计小时数据中每日最大风速及风速对应的风向
客户提出一个需求,有历年逐小时的风速、风向资料,想获取历年最大的风速及风速对应的风向值,通过sql 怎么实现,这个统计,我认为主要考虑一个问题,就是数据重复性,所以我采用以下方法实现…...
【SQL】MySql常见的性能优化方式
MySQL性能优化的常用方式及对比说明 一、引言二、MySQL性能优化的常用方式及对比说明1. 索引优化1.1 合理创建索引1.2 覆盖索引1.3 索引下推 2. SQL语法优化2.1 避免低效操作2.2 分页优化2.3 JOIN优化 3. 配置与架构优化3.1 参数调优3.2 读写分离与分库…...
Prometheus实现负载均衡并将多个实例数据汇总到一个主Prometheus
一、Prometheus实现负载均衡策略原理 要实现 Prometheus 的负载均衡并将多个 Prometheus 实例的数据汇总到一个主 Prometheus 实例中,可以结合 Prometheus 联邦(Federation) 和 负载均衡器 来进行配置。 这种方法的核心是在主 Prometheus 实例…...
力扣 — — 最长公共子序列
力扣 — — 最长公共子序列 最长公共子序列 题源:1143. 最长公共子序列 - 力扣(LeetCode) 题目: 分析: 一道经典的题目:最长公共子序列(LCS) 题目大意:求两个字符串的最长公共序列。 算法&…...
通过AWS EKS 生成并部署容器化应用
今天给大家分享一个实战例子,如何在EKS上创建容器化应用并通过ALB来发布。先介绍一下几个基本概念: IAM, OpenID Connect (OIDC) 2014 年,AWS Identity and Access Management 增加了使用 OpenID Connect (OIDC) 的联合身份支持。此功能允许…...
GNSS静态数据处理
1 安装数据处理软件:仪器之星(InStar )和 Trimble Business Center 做完控制点静态后,我们需要下载GNSS数据,对静态数据进行处理。在处理之前需要将相关软件在自己电脑上安装好: 仪器之星(InS…...
NVIDIA H100 vs A100:新一代GPU架构性能对比分析
一、核心架构演进对比 Ampere架构(A100)采用台积电7nm工艺,集成540亿晶体管,配备6,912个CUDA核心和432个第三代Tensor Core,支持FP16、TF32和INT8精度计算。其显存子系统采用HBM2e技术,80GB版本带宽可…...
AI图像生成
要通过代码实现AI图像生成,可以使用深度学习框架如TensorFlow、PyTorch或GANs等技术。下面是一个简单的示例代码,演示如何使用GANs生成手写数字图像: import torch import torchvision import torchvision.transforms as transforms import …...
计算机考研一战上岸宁波大学经验分享
目录 话不多说先上分数 个人介绍 政治 英语二 数学二 408 复试 话不多说先上分数 初试排名15/65 复试79.81分,复试排名13/65 总成绩13/65,研招网招考50人 (均为公开数据,非泄露复试信息) 个人介绍 本人山东…...
泛微ECOLOGY9 记 数据展现集成 自定义开窗测试中对SQL 的IN语法转换存在BUG
背景 搭建流程时,需将明细表1中的合同字段 供明细表2中的合同开窗查询使用。 最终实现如下图: 选择 发票号时,自动带出明细表1中的采购合同号清单,然后在明细表2中开窗采购合同号时,只跳出明细表1中有的采购合同号&am…...
【Nginx】Nginx代理Tomcat配置及404问题解决
当Tomcat返回HTTP 404未找到错误时,可以通过以下两种方式设置跳转到指定地址: ① 在Tomcat应用内部配置错误页面跳转(直接修改Tomcat的Web应用配置) ② 在Nginx反向代理层拦截404错误并跳转(无需修改Tomcat,…...
【Vue】案例——To do list:
【Vue】案例——To do list: 一、案例介绍:二、效果展示(如图)三、主要功能:四、技术要点:补充:【Vue】Vue模板语法(点击可跳转)补充:【Vue】数据绑定(单双向)…...
JVM不同环境不同参数配置文件覆盖
背景 需要在启动Java服务并且参数不同的场景,例如端口号在yml中的配置是这样的: server:port: 9100 覆盖配置对应JVM参数: java -jar xxxx.jar -Dserver.port12306 [JVM其他参数] 这样12306就会覆盖掉9100端口的配置作为启动配置 IDE…...
游戏引擎学习第215天
总结并为今天做铺垫 今天的工作内容是解决调试系统中的一个小问题。昨天我们已经完成了大部分的调试系统工作,但还有一个小部分没有完全处理,那就是关于如何层次化组织数据的问题。我们遇到的一个问题是,演示代码中仍有一个尚未解决的部分&a…...
C语言--求n以内的素数(质数)
求n以内的素数,可以用试除法或者埃拉托斯特尼筛法(埃氏筛法) 输入:数字n 输出:n以内所有的素数 不管是哪个方法,都有一个数学结论可以减少循环次数: 如果有一个数不是质数,那么它至…...
多版本go冲突问题
今天执行go build时遇到一个报错: compile: version “go1.22.7 (Red Hat 1.22.7-1.moduleel8.10.0700fd5cfc7a)” does not match go tool version “go1.23.4” 结果一查 which -a go 发现 当前系统居然有四个不同的位置都安装了go 于是先看go version…...
Windows 10系统出现无法使用键鼠的问题
有一位系统之家的小伙伴在升级Windows 10系统电脑的时候,出现键盘鼠标不能正常工作打问题,其实,遇到这个问题,有时只需重新启动计算机或断开连接并重新连接鼠标或键盘可以提供帮助,如果没有,可以看看下面系…...
NFC 数据传输
前言 初次接触NFC协议,很多人都会感觉困惑,搜索相关资料,大多数都介绍协议的理论及应用领域,数据传输的内容却很少,但对与开发人员来说,除了理论知识外,数据传输也是非常重要环节,尤…...
基于Streamlit的智能创业计划生成器开发实践
一、应用概述 在数字经济时代,创业者亟需高效工具进行系统化的商业规划。本文介绍的智能创业计划生成器基于Streamlit框架构建,整合了财务建模、时间轴规划、智能文档生成等核心功能。该工具通过模块化设计实现了九大创业要素的系统化配置,显…...
蓝桥杯单片机刷题——按键控制距离显示精度
设计要求 驱动超声波传感器,启动距离测量功能,并将其结果显示到数码管上,距离数据单位为m。 按键“S4”定义为“切换”按键,通过此按键切换距离的显示精度(一位或两位小数)。切换顺序如图所示。 数码管显示格式如下图…...
c++拷贝构造函数(深浅拷贝)+运算符重载
1拷贝构造函数 1.1定义 只有一个形参,且该形参是对本类类型对象的引用(一般用const 修饰),在用已经存在的类类型对象穿件新对象是由编译器自动调用。(是一种特殊构造,即初始化一个一模一样的新对象&#…...
操作系统 3.5-内存换入-请求调页
案例分析内存换入 内存换入分析: 内存换入(Swapping)是指操作系统将不常使用的内存页从物理内存(RAM)移动到磁盘上的交换空间(Swap Space),以释放物理内存供其他进程使用。当需要访…...
stm32工程,拷贝到另一台电脑编译,错误提示头文件找不到cannot open source input file “core_cm4.h”
提示 cannot open source input file “core_cm4.h” ,找不到 [ core_cm4.h ] 这个头文件 . 于是我在原电脑工程文件里找也没有找到这个头文件 接下来查看原电脑keil的头文件引入配置,发现只引入了工程文件下的头文件, 那么core_cm4.h到底哪里来的? (到现在我也不清楚怎…...
使用platformio如何定位hard fault错误
这里写自定义目录标题 前言过程记录结语前言 hard fault是单片机开发过程中经常会遇到的问题,通常是内存溢出、野指针访问等导致,对于有经验的工程师,在代码改动不大的情况下,一般可以通过代码审查定位到问题原因,但也有很多情况下需要借助调试工具进行定位,像Keil就有比…...
全局异常处理器的基本使用
那使用全局异常处理器可以么? 是的,使用全局异常处理器是一个非常好的选择,因为它可以将异常处理逻辑集中化,避免在 Service 层或 Controller 层中重复编写异常处理代码。以下是使用全局异常处理器来处理添加用户时 username 唯一…...
python入门:简单介绍和python和pycharm软件安装/学习网址/pycharm设置(改成中文界面,主题,新建文件)
Python 目前是 AI 开发的首选语言 软件安装 python解释器 官网下载 Python |Python.org 勾选 Add python.exe to PATH 将python.exe添加到PATH 勾选这个选项会将Python的可执行文件路径添加到系统的环境变量PATH中。这样做的好处是,你可以在命令行中从任何位置直…...
众趣科技助力商家“以真示人”,让消费场景更真实透明
在当今的消费环境中,消费者权益保护问题日益凸显。无论是网购商品与实物不符、预定酒店民宿与图文描述差异大,还是游览景区遭遇“照骗”,这些问题不仅让消费者在消费和决策过程中倍感困扰,也让商家面临信任危机。 消费者在享受便…...
【Redis】string类型
目录 1、介绍2、底层实现【1】SDS【2】int编码【3】embstr编码【4】raw编码【5】embstr和raw的区别 3、常用指令【1】字符串基本操作:【2】批量操作【3】计数器【4】过期时间【5】不存在就插入 4、使用场景 1、介绍 string是redis中最简单的键值对形式,…...
EPLAN许可证更新教程
随着电气设计软件的不断更新和优化,确保您的EPLAN许可证始终是最新版本对于顺畅的项目管理至关重要。本文将为您提供一份详尽的EPLAN许可证更新教程,帮助您轻松完成更新操作,确保您的软件始终保持最佳状态。 一、为什么需要更新EPLAN许可证&…...
学习笔记五——Rust 控制流全解析
📚 目录 什么是控制流?Rust 有什么特别?if 表达式完整语法loop / while / for 三种循环写法match 表达式 _ 通配符深入解释if let 表达式用法与场景Option、Some、None 全面通俗讲解 "Tom" 和 "Tom".to_string() 有啥本…...
远程桌面协议(RDP)详解:原理、优势与局限和优化方案分享
文章目录 导言一. RDP的工作原理二. RDP的优势三. RDP的局限性四. RDP的优化与替代方案五. 内网穿透远程访问总结 导言 远程桌面协议(RDP)是一种微软开发的专有协议,允许用户通过网络连接到另一台计算机,并像操作本地计算机一样进行操作。它广泛应用于远…...
Linux 系统管理常用命令
以下是 Linux 系统管理常用命令 的详细介绍,涵盖 IP地址查看、端口管理、进程监控 等核心操作,并附上实际示例: 一、查看网卡 IP 地址 1. 使用 ip 命令 # 查看所有网络接口信息(包括 IP 地址) ip addr show# 查看特定…...
蓝桥杯篇---客观题
文章目录 前言 前言 本文简单介绍了蓝桥杯中客观题各个部分的知识点。 一、单片机相关 IAP15F2K61S2单片机的定时器0具有4种工作模式,当采用外部12MHz晶振时,定时器最大定时长度65535us。8051单片机的P0口,当使用外部存储器时它是一个传输低…...
RK3568 基于Gstreamer的多媒体调试记录
文章目录 1、环境介绍2、概念理清3、提前准备4、GStreamer编译5、GStreamer基础介绍6、视频播放初体验7、视频硬编码7.1、h2647.2、h265 8、视频硬解码8.1、解码视频并播放解码视频并播放带音频 1、环境介绍 硬件:飞凌ok3568-c开发板 软件:原厂rk356x …...
ZYNQ笔记(五):AXI GPIO 中断
版本:Vivado2020.2(Vitis) 任务:使用 AXI GPIO IP 核以中断方式实现按键 KEY 控制 LED 亮灭翻转(两个都在PL端) 目录 一、介绍 二、硬件设计 三、软件设计 四、效果 一、介绍 AXI GPIO 中断通常…...
C++23 多维下标运算符:探索 P2128R6 提案
文章目录 一、背景与动机二、语法与实现2.1 语法2.2 实现方式 三、应用场景3.1 多维数组3.2 自定义数据结构3.3 并行计算 四、性能影响4.1 编译时优化4.2 自定义数据结构的优化 五、总结 C23 引入了许多新特性,其中之一便是多维下标运算符(P2128R6&#…...
原理图设计准备:页面栅格模板应用设置
一、页面大小的设置 (1)单页原理图页面设置 首先,选中需要更改页面尺寸的那一页原理图,鼠标右键,选择“Schmatic Page Properties”选项,进行页面大小设置。 (2)对整个原理图页面设…...