APM建设踩了哪些坑?去哪儿旅行分布式链路追踪系统实践

news/2024/5/5 6:40:24/文章来源:https://blog.csdn.net/shulieTech/article/details/134205853

一分钟精华速览

分布式链路追踪系统在企业的APM体系中扮演着重要的角色。本文分享了去哪儿旅行构建分布式链路追踪系统的实践经验。从APM整体架构设计入手,讲述了日志收集、Kafka传输和Flink任务处理等环节的性能优化实践和踩坑经验。

同时,作者结合丰富的分布式系统架构经验,探讨了APM系统和Trace数据的价值。通过阅读本文,你将了解到去哪儿旅行在构建APM体系中所面临的挑战,并学习如何应对这些挑战,实现更高效的性能监控和管理。 file 作者介绍

file

去哪儿旅行基础平台架构师——王 鹏 TakinTalks稳定性社区专家团成员。毕业于大连理工大学,10年以上大型分布式基础架构经验,专注于大型分布式基础架构和大数据处理领域。曾就职于58集团,主要负责58到家基础架构工作。后进入去哪儿旅行,负责分布式链路追踪系统的建设以及APM体系的搭建。在大数据、高并发的场景有丰富的经验。

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

TakinTalks稳定性社区,公众号后台回复 “交流” 进入读者交流群;回复“1012”获取课件资料;

背景

APM并不是一个新的概念。从2012年到2016年,市场上涌现了许多开源的APM组件,如SkyWalking、Jaeger等。可以说,在过去几年中,随着技术的发展和系统的复杂性增加,分布式链路追踪系统和应用性能管理(APM)已成为许多公司不可或缺的工具。

大多数公司都会根据其技术栈和业务体系来构建自己的APM体系和分布式链路追踪系统。以去哪儿旅行为例,我们的主要业务涉及搜索查询和电子商务交易等领域。由于业务体系的不同,在技术选择、方案设计方面可能存在一些差异。

在构建和应用APM体系的过程中,去哪儿遇到了许多挑战。例如,在日志收集、Kafka传输以及Flink任务处理等环节遇到了一些问题。这次会分享如何克服这些性能瓶颈,以及在这个过程中积累的经验和教训,希望这些经验对其他公司在解决类似问题时能够有所帮助。

一、APM整体架构是如何设计的?

作为一个OTA交易平台,去哪儿旅行的业务系统分为搜索和下单交易部分。从流量来看不会特别大,OTA的交易量无法与零售电商交易相比。因此,去哪儿在构建APM体系上与其他电商公司可能存在一些不同。例如,大多数公司APM的Trace部分采用采样策略,但对我们来说,每一次请求、每一次查询或者每一次交易,尤其是交易链路的Trace非常少,每天几百万的交易量,产生的Trace不会太多。因此,最终采用了交易链路全采样的技术方案。

此外,从2020年开始,全公司技术栈之前的虚拟机模式转向了云原生的开发架构。在这三年中,从应用层、开发层和容器层,都已经完成了迁移。在迁移完成后,需要将可观测性的相关体系迁移到云上,或者说适配云原生的开发环境。

在构建APM体系的早期,由于众多开源技术尚未出现,进行了大量的自研工作。例如,早期我们依赖自研的Java中间件记录Trace。但现在,开源社区已经提供了许多优秀的方案,可以根据公司环境、阶段和技术路线做出合理的选择。

经过技术分析与选型后,去哪儿旅行的APM体系采用插桩Agent模式和中间件埋点并行的方式(如图)。其中,红色部分是重点改造部分。

file

(去哪儿旅行APM体系整体架构)

首先,左上部分主要是如何记录和获取Trace信息。部分中间件以硬编码的方式获取Trace数据,另外,一些开源的第三方组件通过Agent模式获取了Trace。

其次,关于如何收集这些数据,去哪儿旅行采用了开源的Apache Flume日志收集组件,并对其进行了一系列改造。改造的原因是原生组件并未提供如配置管理功能、限流控制等一些必要的功能。

第三,处理层的任务非常繁重,选择了Flink作为数据处理任务框架。数据处理不仅需要实时处理Trace的详细数据,还需要存储并分析出的Trace异常、后置采样、链路分析等等。

最后,Metrics部分则是一个标准的收集和处理流程,通过Statsd将数据存储到时序DB,最终有Prometheus + Grafana去展示。

