如何做到人均告警减少 90%?B 站新一代告警平台的设计与实践

一分钟精华速览

B 站的业务规模和用户群体不断扩大,对于服务的稳定性和可用性的要求也日益增高。这就需要 B 站的监控告警系统能够及时、准确地发现和定位问题,以便尽快解决,维护好用户的使用体验。

本文是对 B 站在告警监控系统上的一次重要迭代和优化的详细记录。文章详细阐述了 B 站对告警平台设计思路和优化迭代,以及在实现过程中遇到的问题和解决方法。特别是对于告警定位的精准性和定位效率的提升,文章给出了新的设计方案和实践方法。

file

作者介绍

file

哔哩哔哩资深开发工程师——王程田

TakinTalks 稳定性社区专家团成员,哔哩哔哩资深开发工程师。2020 年加入 B 站先后负责事件平台,链路追踪,AIOps 及告警平台方向技术演进 &平台迭代。完成了新一代告警平台落地,达成了 99 分位一分钟内的异常端到端发现,实现了人均告警从每周 1000+条/人到 70+条/人告警治理上的突破。

温馨提醒:本文约 6000 字,预计花费 8 分钟阅读。

TakinTalks稳定性社区后台回复 “交流” 进入读者交流群;回复“1130”获取课件;

背景

在 B 站的多元化业务中,告警平台起着至关重要的作用。无论是视频播放、弹幕发送、用户评论、直播间管理,还是后台的内容审核、数据统计等,都离不开系统的稳定运行。告警平台可以实时监控这些业务系统的运行状态,一旦出现异常,就会及时发出告警示,使运维人员能够迅速定位问题,及时进行处理。

然而,维护这些业务的稳定运行并非易事。从告警发生的前、中、后三个阶段,即生产端、传输端和消费端来看,B 站的告警平台设计都面临着不小的挑战和复杂性。 file

考虑到这些业务需求和复杂度,我们着手对 B 站新一代告警平台进行了全面升级,结果达成了人均告警减少 90%,根因分析准确率高达 87.9%的突破。在本文中,我将概述新一代告警平台的设计理念,并重点分享该平台在告警降噪和告警智能化分析方面的实施策略。

一、告警平台做了哪些重点设计?

1.1 业务核心诉求

在告警平台的设计和迭代过程中,我们不断收到各类业务需求。总体上,这些需求的核心都集中在“以质量为中心,及时发现并处理异常,确保业务稳定性”。具体来说,需求场景可划分为风险场景和故障场景。在风险场景中,需要提前感知并有效应对潜在问题;而在故障场景中,需要迅速发现线上问题,及时响应,以实现快速恢复。

在满足这些业务需求的过程中,我们提炼出三个核心诉求和目标:

有效性:我们期望所有收到的告警都是有效的,即每次接收到告警时,都确实存在异常,而且这条告警对当前的接收者是具有意义的。

及时性:对于高优先级的异常,我们希望能在第一时间触达并被用户感知,以便他们能够及时采取行动进行处理。

覆盖性与跟进:我们期望实现告警的全面覆盖和跟进。从用户的角度来看,他们希望所有自己负责的业务或应用的场景都能被告警覆盖,同时,他们也希望能了解不同场景的告警覆盖情况。当规则产生异常后,用户需要有一个便捷的方式去快速处理并跟进解决问题。

1.2 告警平台详细设计

1.2.1 闭环模型

在告警平台的详细设计中,我们基于前述的目标和业务需求,构建了一个闭环模型。这个模型旨在保证各关联方的积极参与,从而推动目标的持续改善。特别的,告警定义和告警治理是模型中的两个关键环节,因为它们决定了告警降噪和召回效果的优劣。 file

接下来将详细介绍 B 站告警定义、检测、通道侧功能的设计。重点是告警处理、根因分析以及告警治理侧的实践内容。

1.2.2 告警接入

在告警接入环节,主要区分了三个场景,这些场景的设计可以覆盖业务对于告警接入的大部分需求。

1)面向平台的场景

我们为平台覆盖的告警场景提供告警规则和模板的开放接口能力,支持多租户规则集成。不同租户可以基于预定义的模板进行配置,可以在业务申请或者注册资源时,快速完成告警的定义和覆盖,整个过程成本低,便捷性高。

2)面向自定义场景

我们为业务直接开放告警规则定义,包括规则的触发条件配置、表达式及通知策略的配置。

