APM建设踩了哪些坑?去哪儿旅行分布式链路追踪系统实践
一分钟精华速览
分布式链路追踪系统在企业的APM体系中扮演着重要的角色。本文分享了去哪儿旅行构建分布式链路追踪系统的实践经验。从APM整体架构设计入手,讲述了日志收集、Kafka传输和Flink任务处理等环节的性能优化实践和踩坑经验。
同时,作者结合丰富的分布式系统架构经验,探讨了APM系统和Trace数据的价值。通过阅读本文,你将了解到去哪儿旅行在构建APM体系中所面临的挑战,并学习如何应对这些挑战,实现更高效的性能监控和管理。
作者介绍

去哪儿旅行基础平台架构师——王 鹏 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模式和中间件埋点并行的方式(如图)。其中,红色部分是重点改造部分。

(去哪儿旅行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数据中断

在对系统进行改造前,发现有大量的Trace出现了数据中断的问题。这种问题表现为Trace的某些部分(比如Span ID为1.4和1.4.2的部分)突然消失,而后面的部分(比如Span ID为1.5)又突然出现。这种情况可能由两种原因导致,一种是中间件里没有这部分数据,另一种是中间件里有数据但是没有传送过来。无论是哪种原因,都需要对系统进行深入地分析。
2.1.2 抽样分析:日志组件和配置问题
尝试把以上问题拆解成可视化的指标,以便于理解和处理它。首先,查看了整个Trace的问题比例,可以通过图上的监控看到Trace中断率达到了惊人的70%~80%。这个结果说明大部分的Trace数据都存在问题。
为了进一步确定问题的原因,我们对100个问题数据进行了抽样分析。分析结果显示,有一半的问题是日志收集组件的问题,也就是Qflume组件的问题;另一部分问题则是配置问题,即没有正确配置数据收集,导致数据没有被收集到。除此之外,还存在一些其他的问题。
对于配置问题,可以通过统一刷新配置来解决。
而对于日志收集组件的问题,则需要进行更深入的分析和改造。首先需要对其内部工作流程进行了解。从左到右,这个流程图展示了日志处理过程。

在最左侧,业务应用通过异步队列将日志输出到磁盘文件。这个队列的长度是有限的,用来控制内存占用。如果队列满了,新的日志就会被丢弃。这就是日志丢失的一个原因。
还有其他两个瓶颈——一个是系统通过单线程同步读取日志,这个读取速度跟不上日志生成的速度。另一个是系统使用同步发送Kafka来传输日志。
2.1.3 优化效果
为了解决这些问题,采取了两个措施。首先,增加了异步队列的长度,但是也不能让它过长,以免消耗过多的内存。其次,将单线程读取改为批量读取,每次读取一个批次的日志。此外,还将同步发送改为Kafka异步发送,发送完一批日志后立马发送下一批,这样可以大大的提高吞吐量。

这样优化后,分钟级传输的数据量有了显著的提升,可以达到每分钟80亿甚至100亿条数据量。
2.1.4 踩坑点1:传输失败率大幅提高
问题描述: 尽管解决了日志组件的性能问题,可以快速地读取和发送数据。然而,随之而来的问题是Kafka的数据量非常不稳定,呈现出明显的波动。

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

一种解决这个问题的方法是增大内存,但这并不是一个长久之计,因为资源有限,不能无限制地增加内存。另外,Trace日志的实时性要求并不像业务那么高,晚几秒甚至十几秒都是可以接受的,只要数据最终能够传输过去就可以。
如何解决? 解决思路是在保证高性能的前提下,对数据传输进行限流,让日志组件在一个可控的内存使用范围内高效的工作。

限流方案包括设定时间窗口和对单条日志大小做限制。在设定时间窗口的方法中,时间窗口是滑动时间窗口,也可以是一条日志的处理时间。比如设置时间窗口为一秒、两秒或五秒,然后规定在这个时间窗口内,限制数据传输的大小,比如不能超过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%,优化效果十分明显。

2.2 高并发下Kafka集群传输优化
在解决了日志收集问题,资源使用得到了限制之后,大量的日志被发送到了Kafka集群,然后Kafka集群再将日志传输给Flink任务进行处理。这就引出了新的问题:如何保证Kafka集群能够高效稳定地传输日志?
2.2.1 问题表现
随着日志收集客户端在全公司范围内的推广,大约有1万多个实例部署,Kafka集群开始出现了不稳定的情况。Kafka集群会出现大量的连接失败,整个的数据接收量和发送量都会急剧下降。在这期间并没有对集群做任何改动,收集组件也没有做任何改动,但是却频繁出现这种不稳定问题。

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

在Kafka的架构中,客户端首先与网络接收线程组进行连接,发送日志数据。网络接收线程组在接收到数据后,将任务转发给RequestQueue进行处理。 
Processor处理器的主要工作是将请求放入请求通道队列(RequestChannel)。理论上,处理器的空闲量应该较大,因为其工作并不复杂,仅仅是进行内存操作,将网络接收的任务提交到队列。然而,监控数据却显示处理器的空闲数急剧下降,变得非常繁忙,并没有足够的空闲链接去处理网络请求。
进一步分析,发现请求处理器(KafkaReuestHandler)从请求通道队列中取出任务进行处理,主要是将请求写入磁盘。如果请求处理器处理不过来,请求通道队列的数据就会逐渐增多。当队列满时,新的请求无法进入,导致网络连接空闲数急剧下降。
综合以上所述,问题可能出在Kafka的请求处理器这一环节。主要可能是内存不足或者刷盘速度不够快。进一步检查后,发现确实有些机器的内存不够,有些机器的刷盘速度有问题,甚至有些磁盘已经损坏,导致部分机器的性能急剧下降。
2.2.3 优化效果
将有问题的机器从集群中移除,并增大了内存。经过这些优化,整个Kafka集群恢复了正常状态。

(正常状态下的集群)
优化后的效果明显,Kafka集群的收发状态保持在一个正常的水平。在约1分钟的时间里,可以收发1.7亿多条数据。而且,根据业务的波峰波谷,数据的收发呈现出稳定的状态,不再出现以前的陡增陡降的情况。
2.3 百万级QPS数据处理任务优化
在数据处理过程中,任务这一环节是最核心的部分。在对比了Spark和Flink的流式处理后,发现后者更适合Trace场景。Flink任务本身也比较复杂,如何能保证它的高可靠和高性能?
2.3.1 数据处理任务
数据存储量的QPS400w左右,峰值1000w。数据进入任务首先进行反序列化,之后开始实时计算业务线的拓扑、异常Trace拓扑、Metrics和Trace关联关系等。

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

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

因此,将一些不关联的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左右,这是一个非常不错的性能表现。

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

(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框架的超时时间拿出来,并对上下游配置进行分析,从而发现不合理的配置。这样,可以确定哪些超时配置是不合理的,以前很难解决的问题现在可以通过链路分析发现。一旦我们找到这些点,可以避免由于超时配置不合理导致的故障。
基于请求耗时占比,分析性能瓶颈 通常情况下,某个请求中会有一个或多个函数的耗时占比非常高。 

通过观察图中的Span ID,某个请求的耗时占比超过了48%。如果某个函数的耗时占比过大,这可能是由于它本身的执行速度较慢,或者它的实现方式存在问题。这个函数可能成为整个链路的瓶颈,影响整体性能。在这种情况下,可以考虑将该函数改为异步操作,或者拆分为并行的请求,以帮助业务线提高性能。
基于同层并发请求重复次数占比,分析代码不合理调用。 有时候我们会在同层中重复调用某个接口,例如在某个地方调用了应用中心,又在另一个地方调用了应用中心,然后在下一层又调用了应用中心,这种重复调用是完全不合理的。

在同层的情况下,这样的调用可能会达到几十次甚至上百次,这显然是没有必要的。可能有些同学会说,只是把编写好的代码复制粘贴过来,没有去分析它的逻辑,长此以往,这些重复调用会导致系统性能下降。
这些是我简单列举的一些Trace数据有价值的点,在实际过程中,它的应用价值远不止这些。也欢迎大家开放探讨和交流。
四、总结展望
在构建整个APM体系过程中,三个主要组件:日志收集组件、传输链路治理以及Flink任务性能优化。日志收集组件和传输链路治理主要解决日志大流量和并发的问题。在日志组件中,关注内部和外部内存的限制。在传输层,关注任务调度和集群性能优化。
最后,分析了APM系统的价值和意义。每家企业都建设自己的APM系统,同时更需要深入挖掘其价值。APM系统的真正意义在于能够通过数据客观深入了解系统的性能。通过APM系统,可以优化系统的性能、提高用户体验、减少故障和降低潜在风险。
Q&A
1、直播迁移到Docker 和使用CGroup 技术的成本怎么评估的?
2、如何及时发现未被监控的指标项,避免未被观测的指标突变引发故障?
3、接口偶发性超时,调用链只能看到超时接口名称,看不到内部方法,无法定位根因,也难以复现,怎么办?
以上问题答案,欢迎点击“阅读全文”,观看完整版解答!
本文由博客一文多发平台 OpenWrite 发布!
相关文章:
APM建设踩了哪些坑?去哪儿旅行分布式链路追踪系统实践
一分钟精华速览 分布式链路追踪系统在企业的APM体系中扮演着重要的角色。本文分享了去哪儿旅行构建分布式链路追踪系统的实践经验。从APM整体架构设计入手,讲述了日志收集、Kafka传输和Flink任务处理等环节的性能优化实践和踩坑经验。 同时,作者结合丰…...
ASTM F963-23美国玩具安全新标准发布
新标准发布 2023年10月13日,美国材料与试验协会(ASTM)发布了新版玩具安全标准ASTM F963-23。 主要更新内容 与ASTM F963-17相比,此次更新包括:单独描述了基材重金属元素的豁免情况,更新了邻苯二甲酸酯的管控…...
swift语言下SurfGen库做的爬虫是什么样的 ?
Swift语言并没有内置的爬虫库,但是你可以使用第三方库来实现爬虫功能。其中比较常用的是Alamofire和SwiftyJSON。Alamofire是一个基于Swift语言的HTTP网络库,可以用来发送HTTP请求和接收HTTP响应。而SwiftyJSON则是一个用于处理JSON数据的Swift库&#x…...
Vue纯CSS实现掷色子
效果图: 实现代码 直接利用CSS3动画实现的效果,无js代码。 <template><div class"wrap"><input type"checkbox" id"roll"><label for"roll"><div class"content"><…...
使用vscode开发uniapp项目常用的辅助插件,提升开发效率
为什么不使用hbuilder开发呢?因为hbuilder对ts和vue3语法支持并不友好,而且代码提示不智能,也不能使用最近很流行的coplit和CodeGeex智能提示,所以就换掉hbulider,使用我们熟悉的vscode开发吧。 第一个:un…...
python脚本监听域名证书过期时间,并将通知消息到钉钉
版本一: 执行脚本带上 --dingtalk-webhook和–domains后指定钉钉token和域名 python3 ssl_spirtime.py --dingtalk-webhook https://oapi.dingtalk.com/robot/send?access_tokenavd345324 --domains www.abc1.com www.abc2.com www.abc3.com脚本如下 #!/usr/bin…...
那些看起来高大上的封装函数
什么 ToGray 只支持3通道图像, 让我看看怎么个事 就这么生硬的加了个判断 好家伙 调用了下opencv ,通道数都不判断一下...
go语言 | grpc原理介绍(三)
了解 gRPC 通信模式中的消息流 gRPC 支持四种通信模式,分别是简单 RPC、服务端流式 RPC、客户端流式 RPC 和双向流式 RPC。 简单 RPC 在gRPC中,一个简单的RPC调用遵循请求-响应模型,通常涉及以下几个关键步骤和组件: 请求头&a…...
记一次heapdump泄漏获取服务器权限
文章目录 一、漏洞原因二、漏洞利用三、漏洞进一步利用1、工具下载2、通过关键字查询3、通过配置redis的默认账号和密码进行登录4、添加定时计划任务,进行反弹shell5、成功获取服务器的shell补充四、总结五、免责声明一、漏洞原因 扫描目录发现某个spring框架存在大量泄露信息…...
大疆Livox MID-360安装ROS1/2驱动 Ubuntu20.04
文章目录 一、接线连接二、安装上位机可视化工具三、安装ROS驱动3.1 配置静态IP3.2 安装Livox SDK23.3 安装ROS驱动3.4 驱动 本文介绍如何在Ubuntu20.04中安装大疆Livox MID-360的ROS1/2驱动 一、接线连接 livox航插一分三线,其中航空母头连接激光雷达,…...
Android 重启App
要重启 Android 应用程序,可以使用 PendingIntent 和 AlarmManager 来实现。下面是一种实现方式: fun restartApp(context: Context) {val packageManager context.packageManagerval intent packageManager.getLaunchIntentForPackage(context.packa…...
C语言的前置知识:数据量单位、汇编语言和寄存器
数据量单位 位(bit)是计算机中最小的存储单位,每一位可以存储一个二进制码值的0或1。而字节(byte)则通常是由八个位组成的一个存储单元。在计算机中,字节是最小的可寻址单位,这意味着 CPU 在使…...
【IDEA】在工具栏设置快速创建包和类的图表
页面效果: 操作步骤: 设置 --> 外观与行为 --> 菜单与工具栏 --> 点击 主工具栏 --> 点击 ---- --> 点击 号 --> 添加操作 主菜单 --> 文件 --> 文件打开操作 --> 打开项目操作 --> 新建 --> 往下找 找到 clas…...
int arrayL = sizeof(array) / sizeof(array[0]);
我有一个四个元素的doublearray,这里我会得到4还是5? 在C或C中,使用 sizeof(array) / sizeof(array[0]) 来计算数组的长度是一种常见的方法。但是,这种方法只适用于在同一作用域中声明的数组,而不适用于函数参数传递的…...
FFmpeg——使用Canvas录制视频尚存问题的解决方案
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
css进阶知识点速览
0前言 零基础部分的博客 1选择器进阶 1.1后代选择器 作用:根据html标签的嵌套关系,选择父元素后代中满足条件的元素 选择器语法:选择器1 选择器2 {css} 结果: 在选择器1所找到标签的后代中 注意: 后代包括…...
P2047 [NOI2007] 社交网络
Portal. 观察到数据范围 n ≤ 100 n\leq 100 n≤100,考虑用 Floyd。 在 Floyd 更新最短路的过程中,如果以当前结点为中转点的路径更新过,那么可以累加答案;否则,更新最短路径并重置答案。 统计答案时,枚…...
线性表的顺序存储
1.创建:实质是对data与length的修改 //定义一个线性表 typedef struct {int data[MaxSize];//存储线性表的元素 int length;//线性表的长度 }SqList; //新建一个表 void create(SqList &l){//传入地址才可以对其值进行改变 printf("请输入线性表的长度&…...
ChinaSoft 论坛巡礼 | 安全攸关软件的智能化开发方法论坛
2023年CCF中国软件大会(CCF ChinaSoft 2023)由CCF主办,CCF系统软件专委会、形式化方法专委会、软件工程专委会以及复旦大学联合承办,将于2023年12月1-3日在上海国际会议中心举行。 本次大会主题是“智能化软件创新推动数字经济与社…...
采用XML作为GUI描述语言
设计方案采用XML作为GUI描述语言的机制主要包括以下几个方面: 模型定义:使用XML定义GUI组件的模型,包括组件的名称、类型、属性、事件等。布局管理:使用XML定义GUI组件的布局,包括组件之间的相对位置、大小、对齐方式等。数据绑定:使用XML定义GUI组件的数据绑定方式,包括数据来…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