总的来说,去哪儿旅行的APM体系整体架构设计结合了开源技术和自研成果,以实现更高效的性能监控和管理。

二、遇到了哪些“坑”?

2.1 日志收集组件的性能瓶颈优化

在Trace数据收集过程中,确实存在许多挑战。由于许多业务和监控系统基于Trace和Metrics来判断是否发出告警,因此这种收集需要比离线日志更实时。然而,这也意味着它们需要在保持高性能的同时,保证不会影响宿主机的性能,这是一个非常大的挑战。

2.1.1 问题表现:Trace数据中断

file

在对系统进行改造前,发现有大量的Trace出现了数据中断的问题。这种问题表现为Trace的某些部分(比如Span ID为1.4和1.4.2的部分)突然消失,而后面的部分(比如Span ID为1.5)又突然出现。这种情况可能由两种原因导致,一种是中间件里没有这部分数据,另一种是中间件里有数据但是没有传送过来。无论是哪种原因,都需要对系统进行深入地分析。

2.1.2 抽样分析:日志组件和配置问题

尝试把以上问题拆解成可视化的指标,以便于理解和处理它。首先,查看了整个Trace的问题比例,可以通过图上的监控看到Trace中断率达到了惊人的70%~80%。这个结果说明大部分的Trace数据都存在问题。

file 为了进一步确定问题的原因,我们对100个问题数据进行了抽样分析。分析结果显示,有一半的问题是日志收集组件的问题,也就是Qflume组件的问题;另一部分问题则是配置问题,即没有正确配置数据收集,导致数据没有被收集到。除此之外,还存在一些其他的问题。

对于配置问题,可以通过统一刷新配置来解决。

而对于日志收集组件的问题,则需要进行更深入的分析和改造。首先需要对其内部工作流程进行了解。从左到右,这个流程图展示了日志处理过程。

file

在最左侧,业务应用通过异步队列将日志输出到磁盘文件。这个队列的长度是有限的,用来控制内存占用。如果队列满了,新的日志就会被丢弃。这就是日志丢失的一个原因。

还有其他两个瓶颈——一个是系统通过单线程同步读取日志,这个读取速度跟不上日志生成的速度。另一个是系统使用同步发送Kafka来传输日志。

2.1.3 优化效果

为了解决这些问题,采取了两个措施。首先,增加了异步队列的长度,但是也不能让它过长,以免消耗过多的内存。其次,将单线程读取改为批量读取,每次读取一个批次的日志。此外,还将同步发送改为Kafka异步发送,发送完一批日志后立马发送下一批,这样可以大大的提高吞吐量。

file

这样优化后,分钟级传输的数据量有了显著的提升,可以达到每分钟80亿甚至100亿条数据量。

2.1.4 踩坑点1:传输失败率大幅提高

问题描述: 尽管解决了日志组件的性能问题,可以快速地读取和发送数据。然而,随之而来的问题是Kafka的数据量非常不稳定,呈现出明显的波动。

file

原因分析: 在查看相关数据后,发现了一个严重问题:频繁的内存溢出(OOM)。这个问题的原因在于,优化后的日志组件以批量的方式读取数据,这会占用大量的内存。如果内存不足,就会发生OOM。

file

一种解决这个问题的方法是增大内存,但这并不是一个长久之计,因为资源有限,不能无限制地增加内存。另外,Trace日志的实时性要求并不像业务那么高,晚几秒甚至十几秒都是可以接受的,只要数据最终能够传输过去就可以。

如何解决? 解决思路是在保证高性能的前提下,对数据传输进行限流,让日志组件在一个可控的内存使用范围内高效的工作。

file

限流方案包括设定时间窗口和对单条日志大小做限制。在设定时间窗口的方法中,时间窗口是滑动时间窗口,也可以是一条日志的处理时间。比如设置时间窗口为一秒、两秒或五秒,然后规定在这个时间窗口内,限制数据传输的大小,比如不能超过200M。

尽管设置了时间窗口,但日志组件仍可能会出现OOM的问题。原因在于有些日志非常大,一条日志就有几兆甚至几十兆。这种情况虽然不合理,但却确实存在。如果遇到这样的日志传输过来,很可能会导致服务瘫痪。因此,团队还需要对单条日志的大小进行限制,如果日志过长,就需要进行截断处理。

另外,如果出现OOM,团队也需要进行断点续传的工作。不能重新传输已经传输过的Trace,因为这样会造成大量的资源浪费,且重复传输本身也是有问题的。