3)面向第三方事件

我们开放事件集成能力,用户可以通过注册事件完成准入,主动触发方式发送到告警平台,告警平台完成后续闭环的处理。

1.2.3 告警计算

我们设计了一个分布式的告警计算引擎,实现了多级的调度。基于线上全量生效的规则,进行全局调度,将告警的场景、可用区调度到不同的可用区和计算集群下。在同一个计算集群下,进行本地调度,将任务调度到不同的计算节点,实现负载均衡。计算节点会周期性地检测数据判断告警是否触发,触发后将投递到告警通道。 file

1.2.4 告警通道

主要做降噪、渲染、分发,以实现准确的投递和快速的触达。对于引擎侧产生的告警事件,在通道会生成告警消息,然后先经过降噪模块,依次完成通知窗口拦截、通知频率拦截、接警拦截、静默拦截、抑制拦截、告警聚合等。接下来,经过告警渲染分发模块,完成渲染接收人、渲染通知通道、渲染通知模板,最终触达到用户并更新告警的投递状态。 file

二、告警治理有哪些实践心得?

下面我将主要阐述 B 站在告警治理的实践过程中,如何推行告警治理策略,降低告警噪声,以及提高告警的有效性。

2.1 告警治理背景

过去一段时间里,B 站的告警通知泛滥问题,对技术团队和平台来说,这已经成为一个多年的困扰,也是一个较大的痛点。一方面,随着稳定性问题的出现以及新平台的接入,告警规则和配置不断增加;另一方面,又缺乏有效的告警治理和运营分析机制。这导致告警数量越来越多,很多用户也不会去主动治理告警,反而选择设定免打扰。最后,真实的风险和异常往往被淹没在众多告警中,无法第一时间被感知到。

用一句话来概括,就是“太多的告警就相当于没有告警”。

2.2 问题分析

我们认为,这主要由以下四部分原因导致:

告警定义不合理:很多规则缺乏有效的维护,大量的规则在触发后,并不代表有异常发生,业务也不会去处理。此外,有些告警的粒度太细,导致同一异常触发后产生大量的告警,放大了整个通知的影响。

通知人数放大:由于历史组织架构的变更或临时排查问题,定位权限相耦合,导致服务树长期缺乏治理,造成告警通知人数的大幅度放大,经常发给一些无关的人员。

缺少分析治理工具:虽然大家都知道告警太多了,需要治理,但是却没有头绪,也没有合适的平台能力帮助他们分析告警主要集中的部分,从而进行有针对性的治理。

缺乏有效的运营机制:大家对治理告警的动力不足,同时也缺乏有效的机制和规范约束。在历史上可能经过一些短期治理后,告警又出现反弹,治理效果就不复存在。

2.3 告警治理的三个阶段

在分析了告警泛滥的原因后,我们开始了告警治理,这个过程主要分为三个阶段。 file

第一阶段:目标设定

经过多轮的会议和讨论,我们确定了告警数的指标,将原先每周超过 1000 条的告警数量降低到每周 80 条。这个目标在初始阶段看起来几乎是不可能完成的。然而,我们认为这 80 条告警是一个业务人员能够逐条响应处理的合理范围。于是,我们坚持以这个目标去执行,并尽力去达成。

第二阶段:数据分析

我们将告警数据集成到数据仓库中,提供了多维度的分析视图,为告警治理提供了数据支持。通过计算公式来确定影响因子,公式基于告警通知数量,即:告警通知数量=告警数每次触发通知的人数降噪系数。这个公式帮助我们明确了治理的方向和重点。

第三阶段:治理动作

在这个阶段,我们开始执行一系列治理动作。

首先,优化了告警项,与 SRE 和平台同事一起评估了默认告警项的合理性,对无效的告警项进行了关闭处理。对于一些不合理的告警项,我们评估并优化了其表达式和默认阈值等条件,以降低告警噪声并提高告警的有效性。

其次,为了解决通知人数放大的问题,优化了告警接收人的设置。我们深度参与并推动了服务树研发和负责人角色的校准,并推出了值班,升级等能力,以缩小告警的通知范围,有效地降低了通知人数放大的噪声。

最后,丰富了通道的告警降噪策略,支持了规则组的微调拦截能力,以及多维度下的告警汇总和聚合能力,从而更高效降低了告警噪声。

2.4 告警治理过程经验总结

在进行了一系列的告警治理行动后,我们对治理过程进行了总结和思考。主要从以下三个方面进行分享:

1)异常召回是底线

在整个治理过程中,集中处理的主要是无效的噪声告警,然而,绝不能忽视真实且有效的告警。在治理中,我们始终坚守一个原则,即不能牺牲异常的召回率。因此,我们将注意力集中在那些持续触发、重复触发以及异常放大等不合理的规则上,以及 Top 级别的规则上,并对这些问题进行专项治理。

2)运营推进不可少

实际上,治理过程就是一个运营推进的过程。在这个过程中,创建了数十个群组,制定了无数的治理、推进和跟进文档,以确保整个密集且强制性的告警治理工作的落实。同时,也与各个场景平台以及 SRE 进行了紧密合作,共同推动了告警治理工作。

3)分层分级抓重点是方向

我们借鉴了毛剑老师的理念,强调分层分级,抓住重点,尤其是保证业务可用性的核心告警。对于事件类的告警,建议记录并可查询,以避免淹没其他重要的告警通知。对于一些不适合直接通知业务侧的依赖告警,建议通过关联的方式来呈现,这样可以有效地降低告警的噪声。

2.5 告警治理效果

近半年地推式的告警治理,告警数据得到显著改善:

中位数告警 1000 次/周减少到 74 次/周,减少到原来的 7.4%;

整体告警通知数从治理前 300w+减少到 22w+,减少到原来的 7%;

人均告警通知数从 1600+减少到 140,减少到原来的 8.8%; file

2.6 建立长效治理机制

为了确保告警治理所取得的成果能够持续稳定,我们构建了一套长效治理机制,具体包含以下三个方面:

1)便捷治理分析工具

包含了一个告警治理分析大盘,它被集成在告警平台上。这个大盘支持从业务、个人和公司等多个视角,通过多个维度对告警的分布和趋势进行分析。此外,我们还利用了一些治理工具,为快速治理提供了必要的能力。

2)数据报表订阅

我们与 SRE 各个组件平台达成了共识,制定了共同的目标,并生成了各类数据报表的订阅。持续跟进这些报表,以防止告警的恶化,并持续进行告警治理。 file

3)接入管控

针对新接入的规则和平台场景,增加了一些告警数据接入的人工校验,以及平台侧的校验和噪声监控。对于一些不合理的规则,我们会建议对应的接入方进行优化,以保持告警治理成果。

三、告警根因分析是如何设计和应用的?

结合当下业界广泛运用的前沿技术,例如异常检测、智能降噪、智能合并策略以及根因分析等,我将重点分享 B 站在根因分析方面的实践和实战经验。

3.1 根因分析背景

随着 SLO 体系的日益完善,更多的业务被接入到 SLO 体系中。这使得我们有了明确的异常定义和触发对象,能够更精确地实施根因分析。

此外,B 站已经设定了 “1-5-10” 的目标。目前,已经通过优化告警计算采集和通道,实现了 99 分位端到端一分钟内的问题发现。然而,对于 5 分钟的定位,仍存在一些瓶颈。定位过程过于依赖人工经验,存在一定的不确定性。人工专家经验因人而异,同时受场景影响,导致定位效率也不一致。另外,由于平台能力的建设和交互,以及一些极端情况下的响应延时,如凌晨故障或者出差等场景,都会影响定位效率。

最后,用户需求的积累也在不断增加。随着业务和基础设施的增长,人们越来越关注告警定位的效率,并积累了大量定位告警的经验。因此,对于根因分析的需求日益迫切,同时,根因分析的实施条件也逐渐成熟。

3.2 根因分析设计

3.2.1 根因分析设计 1.0 版

首先,我们采用了以 SLO 告警为基础的设计方案,对微服务架构下的黄金指标进行定位能力的设计,这就是 1.0 版根因分析设计。整个设计方案主要包含三个阶段。 file

首阶段,我们监听 SLO 的告警触发,关联错误的范围和数据,然后基于这些数据分析日志指标,挖掘出异常的维度。例如,错误可能集中在特定集群的某个实例下,或者某个上游请求的某个接口。

第二阶段,我们根据这些错误维度,对应用侧的链路调用进行关联,找出异常期间的异常链路。通过聚合分析,能区分出耗时和错误的场景,通过关键路径分析和剪枝下钻的方式,定位到异常链路下的异常节点。

