链路传播(Propagate)机制及使用场景
服务间链路追踪传播机制是指在微服务架构中,通过记录和跟踪服务之间的请求和响应信息,来实现对服务间链路的追踪和监控。这种机制可以帮助开发人员快速定位服务间出现的问题,并进行优化和调整。
具体来说,服务间链路追踪传播机制可以通过在每个服务的请求和响应中添加唯一标识符来实现。当一个服务发送请求到另一个服务时,它会将自己的唯一标识符添加到请求头中,并发送给目标服务。目标服务收到请求后,会将请求头中的唯一标识符复制到响应头中,并返回给调用方。调用方收到响应后,可以通过唯一标识符来追踪服务间的调用链路。
为了实现服务间链路追踪传播机制,通常会使用一些开源工具或框架,比如
OpenTelemetry、DataDog、Zipkin、SkyWalking等。这些工具可以自动记录服务间的请求和响应信息,并提供可视化的界面来帮助开发人员进行调试和优化。
通常,我们会将这种特殊标识的请求头称之为传播协议。
常见传播协议
不同的 APM 工具支持一种或者多种传播协议,以便更好的服务于应用。
- b3
- uber
- sw8
- w3c
- datadog
- ot

OpenTelemetry 除了原生支持 ot、w3c 、 b3和uber几种协议外,通过:opentelemetry-collector-contrib 支持 sw8和datadog传播协议。
B3 协议
B3 传播协议是第一个链路追踪协议,这里重点讲述 B3 传播协议相关内容。
B3 有两种编码:Single Header 和 Multiple Header。
- 多个标头编码 X-B3-在跟踪上下文中使用每个项目的前缀标头
- 单个标头将上下文分隔为一个名为 b3. 提取字段时,单头变体优先于多头变体。
这是一个使用多个标头编码的示例流程,假设 HTTP 请求带有传播的跟踪:

Multiple Headers
需要配合多个 header key 使用。
TraceId
X-B3-TraceId 标头编码为 32 或 16 个低十六进制字符。例如,128 位 TraceId 标头:X-B3-TraceId:463ac35c9f6413ad48485a3953bb6124。除非仅传播“采样状态”,否则需要 X-B3-TraceId 标头。
SpanId
X-B3-SpanId 标头编码为16个较低的十六进制字符。例如:X-B3-SpanId:a2fb4a1d1a96d312。除非仅传播“采样状态”,否则需要 X-B3-SpanId 标头。
ParentSpanId
X-B3-ParentSpanId标头可能存在于子跨度上,而在根跨度上必须不存在。它被编码为16个低十六进制字符。例如,ParentSpanId标头可能看起来像:X-B3-ParentSpanId:00020000000000001
Sampling State
接受采样决定编码为X-B3-Sampled:1,拒绝编码为X-B3-Sampled:0。缺席意味着将决定推迟到该报头的接收方。例如:X-B3-Sampled:1。
注:在编写本规范之前,一些示踪剂传播X-B3-Sampled为true或false,而不是1或0。虽然您不应该将X-B3-Sampled编码为true或false,但宽松的实现可能会接受它们。
Debug Flag
调试编码为X-B3-Flags: 1。可以忽略 Absent 或任何其他值。调试意味着接受决定,所以不要同时发送X-B3-Sampled标头。
Single Header
Single Header 只有一个header 为b3的 key 作为标记。
b3={TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}
如
b3: 80f198ee56343ba864fe8b2a57d3eff7-e457b5a2e4d86bd1-d
实现场景
目前主要有两大实现场景:
- APM:主要是服务端之间传播
- RUM:用户端(web、小程序等)与服务端传播
APM
OpenTelemetry 传播器源码
OpenTelemetry 传播器源码
传播器接口:TextMapPropagator
opentelemetry-java 通过定义统一的接口TextMapPropagator来实现各种 Propagate。
TextMapPropagator默认提供了一个空实现noop()。
TextMapPropagator 定义了三个接口方法:
- fields() : 规定了哪些字段作为传播器识别的对象
- inject():定义了传播器字段注入规则
- extract():定义传播器字段提取规则,返回
Context对象
一些厂商有自己的 APM 标准,通过扩展TextMapPropagator接口,实现对接厂商特定的传播器。
@ThreadSafe
public interface TextMapPropagator {static TextMapPropagator composite(TextMapPropagator... propagators) {return composite(Arrays.asList(propagators));}static TextMapPropagator composite(Iterable<TextMapPropagator> propagators) {List<TextMapPropagator> propagatorsList = new ArrayList<>();for (TextMapPropagator propagator : propagators) {propagatorsList.add(propagator);}if (propagatorsList.isEmpty()) {return NoopTextMapPropagator.getInstance();}if (propagatorsList.size() == 1) {return propagatorsList.get(0);}return new MultiTextMapPropagator(propagatorsList);}static TextMapPropagator noop() {return NoopTextMapPropagator.getInstance();}Collection<String> fields();<C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter);<C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> getter);
}
OtTracePropagator
OtTracePropagator 是 OpenTelemetry 特有的传播器,识别解析ot-开头的header,部分源码如下:
@Immutable
public final class OtTracePropagator implements TextMapPropagator {static final String TRACE_ID_HEADER = "ot-tracer-traceid";static final String SPAN_ID_HEADER = "ot-tracer-spanid";static final String SAMPLED_HEADER = "ot-tracer-sampled";static final String PREFIX_BAGGAGE_HEADER = "ot-baggage-";private static final Collection<String> FIELDS =Collections.unmodifiableList(Arrays.asList(TRACE_ID_HEADER, SPAN_ID_HEADER, SAMPLED_HEADER));....@Overridepublic Collection<String> fields() {return FIELDS;}@Overridepublic <C> void inject(Context context, @Nullable C carrier, TextMapSetter<C> setter) {if (context == null || setter == null) {return;}SpanContext spanContext = Span.fromContext(context).getSpanContext();if (!spanContext.isValid()) {return;}// Lightstep trace id MUST be 64-bits therefore OpenTelemetry trace id is truncated to 64-bits// by retaining least significant (right-most) bits.setter.set(carrier, TRACE_ID_HEADER, spanContext.getTraceId().substring(TraceId.getLength() / 2));setter.set(carrier, SPAN_ID_HEADER, spanContext.getSpanId());setter.set(carrier, SAMPLED_HEADER, String.valueOf(spanContext.isSampled()));// Baggage is only injected if there is a valid SpanContextBaggage baggage = Baggage.fromContext(context);if (!baggage.isEmpty()) {// Metadata is not supported by OpenTracingbaggage.forEach((key, baggageEntry) ->setter.set(carrier, PREFIX_BAGGAGE_HEADER + key, baggageEntry.getValue()));}}@Overridepublic <C> Context extract(Context context, @Nullable C carrier, TextMapGetter<C> getter) {if (context == null) {return Context.root();}if (getter == null) {return context;}String incomingTraceId = getter.get(carrier, TRACE_ID_HEADER);String traceId =incomingTraceId == null? TraceId.getInvalid(): StringUtils.padLeft(incomingTraceId, MAX_TRACE_ID_LENGTH);String spanId = getter.get(carrier, SPAN_ID_HEADER);String sampled = getter.get(carrier, SAMPLED_HEADER);SpanContext spanContext = buildSpanContext(traceId, spanId, sampled);if (!spanContext.isValid()) {return context;}Context extractedContext = context.with(Span.wrap(spanContext));// Baggage is only extracted if there is a valid SpanContextif (carrier != null) {BaggageBuilder baggageBuilder = Baggage.builder();for (String key : getter.keys(carrier)) {if (!key.startsWith(PREFIX_BAGGAGE_HEADER)) {continue;}String value = getter.get(carrier, key);if (value == null) {continue;}baggageBuilder.put(key.replace(OtTracePropagator.PREFIX_BAGGAGE_HEADER, ""), value);}Baggage baggage = baggageBuilder.build();if (!baggage.isEmpty()) {extractedContext = extractedContext.with(baggage);}}return extractedContext;}...
}
初始化传播器
opentelemetry-java 通过PropagatorConfiguration 对象对Propagate进行初始化操作,源码如下:
final class PropagatorConfiguration {private static final List<String> DEFAULT_PROPAGATORS = Arrays.asList("tracecontext", "baggage");static ContextPropagators configurePropagators(ConfigProperties config,ClassLoader serviceClassLoader,BiFunction<? super TextMapPropagator, ConfigProperties, ? extends TextMapPropagator>propagatorCustomizer) {Set<TextMapPropagator> propagators = new LinkedHashSet<>();List<String> requestedPropagators = config.getList("otel.propagators", DEFAULT_PROPAGATORS);NamedSpiManager<TextMapPropagator> spiPropagatorsManager =SpiUtil.loadConfigurable(ConfigurablePropagatorProvider.class,ConfigurablePropagatorProvider::getName,ConfigurablePropagatorProvider::getPropagator,config,serviceClassLoader);if (requestedPropagators.contains("none")) {if (requestedPropagators.size() > 1) {throw new ConfigurationException("otel.propagators contains 'none' along with other propagators");}return ContextPropagators.noop();}for (String propagatorName : requestedPropagators) {propagators.add(propagatorCustomizer.apply(getPropagator(propagatorName, spiPropagatorsManager), config));}return ContextPropagators.create(TextMapPropagator.composite(propagators));}private static TextMapPropagator getPropagator(String name, NamedSpiManager<TextMapPropagator> spiPropagatorsManager) {if (name.equals("tracecontext")) {return W3CTraceContextPropagator.getInstance();}if (name.equals("baggage")) {return W3CBaggagePropagator.getInstance();}TextMapPropagator spiPropagator = spiPropagatorsManager.getByName(name);if (spiPropagator != null) {return spiPropagator;}throw new ConfigurationException("Unrecognized value for otel.propagators: "+ name+ ". Make sure the artifact including the propagator is on the classpath.");}private PropagatorConfiguration() {}
}
启动 agent 时,通过指定传播器类型来实现对应实例构造,通过方法得知,otel 支持同时指定多种类型的传播器协议,默认采用tracecontext传播器——即w3c标准的传播器:
List<String> requestedPropagators = config.getList("otel.propagators", DEFAULT_PROPAGATORS);
获取传播器
opentelemetry-java 通过OpenTelemetry对象的propagating()方法构造当前支持的传播器,且通过getPropagators()方法来获取已有的传播器,OpenTelemetry是一个接口类,部分代码如下:
public interface OpenTelemetry {static OpenTelemetry noop() {return DefaultOpenTelemetry.getNoop();}static OpenTelemetry propagating(ContextPropagators propagators) {return DefaultOpenTelemetry.getPropagating(propagators);}TracerProvider getTracerProvider();ContextPropagators getPropagators();...
}
每一个Instrumente都需要通过InstrumenterBuilder获取OpenTelemetry 对象来实现 trace、metric 相关业务逻辑。比如,启动一个 span。
如何获取OpenTelemetry对象
通过上面的研究,我们知道如何获取传播器,但是获取传播器需要获取OpenTelemetry对象,opentelemetry-java提供了一个全局的对象GlobalOpenTelemetry来获取OpenTelemetry对象。我们来看看具体代码
public final class GlobalOpenTelemetry {
...@Nullableprivate static volatile ObfuscatedOpenTelemetry globalOpenTelemetry;public static OpenTelemetry get() {OpenTelemetry openTelemetry = globalOpenTelemetry;if (openTelemetry == null) {synchronized(mutex) {openTelemetry = globalOpenTelemetry;if (openTelemetry == null) {OpenTelemetry autoConfigured = maybeAutoConfigureAndSetGlobal();if (autoConfigured != null) {return autoConfigured;}set(OpenTelemetry.noop());return OpenTelemetry.noop();}}}return openTelemetry;}public static void set(OpenTelemetry openTelemetry) {synchronized(mutex) {if (globalOpenTelemetry != null) {throw new IllegalStateException("GlobalOpenTelemetry.set has already been called. GlobalOpenTelemetry.set must be called only once before any calls to GlobalOpenTelemetry.get. If you are using the OpenTelemetrySdk, use OpenTelemetrySdkBuilder.buildAndRegisterGlobal instead. Previous invocation set to cause of this exception.", setGlobalCaller);} else {globalOpenTelemetry = new ObfuscatedOpenTelemetry(openTelemetry);setGlobalCaller = new Throwable();}}}@Nullableprivate static OpenTelemetry maybeAutoConfigureAndSetGlobal() {Class openTelemetrySdkAutoConfiguration;try {openTelemetrySdkAutoConfiguration = Class.forName("io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk");} catch (ClassNotFoundException var7) {return null;}boolean globalAutoconfigureEnabled = Boolean.parseBoolean(ConfigUtil.getString("otel.java.global-autoconfigure.enabled", "false"));if (!globalAutoconfigureEnabled) {logger.log(Level.INFO, "AutoConfiguredOpenTelemetrySdk found on classpath but automatic configuration is disabled. To enable, run your JVM with -Dotel.java.global-autoconfigure.enabled=true");return null;} else {try {Method initialize = openTelemetrySdkAutoConfiguration.getMethod("initialize");Object autoConfiguredSdk = initialize.invoke((Object)null);Method getOpenTelemetrySdk = openTelemetrySdkAutoConfiguration.getMethod("getOpenTelemetrySdk");return new ObfuscatedOpenTelemetry((OpenTelemetry)getOpenTelemetrySdk.invoke(autoConfiguredSdk));} catch (IllegalAccessException | NoSuchMethodException var5) {throw new IllegalStateException("AutoConfiguredOpenTelemetrySdk detected on classpath but could not invoke initialize method. This is a bug in OpenTelemetry.", var5);} catch (InvocationTargetException var6) {logger.log(Level.SEVERE, "Error automatically configuring OpenTelemetry SDK. OpenTelemetry will not be enabled.", var6.getTargetException());return null;}}}...
GlobalOpenTelemetry 通过单例模式实现获取全局OpenTelemetry对象。而OpenTelemetry则主要是通过AutoConfiguredOpenTelemetrySdk 的 getOpenTelemetrySdk方法初始化构建。
至此,基本上完成了opentelemetry-java从传播器实现、构造、初始化及获取相关操作。
DataDog(DDtrace)传播器源码
DataDog(DDtrace)传播器源码
DDtrace除了支持上面表格中的传播协议之外,还支持其他传播协议,如:
- Haystack
- Haystack-Trace-ID
- Haystack-Span-ID
- Haystack-Parent-ID
- XRAY
- X-Amzn-Trace-Id
RUM
前面了解了传播器的原理、作用以及实现方式。传播器提到最多的是 header,也就说大多数都是基于 http 协议。基于 http 协议,进一步引申到 html、小程序、Android、iOS 等,从而引出另一个概念:RUM。
RUM 全称为
Real User Monitor,即真实用户监控。
RUM 通过实现不同的传播器协议,将用户端与服务端紧密联系在一起,我们知道 APM 是后端接口及服务的性能表现,但接口用于地方很多,有的来源于 web,有的来源于小程序等等。通过引入 RUM,结合链路分析,很容易追踪到数据来源于哪一端。
当然 RUM 的作用不仅仅是这一方面,目前市面上常见的是基于 W3C(万维网联盟)定义的[navigation-timing] 标准(见下图),该标准详细定义了各种浏览器事件,通过浏览器事件的简单计算就可以算出来前端页面的首屏、白屏、DOM 加载、HTML 加载等时长,相较于测试环境的 F12 检查者模式,能有更效的收集生产环境真实用户的前端体验。

opentelemetry-js
opentelemetry-js是 OpenTelemetry 具体的实现,目前支持 nodejs 和 js,作用范围比较有限,主要围绕 OpenTelemetry 的集中传播器协议实现,产品成熟度仍需进一步提升。
opentelemetry-js demo
观测云 RUM
是观测云推出的 RUM 产品,可以与多种 APM 技术融合,本质上是支持多种传播器协议,进而能够与各种 APM 结合使用。
支持的传播器协议有:
- ddtrace :x-datadog-parent-id,x-datadog-sampled,x-datadog-sampling-priority,x-datadog-trace-id。
- skywalking: sw8。
- jaeger: uber-trace-id。
- zipkin: X-B3-TraceId、X-B3-SpanId、X-B3-ParentSpanId、X-B3-Sampled、X-B3-Flags。
- zipkin_single_header: b3。
- w3c_traceparent: traceparent。
- opentelemetry: 该类型支持 zipkin_single_header,w3c_traceparent,zipkin、jaeger三种类型的配置方式,根据在 rum sdk 中配置的 traceType 类型 添加对应的 header。
目前支持的应用有:
- web H5
- 小程序
- Android
- iOS
- React Native
- Flutter
- UniApp
- C++
以 web 为例,展示接入方式,接入简单。
<script src="https://static.guance.com/browser-sdk/v3/dataflux-rum.js" type="text/javascript"></script>
<script>window.DATAFLUX_RUM &&window.DATAFLUX_RUM.init({applicationId: '<应用 ID>',datakitOrigin: '<DATAKIT ORIGIN>', // 协议(包括://),域名(或IP地址)[和端口号]env: 'production',version: '1.0.0',service: 'browser',sessionSampleRate: 100,sessionReplaySampleRate: 70,trackInteractions: true,traceType: 'ddtrace', // 非必填,默认为ddtrace,目前支持 ddtrace、zipkin、skywalking_v3、jaeger、zipkin_single_header、w3c_traceparent 6种类型allowedTracingOrigins: ['https://api.example.com',/https:\/\/.*\.my-api-domain\.com/], // 非必填,允许注入trace采集器所需header头部的所有请求列表。可以是请求的origin,也可以是是正则})
</script>
其中 traceType 为传播器协议。
通过 CDN 加速缓存,以同步脚本引入的方式引入 SDK,此方式可以确保能够收集到所有的错误,资源,请求,性能指标,不过可能会影响页面的加载性能。
单页应用建议将下方代码复制粘贴到 html 文件 head 标签的首行,多页应用建议将下方代码复制粘贴到公共 head 模版文件的首行。
更多更详细接入方式,参考官方文档用户访问监测
RUM 与 APM 实际应用
以某开源平台访问用户资源为例,查看实际应用场景,如下图所示:

右侧服务列表:
- browser :浏览器链路,由RUM端上报
- 其他服务为 APM 上报
RUM 通过传递特定的 header 信息,将链路信息传递给 APM,APM 正确解析相关传播协议,并以 RUM 传递的 trace为基准,创建 span信息,实现前后端串联。
browser同时可以查看当前用户的请求耗时分布(128.3 ms)
通过右上角view 按钮,可以跳转到当前页面的查看器,以此来查看分析用户行为。如下图所示

Baggage
前面已经分析了传播器一般需要携带的参数信息,便于前后端的应用串联,但实际上这只是传播器的基础用法,通常都是用于传递 trace 信息,实际上,在上面 opentelemetry-java 源码分析中,有一个频繁出现的单词baggage,baggage主要作用于业务参数的传递。
通常,研发人员不会直接在接口上填上用户信息,所以无法准确追踪这个接口是哪个用户触发的,借助 baggage,通过 header 进行传递,能够在服务间无限传递下去。
OpenTelemetry Baggage 用法
Header key 以ot-baggage- 开头的参数,会被 OpenTelemetry 一直传递下去。
还可以采用sdk的方式:OpenTelemetry Baggage SDK用法
DataDog Baggage 用法
需要配置启动参数dd.trace.header.baggage,设置哪些header 作为传递的参数依据。用法如下:
Environment Variable: DD_TRACE_HEADER_BAGGAGE
Default: null
Example: CASE-insensitive-Header:my-baggage-name,User-ID:userId,My-Header-And-Baggage-Name
Accepts a map of case-insensitive header keys to baggage keys and automatically applies matching request header values as baggage on traces. On propagation the reverse mapping is applied: Baggage is mapped to headers.
Available since version 1.3.0.
也可以采用 SDK 的方式:DataDog Baggage SDK 用法
相关文章:
链路传播(Propagate)机制及使用场景
服务间链路追踪传播机制是指在微服务架构中,通过记录和跟踪服务之间的请求和响应信息,来实现对服务间链路的追踪和监控。这种机制可以帮助开发人员快速定位服务间出现的问题,并进行优化和调整。 具体来说,服务间链路追踪传播机制…...
pytorch技巧总结1:学习率调整方法
pytorch技巧总结1:学习率调整方法 前言 这个系列,我会把一些我觉得有用、有趣的关于pytorch的小技巧进行总结,希望可以帮助到有需要的朋友。 免责申明 本人水平有限,若有误写、漏写,请大家温柔的批评指正。 目录…...
谈谈VPN是什么、类型、使用场景、工作原理
作者:Insist-- 个人主页:insist--个人主页 作者会持续更新网络知识和python基础知识,期待你的关注 前言 本文将讲解VPN是什么、以及它的类型、使用场景、工作原理。 目录 一、VPN是什么? 二、VPN的类型 1、站点对站点VPN 2、…...
windows 下载安装Redis,并配置开机自启动
windows 下载安装Redis,并配置开机自启动 1. 下载 地址:https://github.com/tporadowski/redis/releases Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包,之后解压 打…...
2. CSS3的新特性
2.1CSS3的现状 ●新增的CSS3特性有兼容性问题, ie9才支持 ●移动端支持优于PC端 ●不断改进中 ●应用相对广泛 ●现阶段主要学习: 新增选择器和盒子模型以及其他特性 CSS3给我们新增了选择器,可以更加便捷,更加自由的选择目标元素: 1.属性选择器 2.结构伪类选择器…...
从零开始训练神经网络
用Keras实现一个简单神经网络 Keras: Keras是由纯python编写的基于theano/tensorflow的深度学习框架。 Keras是一个高层神经网络API,支持快速实验,能够把你的idea迅速转换为结果,如果有如下需 求,可以优先选择Keras&a…...
连接区块链节点的 JavaScript 库 web3.js
文章目录 前言web3.js 介绍web3.js安装web3.js库模块介绍连接区块链节点向区块链网络发送数据查询区块链网络数据 前言 通过前面的文章我们可以知道基于区块链开发一个DApp,而DApp结合了智能合约和用户界面(客户端),那客户端是如…...
js:scroll平滑滚动页面或元素到顶部或底部的方案汇总
目录 1、CSS的scroll-behavior2、Element.scrollTop3、Element.scroll()/Window.scroll()4、Element.scrollBy()/Window.scrollBy()5、Element.scrollTo()/Window.scrollTo()6、Element.scrollIntoView()7、自定义兼容性方案8、参考文章 准备知识: scrollWidth: 是…...
【Docker】Docker的部署含服务和应用、多租环境、Linux内核的详细介绍
前言 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 📕作者简介:热…...
C国演义 [第五章]
第五章 子集题目理解步骤树形结构递归函数递归结束的条件单层逻辑 代码 子集II题目理解步骤树形结构递归函数递归结束的条件单层逻辑 代码 子集 力扣链接 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。…...
Proxy-Reflect使用详解
1 监听对象的操作 2 Proxy类基本使用 3 Proxy常见捕获器 4 Reflect介绍和作用 5 Reflect的基本使用 6 Reflect的receiver Proxy-监听对象属性的操作(ES5) 通过es5的defineProperty来给对象中的某个参数添加修改和获取时的响应式。 单独设置defineProperty是只能一次设置一…...
【Linux后端服务器开发】Shell外壳——命令行解释器
目录 一、Shell外壳概述 二、描述Shell外壳原理的生动例子 三、C语言模拟实现Shell外壳 一、Shell外壳概述 在狭义上 , 我们称Linux操作系统的内核为 Linux 在广义上 , Linux发行版 Linux内核 外壳程序 就比如市面上现在的redhat, centos, ubuntu等等我们耳熟能详的Linux发…...
【无公网IP】在外Windows远程连接MongoDB数据库
文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 转载自cpolar极点云文章:公网远程…...
mac python3 安装virtualenv
第一步,执行安装virtualenv pip3 install virtualenv 注意:如果出现WARNING: The script virtualenv is installed in ‘/home/local/bin’ which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning,…...
网络安全(自学笔记)
如果你真的想通过自学的方式入门web安全的话,那建议你看看下面这个学习路线图,具体到每个知识点学多久,怎么学,自学时间共计半年左右,亲测有效(文末有惊喜): 1、Web安全相关概念&am…...
SPSS方差分析
参考文章 导入准备好的数据 选择分析方法 选择参数 选择对比,把组别放入因子框中,把红细胞增加数放进因变量列表 勾选“多项式”,等级取默认“线性” ,继续 接着点击“事后比较”,弹出对话框,勾选“LSD” …...
【Linux】深入理解文件系统
系列文章 收录于【Linux】文件系统 专栏 关于文件描述符与文件重定向的相关内容可以移步 文件描述符与重定向操作。 可以到 浅谈文件原理与操作 了解文件操作的系统接口。 想深入理解文件缓冲区还可以看看文件缓冲区。 目录 系列文章 磁盘 结构介绍 定位数据 抽象管理…...
12.9 专用指令
目录 状态寄存器传送指令 读CPSR 写CPSR 软中断指令 协处理器指令 协处理器数据运算指令 协处理器存储器访问指令 协处理器寄存器传送指令 伪指令 空指令 LDR 指令 伪指令 状态寄存器传送指令 专门用来读写CPSR寄存器的指令 读CPSR MRS R1,CPSR R1 CPSR 写CP…...
Jvm对象回收算法-JVM(九)
上篇文章介绍了jvm运行时候对象进入老年代的场景,以及如何避免频繁fullGC。 Jvm参数设置-JVM(八) 老年代分配担保机制 这个机制的目的是为了提升效率,在minorGC之前,会有三次判断,之后再次minorGC速度会…...
SpringCloud Alibaba微服务分布式架构组件演变
文章目录 1、SpringCloud版本对应1.1 技术选型依据1.2 cloud组件演变: 2、Eureka2.1 Eureka Server : 提供服务注册服务2.2 EurekaClient : 通过注册中心进行访问2.3 Eureka自我保护 3、Eureka、Zookeeper、Consul三个注册中心的异同点3.1 CP…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