通过这些限制,就可以保证堆内存的使用不会超过限制,同时保持日志组件的高性能。

2.1.5 踩坑点2:接口耗时增长,吞吐量下降

问题描述:

在解决日志组件内存溢出问题之后,又遇到了新的挑战:业务线反馈接口耗时突然大幅上升,吞吐量大幅下降,甚至有些业务应用被操作系统直接终止,导致故障出现。这个问题在一开始是令人困惑的,因为已经解决了OOM的问题,并且对内存使用进行了严格的限制。怎会出现影响业务系统的情况呢?

原因分析:

在排查问题时,发现有问题的服务器上,CPU利用率非常高,达到197%,内存的使用率也非常高,几乎已经没有剩余空间。那么,这是由什么原因引起的呢?回顾之前做的优化工作,发现在优化日志传输的步骤中,将Kafka的发送操作变成了异步发送。而在异步发送过程中,会大量占用堆外内存。

之前针对堆内内存做了限制,但是对堆外内存并没有做限制。如果Kafka大量发送数据,但是由于某些原因传输不过来,那么这些数据就需要放在堆外内存中等待发送。这就是导致内存使用率高涨,最后操作系统终止业务进程。

如何解决?

那么,如何限制堆外内存的大小呢?或者说,如何限制进程使用的内存空间呢?

从Docker这个容器技术中找到了灵感。熟悉Docker都知道,Docker容器中使用的资源是固定的,包括磁盘空间、CPU以及内存等,不能超过容器在初始时分配的大小。那么,Docker是如何实现这个功能的呢?

这就涉及到CGroup技术,也就是Linux内核提供的控制组(Control Group)技术。CGroup技术主要用于限制和隔离进程组应用的物理资源,简单来说,可以通过CGroup技术将硬件资源切分成很多块,并对每一块资源设定使用限制,进程和其产生的子进程都不能超过这个限制。

通过CGroup技术,限制进程的堆外内存使用和CPU使用,保证它们都在一个合理的范围之内。

2.1.6 优化效果

CGroup进行资源限制后,系统的效率得到了显著提升。Root失败率从原来的80%降低到了20%,优化效果十分明显。

file

2.2 高并发下Kafka集群传输优化

在解决了日志收集问题,资源使用得到了限制之后,大量的日志被发送到了Kafka集群,然后Kafka集群再将日志传输给Flink任务进行处理。这就引出了新的问题:如何保证Kafka集群能够高效稳定地传输日志?

2.2.1 问题表现

随着日志收集客户端在全公司范围内的推广,大约有1万多个实例部署,Kafka集群开始出现了不稳定的情况。Kafka集群会出现大量的连接失败,整个的数据接收量和发送量都会急剧下降。在这期间并没有对集群做任何改动,收集组件也没有做任何改动,但是却频繁出现这种不稳定问题。

file

2.2.2 问题分析

通过查看了Kafka集群的监控,发现网络空闲连接和线程数急剧下降。这可能是导致Kafka集群连接失败,数据传输量下降的主要原因。

file

在Kafka的架构中,客户端首先与网络接收线程组进行连接,发送日志数据。网络接收线程组在接收到数据后,将任务转发给RequestQueue进行处理。 file

Processor处理器的主要工作是将请求放入请求通道队列(RequestChannel)。理论上,处理器的空闲量应该较大,因为其工作并不复杂,仅仅是进行内存操作,将网络接收的任务提交到队列。然而,监控数据却显示处理器的空闲数急剧下降,变得非常繁忙,并没有足够的空闲链接去处理网络请求。

进一步分析,发现请求处理器(KafkaReuestHandler)从请求通道队列中取出任务进行处理,主要是将请求写入磁盘。如果请求处理器处理不过来,请求通道队列的数据就会逐渐增多。当队列满时,新的请求无法进入,导致网络连接空闲数急剧下降。

综合以上所述,问题可能出在Kafka的请求处理器这一环节。主要可能是内存不足或者刷盘速度不够快。进一步检查后,发现确实有些机器的内存不够,有些机器的刷盘速度有问题,甚至有些磁盘已经损坏,导致部分机器的性能急剧下降。

2.2.3 优化效果

将有问题的机器从集群中移除,并增大了内存。经过这些优化,整个Kafka集群恢复了正常状态。

file

(正常状态下的集群)