最后一阶段,将定位到的异常节点映射到知识图谱中,通过数据图谱关联到相关的数据库、缓存、消息队列、容器、机器、交换机、机柜、机房等信息。然后,结合异常、告警、变更等信息,通过关联分析模型进行打分推荐,最终推荐出可能的 Top 根因排序。

尽管这个 1.0 版的根因分析设计在某些场景下的准确率可以接受,但是它仍然存在一些瓶颈。

file

3.2.2 根因分析设计 2.0 版

在设计 2.0 版的根因分析时,我们进行了全面的调研,深入了解了业界资深的 SRE 和业务同事们在定位问题时的过程。

总结下来,这个过程主要是:在告警触发后,根据专家的经验,关联到具体的异常事件;然后再根据这些经验,分析这个异常可能由哪些原因导致,并找出这些原因的相关指标和日志等观测数据;最后,通过观察这些数据,判断出导致异常的根源。

在设计 2.0 版的过程中,我们力求将这个过程普遍化,并构建一个异常知识图谱,将专家的经验沉淀下来。同时,也开放了根因分析的集成和知识目录的功能,提供通用的根因分析能力。

file

file

根因分析的实现主要围绕知识的定义。这里的知识主要是基于异常节点定义。每个异常都会定义在具体的某个实体节点下,例如某个应用或某个数据库的集群实例。每个异常都会关联到具体的数据节点,比如日志、指标、告警等,通过这些数据我们可以检测和判断异常的发生。同时,异常之间也存在传导关系,一个异常可能由哪些异常导致,这些异常之间的传导链路和关联关系是怎样的。这就是我们在知识工程中定义的整个知识结构。

这种基于知识图谱的根因分析方式,很好地解决了 1.0 版中遇到的问题。使我们能够更深入地理解异常发生的原因,更准确地定位到问题的根源。通过将专家的经验进行系统化的沉淀,不仅提高了问题定位的效率,也使得知识的传承和积累成为可能。

3.2.3 AIOps 算法支持

根因分析的能力建设,离不开 AIOps 算法的支撑。目前,我们已经构建了一个全面的算法体系,设计了指标、日志、事件、链路等多个场景。同时,也根据不同类型的数据,支持了时序预测、异常检测、指标分类以及日志聚类、多维下钻,和事件聚类、链路分析等多个场景的算法能力。 file

3.2.4 关联分析模型升级

在关联分析的过程中,我们将异常图通过特征构建、模型加载,基于模型推理预测并打分,最终推荐出异常的根因和传导路径。特征设计包括:时间依赖特征、图关系/距离特征、因果特征、路径相似特征、事件类别特征。

模型构建方面,在初期主要是基于冷启动的方式,预定义了一些异常之间的传播系数。随着样本标注数据的增多,开始进行模型的训练,并基于模型进行推理和推荐。此外,我们也支持 GBDT 模型,以进一步提升关联分析能力。

file

3.3 难点和重点

在根因分析的过程中,我们面临着一些难点和重点。难点主要在于,如何有效评价推荐的根因,以及如何获取用户的准确率和评价数据。这对于评估不同版本,以及根因分析的准确率和有效性,以及帮助模型进行迭代至关重要。为了解决这个难题,我们进行了以下四部分工作:

file

在整个过程中,一个重点是围绕专家经验的收集和构建。我们会与不同业务和 SRE 同学深度沟通,梳理相关的异常知识和专家经验,完成这部分知识的定义。

对于组件方面,我们会与相关同学持续完善这部分知识的定义和构建能力。针对一些特殊场景,也会提供外部专家经验的集成方案,提供根因分析的集成能力和接口,让外部的根因也可以通过分析能力完成,实现人工告警的推荐、展示和评价。

3.4 案例分析

3.4.1 上游流量突增导致服务限流,可用率下降

在这种情况下,可以基于告警关联到具体服务的 SLO 异常,并且下钻得到具体的异常接口和错误。同时,通过异常关联分析可以检测到上游的流量突增,明确具体哪一个入口的流量突增。有了这些信息,业务侧可以对上游的服务进行一些限流的配置并进行修复。

file

3.4.2 下游变更导致服务异常影响网关接口可用率

可以通过根因分析关联到具体的链路,并关联到具体下游的异常和变更。最终,可以推荐出 AI 服务的变更是影响网关接口的主要原因。业务同学可以快速找到对应的变更人,然后进行排查和回滚等止损操作。

file

3.4.3 下游 Redis 请求异常影响服务接口

