拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
作者:陈承
背景
在 2018 年的 2 月,ARMS Java Agent 的第一个版本正式发布,为用户提供无侵入的的可观测数据采集服务。6 年后的今天,随着软件技术的迅猛发展、业务场景的逐渐丰富、用户规模的快速增长,我们逐渐发现过去的功能以及架构的设计逐渐难以合理、优雅的满足今天的需求,重构越来越多的被提及,但总是缺少一个合理的契机。
适时,OTel 项目异军突起,其社区经过短短四年的发展,活跃度位列 CNCF 第二,逐渐成为可观测领域的开源标准。OTel(OpenTelemetry)是一个位于云原生计算基金会(CNCF)的开放源代码项目,旨在标准化遥测数据的收集、处理和导出的方式。其贡献者由来自不同公司和组织的成员组成,他们共同协作创建和维护用于分布式追踪、指标和日志的 API、SDK 和工具。他们的目标是使可观测性更加易于访问并整合到云原生软件开发中,从而使用户能够更有效地监控、调试和优化他们的应用程序。
这些现象也极大的引起了我们的兴趣, 促使我们对 OTel Java Agent 进行了一次深入的调研。
关于 OTel Java Agent
首先我们对比了 OTel Java Agent 和 ARMS 现有探针在 Tracing、Metrics、Logs、Profiling 以及其他五个方面的功能差异,如下表所示。可以看到,简单的从功能层面来说,OTel Java Agent 依托社区广大的贡献者,在插件数量上远远领先。此外,基于一些领先的埋点技术,对于各种异步场景支持较好;ARMS 探针则依托广大的商业化用户场景和多年服务集团内外客户的经验,在采样、多协议支持、指标丰富度以及各种三方功能集成方面比较领先。
除了上面列举的功能对比,在对 OTel Java Agent 调研中,我们也发现他有很多领先的设计在解决埋点生效判断、异步、类隔离等问题时十分方便。这里简单介绍一下他的几个比较领先的设计。
muzzle-check 机制
编译时收集我们埋点代码中访问了被增强类的哪些方法、字段。在运行时,如果待增强类没有相应的方法和字段,则不执行增强动作,避免增强代码报错;在平时,可以对待增强类的所有版本执行静态检测,获得支持版本列表。
VirtualField 机制
JVM 的字节码增强机制有一些限制,对于已加载类的增强,只能修改方法体,不能给类新增字段。这个限制对于我们影响较大,因为在 APM 的场景下,往往有较多的场景需要给类增加字段来作一些变量传递。opentelemetry-java-instrumentation 提供了 VirtualField 机制,如下图所示,通过统一的编程接口,可以给类 T 添加一个类型为 F 的字段。
- 当类 T 当前尚未加载时,此时的实现就是给类 T 增加了类型为 F 的字段。当访问类 T 的 F 字段时和访问普通的类字段一致。
- 当类 T 已经加载时,此时的实现是有一个全局的 ConCurrentWeakhashMap,map 的 key 类型为 T,value 类型为 F。当访问类 T 的 F 字段时实际在底层为 map 的 get 操作。
public static <U extends T, V extends F, T, F> VirtualField<U, V> find(Class<T> type, Class<F>fieldType) {return RuntimeVirtualFieldSupplier.get().find(type, fieldType);
}
异步上下文透传
除了原生的 JDK 线程池,对市面上常见的异步框架 akka、netty event loop 等均做了异步埋点。异步埋点思路整体上包含两个步骤:
- 实现了 Runnable 接口的实现类,利用上述的 VirtualField 机制,给实现类增加一个记录 Trace 上下文的字段,同时埋点其 run 方法,run 方法执行时获取增加字段中的 Trace 上下文,并设置到当前线程的 ThreadLocal 中。
- 埋点 Exectuor 的 execute 方法,在 execute 方法执行时从 ThreadLocal 获取当前 Trace 上下文,并设置给对应的 Runnable 实现类。
新埋点思路
最大程度利用框架的拓展能力进行埋点,比如利用 Dubbo 的 Filter 机制、grpc 的 Intercepter 机制、实现 lettuce 的 Tracing 接口等等。而不是一味的对框架的方法进行增强。
除了上面提到的这些,opentelemetry-java-instrumentation 还有很多亮点设计,比如类加载器隔离,opentelemetry-java-sdk 兼容,多 JDK 版本兼容等等,这里不再一一赘述,后续会推出系列文章专门介绍 OTel Java Agent 的一些亮点设计和技巧。
调研结论
当完成 OTel Java Agent 各方面的调研之后,我们会发现他的很多设计都是领先的,一章节提到的那些代码设计和技巧、埋点方式等帮助我们打开了新的思路,可以解决很多困扰许久的问题。OTel Java Agent 的蓬勃发展成为了一个促使我们进行一次大规模重构最合理的契机,再考虑到拥抱开源、拥抱标准的基本原则,于是我们在 2023 年的夏天做了一个重大的决定,在 ARMS Java Agent 的下一个大版本 4.x 版本中,基于 OTel Java Agent 做一次升级重构,将现有 ARMS 3.X 版本探针的商业化能力迁移过来,并做到能 100% 兼容 3.x 探针的功能。
围绕 OTel Java Agent 做了哪些增强
在接下来将近一年的时间里,围绕 openTelemetry-java-instrumentation,首先,我们对其现有的功能进行了升级重构。包括新插件支持,基础的 Tracing 能力增强,指标类型增加、指标维度增加等等;其次,迁移了很多过往几年沉淀的商业化能力。包括 Arthas 诊断,应用安全、内存 Dump,微服务治理(全链路灰度、无损上下线,限流降级等等);最后,围绕探针构建了完善的稳定性保障措施。升级后的探针整体架构图如下图所示:
下面分别展开说明。
新插件支持
OTel 探针对国内一些被广泛使用的框架、中间件支持较少,比如 druid、xxl-job、hsf、influxdb、mybatis、xxlJob、motan、shenyu 等,我们此次增加了对这些框架的支持,并且部分已经贡献给开源。
Tracing 增强
Tracing 能力是 APM 探针的核心能力,OTel 探针原生的 Tracing 能力在企业内部复杂场景下往往会遇到不少挑战,包括多协议场景下断链、极端场景下 Span 数量爆炸、采样难以命中高价值数据等等。针对这些问题,我们对 OTel 探针做了以下增强来解决:
多协议支持
原理:默认情况下会自动按照 EagleEye、W3C、Skywalking、Zipkin、Jaeger、Skywalking 的顺序识别并恢复上游透传的 Trace 上下文。同样也支持按照用户需求配置优先或者强制使用某种协议。
优点:在客户多语言、内部不同部门使用多套 Tracing 系统、外部流量携带 Trace 上下文、上云迁移等场景下能尽量保证不断链。
调用链压缩
原理:ARMS 探针会将一些同一层级的重复 Span 压缩成一个,比如业务代码在一个 for 循环中,调用数据库应用 10000 次,那么在调用链中会生成 10000 个 Span,而经过调用链压缩后,仅会记录一个 Span,并在这个 Span 中记录重复 Span 的次数、最大耗时、最小耗时、总耗时等信息,效果如下图所示。
同时,为了避免尽可能保留重要信息。会将耗时 top3 和最开始报错的三个 Span 转换为 SpanEvent 保留在压缩后 Span 的 SpanEvent 中。优点:一方面可以避免极端场景下产生大量数据,客户 overhead 过高;另一方面避免 Span 过多场景下,后端查询缓慢、前端渲染卡顿、展示臃肿、客户排查问题难以抓住重点等问题。
缺点:因为仅保留了部分样本,无法看到全部的信息,可能导致丢失用户真正关注的数据。
采样
相比于其他产品单一的采样策略,ARMS 探针提供相对较为丰富的采样策略,且大多不需要用户进行复杂配置,每个采样策略保证特定场景下高价值 Tracing 数据被采样,低价值 Tracing 数据少采样,分别如下所示:
固定比例采样
即现有的默认采样,按照百分比采样链路。
自适应采样
自适应采样会按照 LFU 的策略选取当前调用量 top-1000 的接口,每个接口的采样彼此隔离,可设置两种采样策略,两种策略两种采样分别如下所示。
- 每秒固定条数(默认):一秒采样 10 条。
- 自适应比例:默认 10%,会根据该接口上一分钟请求量动态调整,避免大流量接口采样太多无效数据。
另外对于调用量 top-1000 以外的接口,可以认为是一个 other 接口。处理逻辑和前面介绍的 top-1000 中任 1 接口一致。
小流量采样
无需用户配置,自动保证每一个接口每一分钟至少有一个 Span。原理是用一个布隆过滤器存储一分钟内已经被采样过的接口。并每一分钟定期重置该布隆过滤器。这样可以保证无论用户接口有多发散,内存开销都是确定的。
错慢异常采样
无需用户配置,当一次调用满足下面三个条件时,则上报该次调用相关 Span。
- 接口报错:http 类接口响应码非 2xx、3xx 或者本次调用的 localRootSpan 埋点方法处抛出异常。
- 接口内部有异常:一次调用的非 LocalRootSpan 的 Span 记录到异常信息。
- 接口调用耗时长的定义:接口耗时大于过去一段时间该接口的 p99 耗时。
该采样对于问题排查十分重要,但是因为时机问题,无法保证链路完整。比如接口 A 调用接口 B,A 命中错慢采样,并不能保证 B 接口的 Span 一定上报。
自定义采样
即用户自己配置 100% 采样接口、接口前缀、接口后缀等等。满足用户配置要求的调用会一定采样。
总结
上述各个采样策略会在一次调用中都生效,一个 Span 是否上报由上述采样策略综合决定,详细流程如下图所示:
其中不同颜色的采样策略区别在于:
- 紫色: 标准的头采样,只会在链路的 RootSpan 处触发,采样后可以保证后续链路完整。
- 蓝色: 只要当前的采样结果是不采样,可以在链路的任何一个 LocalRootSpan 处触发,采样后可以保证后续链路完整。
- 绿色: 只要当前的采样结果不采样,可以在链路的任何节点触发,采样后无法保证后续链路完整。
以一个常见的链路 A->B->C 为例说明,在不同节点命中不同采样规则时,对应会链路哪些 Span 会上报,哪些 Span 不上报。
Metrics 增强
更丰富的指标
1)线程池监控指标:针对常见 JDK 线程池,Jetty、Undertow 线程池监控,支持核心线程、最大线程、活跃线程、当前线程、历史最大线程、调度任务、完成任务、拒绝任务以及队列大小 9 类指标。便于排查线程池打满类问题。
2)线程监控指标:将当前 JVM 种所有线程归类后,统计不同类别线程的耗时以及处于不同状态线程的数量,并定时抓取线程栈,便于排查线程阻塞,线程耗时高等问题。
3)MQ 消费延迟指标:针对 MQ 类组件,出了常见的 RED 指标,增加消费延迟指标,便于排查消费延迟类问题。
4)数据库响应大小:针对 DB 类操作,增加请求、响应大小指标,便于排查大查询类问题。
5)新增异常类指标:指标主要为异常次数,维度记录了当前接口,便于排错异常类问题。
更多样的维度
1)接口类 RED 指标记录上游接口:方便查看接口到接口的调用拓扑、调用关系,方便接口异常时快速定位上下游。
2)数据库类调用指标。额外记录当前接口、数据库语句维度,方便接口出问题时,快速定位是否 db 的问题。db 出问题时,快速查询影响的接口,具体出问题的 sql 语句。
Profiling 能力支持
和阿里云 Dragonwell 团队合作,底层基于 async-profiler,提供 CP(Continuous Profiling)的能力。阿里云 Java Agent 提供的 CP 支持多种剖析类型,比如 CPU 热点剖析、堆内存热点剖析,墙钟热点剖析等。
特色能力介绍
除了常见的 CPU 热点剖析、内存热点剖析,ARMS 还针对慢调用链诊断场景,提供了代码热点产品能力,其是在开源 Async Profiler 墙钟能力的基础上,通过关联调用链中的 TraceId & SpanId 信息提供了调用链级别的 On & Off-CPU 火焰图,可有效对 Tracing 的监控盲区细节进行还原,帮助用户诊断各类常见的慢调用链问题,详情可参见文档 [ 1] 。
那么,和客户自己用开源的 Async Profiler 生成火焰图相比有什么优势呢?
首先,支持常态化开启。 开源的 Async Profiler 未提供支持常态化开启的数据存储与处理能力,难以在生产环境常态化开启,对于一些线上偶现的问题,难以使用其进行问题排查。
其次,运行环境覆盖面更广。 开源的 Async Profiler 一些剖析类型对应用运行环境有一定要求,比如 Alpine Linux 基础镜像为了控制体积而去除了 JDK 调试符号(debug symbols)导致无法使用内存热点剖析功能,但是 ARMS 在其基础上通过针对特定版本的 Alpine Linux 基础镜像对应的 JDK 调试符内容做了预适配,对相关类型的环境,在不安装调试符的情况下,也可以使用内存热点。
最后,更好的稳定性。 开源的 Async Profiler 常态化开启过程中可能会容易出现 Crash 问题比如 #694 [ 2] 或者多个剖析引擎(CPU 热点、内存热点等)同时启动,一个外部条件不满足引发的单引擎失败会导致整体失败,ARMS 在开源 Async Profiler 基础上做了一些 bugfix 和剖析引擎隔离优化,稳定性更好。
性能优化
在分析 OTel Java Agent 的过程中,我们发现它在创建 Span、记录指标等地方,对于 Attributes 有大量的重复 copy 以及排序操作,这些部分是占用整个探针 CPU 开销的大头,我们对这些操作进行了大量的优化,结果表明在 TPS4000 流量的测试场景下,aliyun-java-agent 探针相较开源版本 OTel Java 探针 CPU 性能表现更好,整体容器 CPU 开销水位大约降低 2%;内存性能表现上,在进行 2h 压测后容器申请的 RSS 内存,aliyun-java-agent 探针相较开源版本 OTel 探针的内存占用降低约 10MB。
问题诊断场景的增强
- 集成代码级问题诊断利器 Arthas。无需依赖 JDK,一键开启、关闭。常见命令白屏化操作。且支持企业级鉴权、审计能力。避免任意用户随意执行 Arthas 命令。详情见 Arthas 诊断 [ 3] 。
- 内存 Dump。一键对指定机器执行内存 Dump,并配套白屏化分析能力。
云产品集成
- 微服务治理。在同一个 Java Agent 中集成了阿里云 MSE 微服务治理能力,包括全链路灰度、限流降级、无损上下线,系统防护、消息灰度等。
- 集成云安全中心应用安全 RASP。一键开启后拥有危险组件检测、25+ 种攻击行为 [ 4] 的监控,阻断的能力。
探针稳定性建设
由于 Java 探针和用户代码运行在一个进程中,且会对用户代码进行增强修改,Java 探针的稳定性建设尤为重要,多年的公有云用户服务经验告诉我们,对于一款可观测产品而言,我们的底线是不能影响业务行为,比如导致用户进程启动失败,用户进程 crash,用户接口报错,占用大量用户机器资源等等。为了最大程度的避免这类问题,并在出现这类问题时能够及时止血,我们在 OT 的基础上增加了下述能力。
- 探针 CPU/内存占用上限控制能力:在探针 CPU 开销,内存占用超过指定阈值时,自动降级探针的 Tracing 或者 Metrics 数据采集能力。
- 探针启动预检能力;因为探针本身有运行的环境要求,为了避免在非预期环境中出现异常行为,探针启动有若干检测项,比如 JVM 类型、JVM 版本、最大堆内存等等,最大程度的避免影响用户业务。
- 探针功能可动态插拔能力:大部分探针功能,特别是可能影响用户业务的能力,都具备动态控制开关,可以在出现问题时快速关闭。
阿里云 Java Agent 4.0 探针带来了哪些好处
从功能层面上来说,这次升级,完全吸纳了 OTel 的优秀设计,对我们现有的很多功能做了升级或者增强。
- 遵循 JDBC 规范的数据库埋点从 JDBC 接口层面埋点,理论上支持所有遵循 JDBC 规范的数据库埋点(3.x 探针仅支持固定的 9 种)。
- 异步埋点无需用户配置,不会断链。
- vertx、webflux、lettuce、Rabbitmq、kafka、RocketMq、ONS 等插件相比老版本,因为埋点的位置优化,指标统计更准确,支持版本范围更广。
- 支持容器场景的系统指标采集。
- 线程池监控支持用户自定义线程池的监控。
从工程质量上来看来说,这次升级重构是对 3.x 代码的一次取其精华、去其糟粕的过程、是重新树立更合理科学的开发规范的过程,通过这次升级重构:4.0 探针的内存占用下降了 20%、线程数降低了 60%,探针包大小降低了 30%。
最后,从长远发展来看,我们制定了每三个月合并一次开源最新稳定代码的计划,可以快速的享受到社区快速迭代的红利。
我们为社区做了什么
在基于 OTel Java Agent 二次开发的过程中,我们也积极的反哺开源,在过去 6 个月中,我们累计向社区贡献并合并各类 PR 40+,其中包含新增在国内广泛使用的 XXL-JOB、InfluxDB、MyBatis 等插件,参与社区日常 PR Review 100+,steverao [ 5] 和 123liuziming [ 6] 两位同事成为社区 member,其中 steverao 受邀作为该项目的 Triager 并且负责该社区的日常维护、代码 CR,且个人贡献长期位列社区前四名,贡献度积分位列社区 Top 20,亚太地区第一。
此外,我们也积极参与社区相关各类会议活动,今年 6 月,受社区邀请,在北美举行的 2024 OpenTelemetry Community Day 活动中,我们同事望陶和铖朴,为社区带来了《GraalVM 静态编译下 OTel Java Agent 的自动增强方案与实现》 [ 7] 主题分享,对相关问题的原创性解决方案得到了社区开发者的广泛关注。今年 8 月,在中国香港举行的 KubeCon China 2024 大会上,望陶和铖朴与社区其他开发者一起,在社区 Governance Committee 团队的支持下,代表社区在大会上做了《社区最新进展以及阿里云拥抱 OTel 社区实践》相关分享。
此外,为了促进亚太地区与社区的交流,在团队相关同学向社区提议,在与社区 Governance Committee Member 成员沟通后,OTel 社区也在多个领域,设立了亚太地区友好的周会交流时间。其中包含 Java: SDK + Instrumentation、Semantic Conventions: LLM、Contributor Experience 和 Developer Experience,相关时间可以参考社区周会安排 [ 8] ,相关会议中有社区最资深的开发者一起参与,欢迎有兴趣的朋友加入。
目前,我们也正在将由阿里云开源的 Go Instrumentation [ 9] 贡献到 OTel 社区,相关内容正在与社区相关 Governance Committee 和 Technical Committee 团队讨论中 #1961 [ 10] 。
写在最后
我们用了接近一年的时间完成了基于 OTel Java Agent 的升级重构,并于今年 5 月份发布了 4.x 探针的第一个版本 4.1.0,经过接近半年时间的验证、回归、优化,目前最新的稳定版本 4.1.12 [ 11] 已经正式发布,欢迎大家了解使用。
接下来的时间,一方面我们将持续的 Follow OTel Java Agent 的发版节奏,定期合并开源稳定代码,保障用户可以持续的享受社区最新的 feature;另一方面,我们也将重点打造阿里云 Java Agent 相比 OTel Java Agent 的差异化能力,补齐其不足与短板,帮助用户获得更全面、更透彻的应用可观测体验。
对 ARMS 有任何疑问,可搜索钉钉群号:31123480 加入 ARMS 沟通交流群。
相关链接:
[1] 文档
https://help.aliyun.com/zh/arms/application-monitoring/user-guide/enable-continuous-profiling
[2] #694
https://github.com/async-profiler/async-profiler/issues/694
[3] Arthas 诊断
https://help.aliyun.com/zh/arms/application-monitoring/user-guide/arthas-diagnosis
[4] 25+ 种攻击行为
https://help.aliyun.com/zh/arms/application-security/attacks-and-solutions
[5] steverao
https://github.com/steverao
[6] 123liuziming
https://github.com/123liuziming
[7] 《GraalVM 静态编译下 OTel Java Agent 的自动增强方案与实现》
https://otelcommunitydayna24.sched.com/event/1d0AC/implement-auto-instrumentation-under-graalvm-static-compilation-on-otel-java-agent-zihao-rao-huxing-zhang-alibaba
[8] 社区周会安排
https://github.com/open-telemetry/community?tab=readme-ov-file#special-interest-groups
[9] Go Instrumentation
https://github.com/alibaba/opentelemetry-go-auto-instrumentation
[10] #1961
https://github.com/open-telemetry/community/issues/1961
[11] 4.1.12
https://help.aliyun.com/zh/arms/application-monitoring/user-guide/versions-of-arms-agent-for-java
相关文章:
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
作者:陈承 背景 在 2018 年的 2 月,ARMS Java Agent 的第一个版本正式发布,为用户提供无侵入的的可观测数据采集服务。6 年后的今天,随着软件技术的迅猛发展、业务场景的逐渐丰富、用户规模的快速增长,我们逐渐发现过…...
【Linux】开发工具
这篇文章主要涉及sudo指令进行提权的方法,gcc/g的使用并且提及了一些make、makefile sudo指令 在前几篇文章中,我们先后了解了对于不同的角色来说,可以进行不同的操作,而对于新建的普通用户是不能进行权限提升的,这是…...
网络通信基础:TCP/IP、UDP、三次握手、Socket与HTTP协议详解
在网络通信的世界中,TCP/IP、UDP、三次握手、Socket和HTTP协议是不可或缺的基本概念。它们构成了网络通信的基石,对于理解网络编程和设计网络应用程序至关重要。本文将详细介绍这些概念,帮助读者更好地理解网络通信的原理。 首先,…...
(Python)前缀和
前缀和: 前缀和预先计算并存储一系列连续元素的总和,是一种优化技巧,提高算法效率。记录一个数组中各下标位置之前的所有元素的总和,本文对应下标的总和中不含对应下标元素本身。若有需要也可以对应下标记录的总和包含下标本身元…...
【Linux】-操作系统
🔑🔑博客主页:阿客不是客 🍓🍓系列专栏:深入代码世界,了解掌握 Linux 欢迎来到泊舟小课堂 😘博客制作不易欢迎各位👍点赞⭐收藏➕关注 一、冯•诺依曼架构ÿ…...
shell echo双引号和单引号区别
echo双引号"" var1"a" var2"b" echo -e "$var1\t$var2"输出: 使用双引号 "" 时,变量会被正确解析。 echo单引号‘’ var1"a" var2"b" echo -e $var1\t$var2输出: …...
嵌入式QT学习第3天:UI设计器的简单使用
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 Qt Creator 里自带的 Qt Designer,使用 Qt Designer 比较方便的构造 UI 界 面。 在 UI 文件添加一个按钮 左边找到 Push Button,然后拖拽到中…...
Nuxt.js 应用中的 render:response 事件钩子
title: Nuxt.js 应用中的 render:response 事件钩子 date: 2024/11/29 updated: 2024/11/29 author: cmdragon excerpt: render:response 是一个在 Nuxt.js 中与服务器端渲染(SSR)相关的钩子,它会在请求的响应发送之前被调用。这个钩子的目的是让开发者可以在响应发送之…...
Node报错:npm error code ETIMEDOUT
1、报错详细信息 npm error code ETIMEDOUT npm error syscall connect npm error errno ETIMEDOUT npm error network request to https://registry.npmjs.org/express failed, reason: connect ETIMEDOUT 104.16.1.35:443 npm error network This is a problem related to ne…...
领域驱动设计(DDD)模式深度剖析与 C# 实践
一、DDD 模式概述 领域驱动设计(Domain-Driven Design,简称 DDD)是一种软件开发方法论,旨在应对复杂业务领域的软件系统构建挑战。它强调以领域模型为核心,围绕业务领域中的关键概念、规则以及它们之间的关系来组织软…...
2024“蜀道山” RE 部分题解
Map_maze 题目描述 真真假假真真,你能够寻找到最后的终点吗? 附件下载 迷宫生成 v5 是一个长度为 105 的数组,被用作 15x15 的二维网格 int __cdecl sub_4010D0(_DWORD *a1, _DWORD *a2) {_DWORD *v2; // eax_DWORD *v3; // eaxint result; // eax_DWORD v5[1…...
composition
议论文 三个段落 第一段:2-3句话((1)引出背景(2)提出问题(3)过渡句) 第一段 (1)引出背景 As the giant leap of __(society,technology,education,culture,medical se…...
前端开发:构建高质量用户体验的全方位指南(含实际案例与示例)
前端开发:构建高质量用户体验的全方位指南(含实际案例与示例) 在当今数字化时代,前端技术不仅是网页和应用的门面,更是连接用户与数字世界的桥梁。一个高质量的前端开发项目不仅能够提升用户体验(UX&#…...
从Facebook的技术演进看社交媒体的未来趋势
在过去的二十年里,Facebook(现为Meta)从一个大学校园中的社交平台发展成了全球最大的社交媒体网络之一,成功塑造了人们交流、分享和消费信息的方式。作为社交媒体的巨头,Facebook的技术演进不仅推动了平台自身的发展&a…...
Linux下的wlan0控制
WIFI常用的两种模式:STA / AP 1. STA模式:客户端 嵌入式的系统下常常要手动配置wifi,和IP地址才能开始上网,关于STA模式下,常用的wifi配置工具有wpa_supplicant和轻量级的udhcpc客户端。 1.1wpa_supplicant 最小配置…...
常用循环依赖解决方案
常用循环依赖解决方案 Spring框架在4.3版本开始引入了对循环依赖的更好支持,但在此之前,Spring已经提供了一些机制来处理循环依赖。 实际上,Spring从一开始就提供了几种解决循环依赖的方法,只是在后续版本中对这些机制进行了优化…...
HTTPTomcatServlet
今日目标: 了解JavaWeb开发的技术栈理解HTTP协议和HTTP请求与响应数据的格式掌握Tomcat的使用掌握在IDEA中使用Tomcat插件理解Servlet的执行流程和生命周期掌握Servlet的使用和相关配置1,Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网,也称为万维网(www),能够通过浏览…...
instanceof运算符
而instanceof可以精准判断数据类型...
Conda 管理python开发环境
同步发布于我的网站 🚀 故事起因: 在公司使用Requests多任务并行开发时遇到了问题,使用 ProcessPoolExecutor 时不能正常发出网络请求,会卡在网络请求发不出去,但是善于用 ThreadPoolExecutor 时是可以的,纠结了很久,一…...
uniapp关闭sourceMap的生成,提高编译、生产打包速度
警告信息:[警告⚠] packageF\components\mpvue-echarts\echarts.min.js 文件体积超过 500KB,已跳过压缩以及 ES6 转 ES5 的处理,手机端使用过大的js库影响性能。 遇到问题:由于微信小程序引入了mpvue-echarts\echarts.min.js&…...
服务器挖矿
文章目录 一、确定挖矿进程并停止二、查找并清除挖矿相关文件三、检查并修复系统漏洞四、加强安全防护 一、确定挖矿进程并停止 查找挖矿进程 在Linux系统中,可以使用命令如top或htop来查看系统资源占用情况。挖矿程序通常会占用大量的CPU或GPU资源。例如ÿ…...
Flink双流Join
在离线 Hive 中,我们经常会使用 Join 进行多表关联。那么在实时中我们应该如何实现两条流的 Join 呢?Flink DataStream API 为我们提供了3个算子来实现双流 join,分别是: join coGroup intervalJoin 下面我们分别详细看一下这…...
.net XSSFWorkbook 读取/写入 指定单元格的内容
方法如下: using NPOI.SS.Formula.Functions;using NPOI.SS.UserModel;using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;using OfficeOpenXml.FormulaParsing.Excel.Functions.Numeric;/// <summary>/// 读取Excel指定单元格内容/// </summa…...
【VUE3】【Naive UI】<NCard> 标签
【Vue3】【Naive UI】 标签 title 属性bordered 属性header-style 和 body-style 属性footer 属性actions 属性hoverable 属性loading 属性size 属性type 属性cover 和 avatar 属性description 属性style 属性 【VUE3】【Naive UI】<NCard> 标签 【VUE3】…...
喜欢发光的自己
Music: 听见下雨的声音 想着写点什么吧...从哪开头好呢?... 好像有很多话想记录下来,但又不知道从哪开头 自上次写博客至现在已经有段时间了。 最近还发生了挺多事,自己的身体又将面临一次考验... 有颗蛀牙,但莫名奇妙的是里…...
mfc110u.dll是什么意思,mfc110u.dll丢失解决方法大全详解
mfc110u.dll是Microsoft Foundation Classes (MFC)库的一个特定版本(版本11.0)的Unicode动态链接库文件。MFC是Microsoft为C开发者设计的一个应用程序框架,主要用于简化Windows应用程序的开发工作。这个框架封装了很多Windows API函数&#x…...
制片人欧阳行远:引领独立电影斩获国际殊荣
随着全球电影市场对独特叙事和多元化题材的需求持续高涨,独立电影再次成为业内外讨论的焦点,尤其是聚焦亲情、成长经历和女性视角的影片,在国际影坛掀起了一股热潮。这一趋势的形成,离不开一些杰出短片的奠基作用,而欧阳行远作为执行制片人,凭借敏锐的行业嗅觉和出色的制作能力…...
《C++ Primer Plus》学习笔记|第7章-函数——C++编程模块 (未完结)
文章目录 7.1 函数的基本知识7.1.1 定义函数7.1.2 函数原型和函数调用 7.2 函数参数和按值传递7.3 函数与数组7.3.5 指针与const7.4 函数和二维数组 7.10 函数指针1. 函数的地址2. 声明函数指针3.使用指针来调用函数 7.12 复习题1. 使用函数的3个步骤是什…...
C/C++ 数据结构与算法【线性表】 顺序表+链表详细解析【日常学习,考研必备】带图+详细代码
1)线性表的定义 线性表(List):零个或多个数据元素的有限序列。 线性表的数据集合为{a1,a2,…,an},假设每个元素的类型均为DataType。其中,除第一个元素a1外,每一个元素有且只有一个直接前驱元素…...
详细说说 JDK 的线程池的创建参数
文章目录 1. 概要2. 线程的核心参数2.1.核心线程和最大线程2.2.任务队列2.2.1.ArrayBlockingQueue2.2.2.LinkedBlockingQueue2.2.3.SynchronousQueue2.2.4.PriorityBlockingQueue2.2.5.DelayQueue2.2.7.LinkedBlockingDeque 2.3 keepAliveTime2.4 ThreadFactory2.5 拒绝策略 3.…...
惠普电脑切换默认F1至F12快捷键,FN切换
发现新买的惠普电脑,按F1至F12发现是快捷功能键,而按fnF1至F12才是windows的功能键和正常我自己使用的电脑刚好相反,实在太不方便了。 解决办法需要进入biso里面去把功能键模式选中给关掉,才能恢复回来...
RabbitMQ在手动消费的模式下设置失败重新投递策略
最近在写RabbitMQ的消费者,因为业务需求,希望失败后重试一定次数,超过之后就不处理了,或者放入死信队列。我这里就达到重试次数后就不处理了。本来以为很简单的,问了kimi,按它的方法配置之后,发…...
[巅峰极客 2021]签到
[巅峰极客 2021]签到 给了我们好多表情,真的是一脸懵逼 注意给我们的关键词 GAME 现在还不知道是什么意思我们去试着解开一下 用这个emoji表情解密器,这里我找了好久才找到一个 emoji-aes 这里的Key值就是GAME 运行后出现flag NSSCTF{10ve_4nd_Peace…...
CrystalDiskInfo:硬盘健康监测工具简介和下载
原论坛给你更好的阅读体验:CrystalDiskInfo:硬盘健康监测工具简介和下载 | 波波论坛 引言 在日常使用电脑时,硬盘的健康状态对于系统的稳定性和数据的安全性至关重要。硬盘出现故障可能会导致数据丢失,严重时甚至会使整个系统无…...
循环神经网络(RNN)详解
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
vue基础之3:模板语法、数据绑定
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
Ubuntu通过脚本启动多个可执行文件
Ubuntu通过脚本启动多个可执行文件 在 Ubuntu 中,可以通过一个脚本启动多个可执行文件,同时支持顺序执行、并行执行或特定条件下的执行。以下是实现的详细方法: 1. 创建脚本文件 首先,创建一个脚本文件,例如 start_p…...
【C++】LeetCode:LCR 026. 重排链表
题干 LCR 026. 重排链表 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln-1 → L2 → Ln-2 → … 不能只是单纯的改变节点内部的值,而是需要实…...
文档加密怎么做才安全?
公司的文档包含很多机密文件,这些文件不仅关乎公司的核心竞争力,还涉及到客户隐私、商业策略等敏感信息。因此,文档的保管和传递一直是我们工作的重中之重。 为了确保机密文件的安全,公司需要制定了一系列严格的保密措施。从文件的…...
CTF之WEB(php弱类型绕过)
PHP 的弱类型特性有时会导致意外的行为,特别是在类型比较时。这些特性可以被利用来绕过一些预期的安全检查。以下是一些常见的 PHP 弱类型绕过技巧及其解释: 类型介绍 1. 类型比较 ( vs ) 在 PHP 中, 是松散比较,而 是严格比较…...
Java ConcurrentHashMap
Java Map本质不是线程安全的,HashTable和Collections同步包装器(Synchronized Wrapper)在并发场景下性能低。Java还为实现 Map 的线程安全提供了并发包,保证线程安全的方式从synchronize简单方式到精细化,比如Concurre…...
力扣162:寻找峰值
峰值元素是指其值严格大于左右相邻值的元素。 给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。 你可以假设 nums[-1] nums[n] -∞ 。 你必须实现时间复杂度为 O(…...
网络设备配置指南:交换机、路由器与防火墙的基础配置与管理
在现代网络管理中,交换机、路由器和防火墙是不可或缺的关键设备。掌握这些设备的基本配置与管理,对于确保网络的稳定性、安全性和高效性至关重要。本文将详细介绍交换机、路由器和防火墙的基础配置与管理,并通过代码示例和图示来帮助读者更好地理解和应用。 一、交换机的基…...
parallelStream并行流使用踩坑,集合安全
parallelStream并行流使用踩坑 parallelStream介绍 parallelStream实现的是多线程处理从而实现并行流,相较于stream的单行流处理数据的速度更快,看一下其源码会发现parallelStream是使用线程池ForkJoin来调度的。 而ForkJoinPool的默认线程数是CPU核数 …...
清远榉之乡托养机构探讨:自闭症的本质辨析
当人们谈及自闭症时,常常会产生一个疑问:自闭症是精神类疾病吗?今天,清远榉之乡托养机构就来为大家解开这个疑惑。 榉之乡大龄自闭症托养机构在江苏、广东、江西等地都有分校,一直致力于为大龄自闭症患者提供专业的支持…...
音视频入门基础:MPEG2-TS专题(10)——PAT简介
一、引言 当某个transport packet的TS Header中的PID属性的值为0x0000时,该transport packet的payload为Program association table ,即 PAT表。PAT表包含所有PMT表的目录列表,将program_number和PMT表的PID相关联,获取数据的起始…...
wordpress网站首页底部栏显示网站备案信息
一、页脚文件footer.php 例如,wordpress主题使用的是simple-life主题,服务器IP为192.168.68.89,在wordpress主题文件中有个页脚文件footer.php,这是一个包含网站页脚代码的文件。 footer.php 路径如下: /www/wwwroot/192.168.68…...
SOLIDWORKS英文,怎么修改成中文
SOLIDWORKS英文,怎么修改成中文 打开控制面板里的程序 选择程序与功能 找到SOLIDWORKS,选择并点击上方 “更改” 在跳出来的更改页面,选择“简体中文” 点击SOLIDWORKS界面上小齿轮,进入设置 取消勾选English两个相关设置 重启SO…...
简单搭建qiankun的主应用和子应用并且用Docker进行服务器部署
在node18环境下,用react18创建qiankun主应用和两个子应用,react路由用V6版本,都在/main路由下访问子应用,用Dockerfile部署到腾讯云CentOS7.6服务器的8000端口进行访问,且在部署过程中进行nginx配置以进行合理的路由访…...
等保三级安全架构设计方案
一、概述 等保三级,全称为“信息系统安全等级保护三级”,是根据信息安全保护的需求,将系统的安全保护划分为五个等级中的第三级,主要针对相对重要的信息系统进行保护。根据《信息系统安全等级保护基本要求》(GB/T 222…...