优化后的效果明显,Kafka集群的收发状态保持在一个正常的水平。在约1分钟的时间里,可以收发1.7亿多条数据。而且,根据业务的波峰波谷,数据的收发呈现出稳定的状态,不再出现以前的陡增陡降的情况。

2.3 百万级QPS数据处理任务优化

在数据处理过程中,任务这一环节是最核心的部分。在对比了Spark和Flink的流式处理后,发现后者更适合Trace场景。Flink任务本身也比较复杂,如何能保证它的高可靠和高性能?

2.3.1 数据处理任务

数据存储量的QPS400w左右,峰值1000w。数据进入任务首先进行反序列化,之后开始实时计算业务线的拓扑、异常Trace拓扑、Metrics和Trace关联关系等。

file

另一个重要的任务是存储。每秒几百GB的日志存储到存储介质中,有HBase、ES、ClickHouse等存储介质。这些存储还有一些关联数据,这些关联数据需要拆分。例如,有很多Metrics和Trace的关联数据,需要先将它们解析出来,然后做分布式的存储,将它们存入数据库。这些计算都是在Flink的任务里面完成的。

2.3.2 Flink任务拆分

file

上图是一个大任务,整个数据打散后分给不同的子任务去处理。这种方式有一个问题,如果某个子任务处理速度较慢,会产生一些背压。背压会继续向上反映到总的任务分发环节。分发环节处理速度慢,所有任务的处理速度也会变慢。所以,一个小任务出问题,就导致整个链路出问题。

file

因此,将一些不关联的Trace任务进行拆分,而不是让它们耦合在一起。这样做可以大大降低问题的发生概率。

2.3.3 背压如何解决?

背压(Back Pressure)是流控制中的一种策略,主要用于保护系统在高负载情况下的稳定性。当下游处理速度跟不上,上游数据输入的速度时,就会发生背压,这就像水管出水口被堵住,压力太大后就可能会导致水管崩裂。

解决背压可以从以下几个方面着手:

观察Flink任务中子任务的消费是否均匀。Flink任务会被分解为子任务,子任务会被分配到不同的机器上执行。如果某些高耗CPU或者高耗IO的任务集中在同一台机器,会导致该机器的处理能力不足,从而影响整个任务的处理速度。因此,需要关注子任务的消费均匀性,并尝试调整资源的分配,使其更加均衡。 关注上下游算子的内存是否充足。如果输出算子的内存不足,可能会导致输入算子的数据无法正常传递。因此,需要通过内存监控,并合理设置不同算子的内存大小。 尽量使用内存的Map来替代Window。虽然Window可以保证数据的完整性,但在某些情况下,并不需要这么强的一致性,更多的时候只是对数据缓存,使用内存的Map可以极大的节省内存消耗。

善用Shared Group。Filter一定小心下游算子的拥堵导致全面的拥堵,Shared Group可以将频繁进行网络传输的算子放到一个JVM内,这样可以极大的节省网络资源和计算资源。

2.3.4 优化效果

通过优化背压问题,平均写入达到400万QPS,平均写入耗时在600ms左右,这是一个非常不错的性能表现。

file

三、如何看到APM和Trace数据的价值?

3.1 APM系统有哪些作用?

当系统经过几年的发展,可能会变得杂乱无章,各个系统之间的联系混乱不堪。在这样的情况下,可能对系统的运行逻辑一头雾水,更别说从这个混乱的拓扑中找出问题所在。而APM系统的作用就是帮助理清这些混乱的联系,然后指出可能出现问题的地方。与仅有监控系统相比,APM系统可以更清晰地定位问题所在,这是一个巨大的价值点。

file

(APM系统让查问题变得更简单)

3.2 Trace与Metrics怎么关联

在业界很多并没有关注Metrics和Trace的关联关系,常见的做法是根据时间进行随机关联。然而,这样的关联性并不强。因此,根据去哪儿的业务情况进行了一些改进。

针对三类指标进行分析:一类是Time类的指标,一类是Count类的指标,另一类是Rate类的指标。

1、Time类指标:假如一种操作的耗时是最长的,那么这种操作肯定是存在问题的。所以这类指标我们只取Top10即可。