可以通过内部分析以及异常关联到具体的服务,并构建起异常的传导路径。同时,可以推荐出具体的异常请求耗时和日志。此外,业务侧也可以与相关组件的同学一起进行更深入的定位。

file

3.5 效果评估

根因分析已经落地,并取得了一些成效——

根因分析次数:20652/天

准确率:87.9%

召回率:77.5%

分析耗时 95 分位:10s

平均分析耗时:4s 内(这意味着,在告警发出后,平均仅需 4 秒钟就可以推荐出根因,业务人员打开告警卡片就可以直接看到对应的异常根因。)

file

四、总结与展望

设计告警平台时,需要考虑到多种多样的业务需求和不同的应用场景。理解这些需求的本质,然后基于这个本质来构建平台的能力以及关键功能模型,并设计出闭环逻辑,以此来设计出更贴近业务需求的告警平台。其次,告警治理过程是必不可少的。无论告警的数量多少,只有通过完善的告警治理机制,才能使整个系统的闭环优化规则的定义,持续提升告警的有效性,发挥告警的价值。最后,告警与人工智能的结合是未来的发展趋势。通过深度结合的一些能力,可以提升故障发现的准确率,减少定位和恢复止损的时间,为质量管理和系统稳定性提供保障。(全文完)

Q&A:

1、这个告警治理是否主要靠人力筛选减少规则?

2、业务侧的告警关联降噪可以举个例子吗?是在监控侧关联还是在告警侧关联?业务告警可以和基础告警关联吗?

3、告警后有进一步的自动分析场景吗?

4、监控告警通知的发送状态和效果怎么管理?怎么处理通知失败或异常的情况?

5、在告警合并方面,高优告警怎么不被淹没?同时保证低优告警的质量巡检?

6、怎么优化根因分析的效率和准确性,来支持实时分析和批量处理呢?根因分析过程中,大量的数据和日志信息怎么管理和存储?有哪些最佳实践和经验可以分享?

以上问题答案,欢迎点击“阅读全文”,观看完整版解答!

声明:本文由公众号「TakinTalks 稳定性社区」联合社区专家共同原创撰写,如需转载,请后台回复“转载”获得授权。

本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

小红书可观测 Metrics 架构演进,如何实现数十倍性能提升?

在当前云原生时代,随着微服务架构的广泛应用,云原生可观测性概念被广泛讨论。可观测技术建设,将有助于跟踪、了解和诊断生产环境问题,辅助开发和运维人员快速发现、定位和解决问题,支撑风险追溯、经验沉淀、故障预警&a…

MATLAB图解傅里叶变换(初学者也可以理解)

1、概述 相信很多人对于傅里叶变换可能觉得比较复杂和有点难懂,其实不难,它只是一种积分变换。 傅里叶变换,表示能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。也就是说&qu…

『 Linux 』进程地址空间概念

文章目录 🫙 前言🫙 进程地址空间是什么🫙 写时拷贝🫙 可执行程序中的虚拟地址🫙 物理地址分布方式 🫙 前言 在c/C中存在一种内存的概念; 一般来说一个内存的空间分布包括栈区,堆区,代码段等等; 且内存是…

Notes2024节气和日历来了

大家好,才是真的好。 还有三周就是2024年了。 2024的节假日安排其实早就发布,有些人已经把这些节假日安排都写在自己的日历上了;同时我们这里也设置了一份,包括节假日和农历二十四节气以及中西传统的节日日期等。 如果你需要的…

均匀分布的随机变量

如果连续型随机变量的概率密度满足如下公式: 那么就称在区间(a,b)上服从均匀分布,记为。

国际语音呼叫中心有什么功能特点?

国际语音呼叫中心的功能特点 智能客服 国际语音呼叫中心通过智能客服系统,可以为客户提供快捷、高效的服务。可以根据客户需求,自动回答部分常见问题,提高客户服务效率。 个性化定制 国际语音呼叫中心平台可以根据客户需求,为…

el-tree搜索的使用

2023.12.11今天我学习了如何对el-tree进行搜索的功能,效果如下: 代码如下: 重点部分:给el-tree设置ref,通过监听roleName的变化过滤数据。 default-expand-all可以设置默认展开全部子节点。 check可以拿到当前节点的…

线程安全集合类