2、Count类指标:处理方式会相对复杂一些,因为它涉及到的业务概念较多。采用了随机策略,比如在记录某个指标时,无法将所有的Metrics与Trace的关联关系全部记录下来,只需要随机抽取一部分进行记录就可以了。另外一种策略是:报警策略,假如某个指标出现报警,那么在这段时间内这个指标存在问题的概率是非常大的,所以会提高采样率,为了更可能命中存在问题的Trace。还有一种策略是:关键词策略,比如定义了一些业务异常,这种情况下,会进行全采样,因为这种Trace的价值非常大,例如ERRO FAILED EXCEPTION 等关键词。

3、Rate类指标:处理起来会更为困难。因为Rate类指标往往是两个数的比值,比如成功率和失败率。这些指标上升还好,但是如果下降,那么可能是因为没有Trace关联。所以对于Rate类指标,只能关注上升的情况。

在实际操作中,发现研发同学非常喜欢使用这个功能,因为大家只要加报警就能找到问题的Trace。以前要找这个问题的Trace就需要在日志和代码中反复查找,非常费劲。而有了这个功能,他们只需要设置一个报警,只要出现问题,他们就能找到对应的Trace,这大大节省了排查问题的时间。

3.3 Trace作为基础底座如何应用

作为一个基础功能,Trace在很多公司都有广泛的应用,可以在其基础上进行许多工作。基于Trace的高连通性,通过上下文传递来降低整个调用量。例如,在用户中心的接口中,调用量通常非常大。如果不合理在上下层或同级之间进行多次调用,用户中心的调用量就会指数级增加。

如果能够获取Trace的上下文,那么在短时间内,一个Trace内的用户数据的变化可能非常小。绝大部分数据是固定的,例如User ID。通过传递Trace的上下文,可以指数级别降低其调用量。在一个Trace内,调用次数可以被限制在几百次以内。如果通过上下文传递,只需要调用一次就够了。这种优化的方法在实际应用中是可行的,还可以结合其他的技术,比如将大量访问频繁的数据存储在缓存中,以降低信息在传输层的大小。

另外,Trace的高连通性对于混沌工程和全链路压力测试非常重要。全链路压力测试是基于Trace的连通性的。在进行灰度环境的压力测试时,不允许将整个压力施加到线上,以免造成故障。如何确保只在灰度链路内进行测试而不影响线上环境?这就是基于Trace的高连通性。高连通性意味着的链路拓扑应该是一个全连通集的子集,不允许出现调用跳转到线上的情况,如果出现则表明压力测试的拓扑是有问题,需要终止。

此外,如果出现无法覆盖整个Trace的情况,可以在网络层面进行拦截。在整个网络拓扑中,不允许请求外部的线上机器或服务。如果有请求到线上机器或服务的情况,可以进行拦截,终止压力测试。

3.4 Trace数据有哪些价值

基于Trace的连通性,通过分析Trace数据,可以了解整个链路的性能瓶颈和热点,从而给业务线提出优化建议。

基于超时时间的链路拓扑分析,发现配置不合理的点,是否有环装调用 在分布式服务中,通常使用RPC框架(如Double或GRPC)进行通信。在早期,这些框架需要手动配置节点的超时时间。例如,上游的超时配置为1秒,下游的超时配置为3秒,这是一个不合理的配置,因为上游已经在1秒之后超时了,下游的超时时间设置并没有意义。这种不合理的配置可能出现在分布式系统中的许多节点中,难以寻找和识别。

通过分析每个请求的耗时数据,可以将RPC框架的超时时间拿出来,并对上下游配置进行分析,从而发现不合理的配置。这样,可以确定哪些超时配置是不合理的,以前很难解决的问题现在可以通过链路分析发现。一旦我们找到这些点,可以避免由于超时配置不合理导致的故障。

基于请求耗时占比,分析性能瓶颈 通常情况下,某个请求中会有一个或多个函数的耗时占比非常高。 file

file

通过观察图中的Span ID,某个请求的耗时占比超过了48%。如果某个函数的耗时占比过大,这可能是由于它本身的执行速度较慢,或者它的实现方式存在问题。这个函数可能成为整个链路的瓶颈,影响整体性能。在这种情况下,可以考虑将该函数改为异步操作,或者拆分为并行的请求,以帮助业务线提高性能。

基于同层并发请求重复次数占比,分析代码不合理调用。 有时候我们会在同层中重复调用某个接口,例如在某个地方调用了应用中心,又在另一个地方调用了应用中心,然后在下一层又调用了应用中心,这种重复调用是完全不合理的。

file