文章目录 1. ConcurrentHashMap2. LinkedBlockingQueue 阻塞队列3. ConcurrentLinkedQueue4. CopyOnWriteArrayList JDK1.7 hashmap采用数组加链表头插的方式,在扩容时会出现循环死链问题,A->B->C扩容后C->B->A AB BA出现循环死链。 1. Conc…

msvcp140.dll丢失怎么办?这些方法值得一试

小编将探讨计算机系统中MSVCP140.DLL文件的重要性及其潜在的问题和相应的修复措施。此文件对实现软件应用的特定功能起着关键性的作用,当其丢失时,某些运行环境下的应用程序和游戏便无法正常运作。因此,了解并解决相关问题非常必要。 一、msv…

SpringBoot Maven 项目打包的艺术--主清单属性缺失与NoClassDefFoundError的优雅解决方案

Maven项目的Jar包打包问题-没有主清单属性&&ClassNotFoundException 与 NoClassDefFoundError 文章目录 Maven项目的Jar包打包问题-没有主清单属性&&ClassNotFoundException 与 NoClassDefFoundError1、问题出现1.1、Jar包运行:没有主清单属性解决方…

如何在Python控制台中运行程序

一、打开cmd,并进入程序所在的目录 这里可以先进入要运行的程序所在的目录,然后在地址栏输入cmd并回车,就可以打开cmd并定位到当前目录。 二、在控制台中运行程序 python hello.py运行结果就会打印出来了

【运维】Kafka高可用: KRaft(不依赖zookeeper)集群搭建

文章目录 一. kafka kraft 集群介绍1. KRaft架构2. Controller 服务器3. Process Roles4. Quorum Voters5. kraft的工作原理 ing 二. 集群安装1. 安装1.1. 配置1.2. 格式化 2. 启动测试2.1. 启功节点服务2.2. 测试 本文主要介绍了 kafka raft集群架构: 与旧架构的不…

Unity | Shader基础知识(第六集:语法<如何加入外部颜色资源>)

目录 一、本节介绍 1 上集回顾 2 本节介绍 二、语法结构 1 复习 2 理论知识 3 Shader里声明的写法 4 Properties和SubShader毕竟不是一家人 三、 片元着色器中使用资源 四、代码实现 五、全部代码 六、下集介绍 相关阅读 Unity - Manual: Writing Surface Shaders…

jpa 修改信息拦截

实现目标springbootJPA 哪个人,修改了哪个表的哪个字段,从什么值修改成什么值 import jakarta.persistence.*; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; im…

死锁(JAVA)

死锁在多线程代码中是非常严重的BUG,一旦代码中出现死锁就会导致线程卡死。 当单个线程连续两次对同一个对象进行加锁操作时,如果该锁是不可重入锁就会发生死锁(线程卡死) 两个线程两把锁,如果出现这种情况也是会发生…

逻辑回归代价函数

逻辑回归的代价函数通常使用交叉熵损失来定义。这种损失函数非常适合于二元分类问题。 本篇来推导一下逻辑回归的代价函数。 首先,我们在之前了解了逻辑回归的定义:逻辑回归模型是一种用于二元分类的模型,其预测值是一个介于0和1之间的概率…

【产品设计】零代码核心模块之一:表单

在数字化越来越高级、越来越智能的场景下,信息收集依旧是适用场景最为丰富的方式之一。 应用开发工作台开三大核心模块:表单、流程、报表。 表单:一般适合数据录入,专人管理,如:用户调研、产品入库&#x…

项目篇 | 图书管理系统 | 图像加载与绘制

项目篇 | 图书管理系统 | 图像加载与绘制 基本介绍 首先解释清楚什么叫图像加载与绘制,意思就是说项目中需要用到一些图片资源(各种图标),我们要在图书管理系统中展示这些图片,就需要先导入图片到项目中,再加载图片资源(通过资源路径)、绘制图片(即展示)。 注:如果…

商业印刷市场分析:预计2029年将达到53004亿元

商业印刷技术显示了强大的生命力。电子商务的扩张性发展,传统的商务印刷行业也在逐渐的转型。中国印刷业已深度融入全球印刷加工产业链,为国际社会超过50个国家提供印刷包装服务。数据显示,中国印刷业对外加工贸易额已达842亿元。 商业印刷是…

【无标题】C++ STL -->模拟实现vector

这篇文章将模拟实现vector类的常用函数 vector类的函数接口 namespace ding {template<class T>class vectot{public:typedef T* iterator;typedef const T* const_iterator;//Member functionsvector(); vector(size_t n, const…