在同层的情况下,这样的调用可能会达到几十次甚至上百次,这显然是没有必要的。可能有些同学会说,只是把编写好的代码复制粘贴过来,没有去分析它的逻辑,长此以往,这些重复调用会导致系统性能下降。

这些是我简单列举的一些Trace数据有价值的点,在实际过程中,它的应用价值远不止这些。也欢迎大家开放探讨和交流。

四、总结展望

在构建整个APM体系过程中,三个主要组件:日志收集组件、传输链路治理以及Flink任务性能优化。日志收集组件和传输链路治理主要解决日志大流量和并发的问题。在日志组件中,关注内部和外部内存的限制。在传输层,关注任务调度和集群性能优化。

最后,分析了APM系统的价值和意义。每家企业都建设自己的APM系统,同时更需要深入挖掘其价值。APM系统的真正意义在于能够通过数据客观深入了解系统的性能。通过APM系统,可以优化系统的性能、提高用户体验、减少故障和降低潜在风险。

Q&A

1、直播迁移到Docker 和使用CGroup 技术的成本怎么评估的?

2、如何及时发现未被监控的指标项,避免未被观测的指标突变引发故障?

3、接口偶发性超时,调用链只能看到超时接口名称,看不到内部方法,无法定位根因,也难以复现,怎么办?

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

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

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

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

相关文章

【HarmonyOS】HarmonyOS备案获取公钥和指纹

【关键字】 HarmonyOS应用、鸿蒙应用、元服务、应用备案 HarmonyOS应用在华为云等平台进行应用备案时,平台需要提供用公钥和签名指纹的信息,Android可以直接通过keystore或jks签名文件进行签名信息获取,HarmonyOS签名方式与Android不同&…

软件测试用例与分类

测试用例与分类 黑盒测试基于需求的设计方法等价类边界值判定表正交表场景设计法错误猜测法 FiddlerPostman测试用例测试分类按测试对象界面测试可靠性测试容错性测试文档测试兼容性测试易用性安装卸载测试安全测试性能测试内存泄漏测试 白盒测试灰盒测试开发阶段单元测试集成测…

IDEA项目下不显示target目录或者target目录不完整没有新添加的资源,idea隐藏target目录

文章目录 一、前言二、idea隐藏target目录2.1、idea隐藏target目录2.2、git提交时隐藏target目录 三、idea下显示target目录3.1、解决idea下不显示target目录问题3.2、target显示目录不完整 一、前言 在idea-2020.1.4版本下讲解idea怎么显示或隐藏target目录。 需要知道:如果…

P5906 【模板】回滚莫队不删除莫队

这一题,虽说在洛谷标的是模板题,但可能没有“历史研究”那一题更加模板。 这一题相对于回滚莫队的模板题,可能在回滚的处理上稍微复杂了一点。对于回滚莫队就不多解释了,可以看一下 回滚莫队模板题 这一篇博客,稍微简单…

SMT:引领新时代公链赛道的龙头之选!

近年来,区块链技术的应用越来越广泛,而公链作为区块链技术的重要组成部分,也得到了越来越多的关注。SMT公链作为新兴的公链项目,正在吸引着越来越多的关注。 SMT平台由拥有丰富金融行业和区块链技术经验的专业团队运营&#xff0…

LeetCode148.排序链表

看完题目的想法是,直接把所有节点的值都遍历出来放进优先队列里面,然后从头节点遍历一次,每次把优先队列poll()的值赋给节点的val即可,说实话,想完还觉得估计有问题怎么可能这么简单,但是不管了&#xff0c…

【gogogo专栏】golang并发编程

golang并发编程 并发编程的工具goroutine介绍协程管理器sync.WaitGroup channel介绍readChannel和writeChannelclose的用法select的用法 通讯示例总结 并发编程的工具 在golang中,并发编程是比较简单的,不像java中那么麻烦,golang天然的支持协…

Pytorch网络模型训练

现有网络模型的使用与修改 vgg16_false torchvision.models.vgg16(pretrainedFalse) # 加载一个未预训练的模型 vgg16_true torchvision.models.vgg16(pretrainedTrue) # 把数据分为了1000个类别print(vgg16_true) 以下是vgg16预训练模型的输出 VGG((features): S…

【FastCAE源码阅读6】C++与Python的集成,实现相互调用

分析FastCAE代码之前先看看C与Python如何相互调用的。 一、C调用Python 先写个C调用Python的例子&#xff0c;然后再来看FastCAE集成Python就比较简单了。直接上代码&#xff1a; #include <iostream> #include "python.h"int main() {Py_Initialize();PyRu…

uniapp+uview2.0+vuex实现自定义tabbar组件

效果图 1.在components文件夹中新建MyTabbar组件 2.组件代码 <template><view class"myTabbarBox" :style"{ backgroundColor: backgroundColor }"><u-tabbar :placeholder"true" zIndex"0" :value"MyTabbarS…

关闭EasyConnect进程详细步骤

1、不关闭导致的问题 nacos浏览器可以正常访问&#xff0c;但idea启动的时候连不上nacos&#xff0c;而且第二次启动都启动不了&#xff0c;一直卡在那里&#xff0c;排查了半天&#xff0c;怀疑是装的EasyConnect的VPN导致的&#xff0c;于是停止掉相关服务即可。但直接结束进…

Git 基础知识回顾及 SVN 转 Git 自测

背景 项目开发过程中使用的版本控制工具是 SVN&#xff0c;Git 多有耳闻&#xff0c;以前也偶尔玩过几次&#xff0c;但是工作中不用&#xff0c;虽然本地也有环境&#xff0c;总是不熟练。 最近看一本网络开源技术书时&#xff0c;下载源码部署了一下&#xff0c;又温故了一…

js调整table表格上下相邻元素顺序

有时候我们会遇到要通过箭头控制table表格上下顺序的需求,如下: 点击向下就将该元素下移一位,下面的一位元素就移上来,点击向上就将该元素上移一位,上面的一位元素就移下来,也就是相邻元素互换位置顺序: <el-table :data="targetTable" border style=&quo…

Sui发布RPC2.0 Beta,拥抱GraphQL并计划弃用JSON-RPC

为了解决现有RPC存在的许多已知问题&#xff0c;Sui正在准备推出一个基于GraphQL的新RPC服务&#xff0c;名为Sui RPC 2.0。GraphQL是一种开源数据查询和操作语言&#xff0c;旨在简化需要复杂数据查询的API和服务。 用户目前可以访问Sui主网和测试网网络的Beta版本的只读快照…

nacos的部署与配置中心

文章目录 一、nacos部署安装的方式单机模式:集群模式:多集群模式: 二、安装的步骤1、预备环境准备2、载安装包以及安装2.1、Nacos有以下两种安装方式:2.2、更换数据源数据源切换为MySQL 2.3、开启控制台授权登录&#xff08;可选&#xff09; 3、配置中心的使用3.1、创建配置信…

3.27每日一题(常系数线性非齐次方程的特解)

常系数非齐次线性方程的特解如何假设&#xff08;两种&#xff09;形式&#xff1a; 1、题目中 e 的 x 次幂以及 1&#xff0c;都是第一种&#xff1a;1可以看成为e的0次幂 注&#xff1a;题目给的多项式是特殊的形式&#xff0c;我们要设为一般的形式的多项式 2、题目中sin…

竞赛 深度学习疫情社交安全距离检测算法 - python opencv cnn

文章目录 0 前言1 课题背景2 实现效果3 相关技术3.1 YOLOV43.2 基于 DeepSort 算法的行人跟踪 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习疫情社交安全距离检测算法 ** 该项目较为新颖&#xff0c;适合作为竞赛…

搭建二维码系统,轻松实现固定资产的一物一码管理

固定资产管理中普遍存在盘点难、家底不清、账实不一致、权责不清晰等问题&#xff0c;可以在草料上搭建固定资产管理系统&#xff0c;通过组合功能模块实现资产信息展示、领用登记、出入库管理、故障报修等功能&#xff0c;对固定资产进行一物一码规范化管理。 比如张掖公路事业…

【webrtc】 对视频质量的码率控制的测试与探索

目录 环境设置 transport-cc goog-remb (webrtc中的两种码率算法&#xff09; 修改成remb算法 测试 效果 后续 可参考工程 环境设置 要到meshx上操作 telnet 112 然后执行factory_env show |grep meshx_ip 之后telnet meshx_ip 用户名admin 密码****.119 执行一下r…

self.register_buffer方法使用解析(pytorch)

self.register_buffer就是pytorch框架用来保存不更新参数的方法。 列子如下&#xff1a; self.register_buffer("position_emb", torch.randn((5, 3)))第一个参数position_emb传入一个字符串&#xff0c;表示这组参数的名字&#xff0c;第二个就是tensor形式的参数…