云原生之开源遥测框架OpenTelemetry(在 Gin 框架中使用 OpenTelemetry 进行分布式追踪和监控)

文章目录

  • 云原生之开源遥测框架OpenTelemetry
    • 背景
      • 什么是可观测性?
    • 什么是 OpenTelemetry?
    • Opentelemetry的主要优势有以下几点:
    • 理解分布式链路
      • 日志
      • Spans
      • 分布式链路
    • 在 Gin 框架中使用 OpenTelemetry 进行分布式追踪和监控
      • 0. 整体思路
      • 1. 初始化 OpenTelemetry
        • 工作流程
      • 2. 集成 Gin 和 OpenTelemetry
        • otelgin 中间件的能力
        • 关于otel-go-contrib-tracer
      • 3. 手动创建 Span
      • 4. 导出数据到
        • 关于路径:/api/v1/traces
    • 其他参考

云原生之开源遥测框架OpenTelemetry

背景

在云原生时代,随着系统应用的不断复杂化和分布式,传统的监控手段已经难以满足需求。因此,OpenTelemetry这一开源遥测框架应运而生,它旨在提供一套统一的解决方案,帮助开发者和运维团队全面了解系统性能状况,迅速定位和解决问题。

什么是可观测性?

可观测性是通过检查系统输出来理解系统内部状态的能力。 在软件的背景下,这意味着能够通过检查遥测数据(包括链路、指标和日志)来理解系统的内部状态。

要使系统可观测,必须对其进行仪表化。也就是说,代码必须发出链路、指标或日志。 然后,仪表化的数据必须发送到可观测性后端。

什么是 OpenTelemetry?

官方文档:https://opentelemetry.io/zh/docs/what-is-opentelemetry/

OpenTelemetry 是一个可观测性框架和工具包, 旨在创建和管理遥测数据,如链路、 指标和日志。 重要的是,OpenTelemetry 是供应商和工具无关的,这意味着它可以与各种可观测性后端一起使用, 包括 Jaeger 和 Prometheus 这类开源工具以及商业化产品。

OpenTelemetry 是云原生计算基金会 (CNCF)的一个项目,是由 OpenTracing 和 OpenCensus 项目合并而成的。原来这两个项目都是为解决同样的问题而创建的: 缺乏一种标准的方法来为代码进行仪表化并将遥测数据发送到可观测性后端。 由于这两个项目都无法独立解决这个问题,所以将其合并成立了 OpenTelemetry, 吸收了双方的优势,提供了统一的解决方案。

OpenTelemetry 不是像 Jaeger、Prometheus 或其他商业供应商那样的可观测性后端。 OpenTelemetry 专注于遥测数据的生成、采集、管理和导出。 OpenTelemetry 的一个主要目标是, 无论应用程序或系统采用何种编程语言、基础设施或运行时环境,你都可以轻松地将其仪表化。 重要的是,遥测数据的存储和可视化是有意留给其他工具处理的。

Opentelemetry的主要优势有以下几点:

支持开源通用标准:Opentelemetry使用开放式协议,使得开发人员可以更加灵活地根据需求选择适合的实现方法,如Jaeger、Zipkin等。这有助于确保数据的一致性和互通性。

跨语言支持:Opentelemetry支持众多编程语言,因此可以应用于任何一种混合语言的架构中。这使得多语言环境下的监控和观测变得更加容易,降低了跨语言集成的复杂性。

统一的SDK和自动化埋点方案:Opentelemetry提供了一套统一的SDK,简化了开发人员的工作。此外,它还支持自动化埋点方案,可以自动收集关键的性能指标,减少了手动配置的工作量。

数据采集和Traces/Metrics/Logs互通:Opentelemetry不仅关注跟踪数据,还关注度量和日志数据。这使得开发人员可以从多个维度全面了解系统性能状况,提高了问题的定位和解决效率。

理解分布式链路

分布式链路让你能够观察请求如何在复杂的分布式系统中传播。它提高了应用程序或系统健康状况的可见性,并让你能够调试那些难以在本地重现的行为。对于分布式系统来说,分布式链路是必不可少的,因为这些系统通常存在不确定性问题,或者过于复杂而无法在本地重现。

要理解分布式链路,你需要了解其各个组成部分的角色:日志、span(跨度)和 trace(链路)。

日志

日志 日志是由服务或其他组件发出的带时间戳的消息。与链路不同,它们不一定与特定的用户请求或事务相关联。在软件中几乎到处都能找到日志。长期以来,开发人员和运维人员一直依靠日志来洞察系统行为。

日志虽然有用,但仅靠它们来追踪代码执行还不够,因为日志通常缺乏上下文信息,比如它们是从哪里被调用的。

当日志作为 span(跨度)的一部分,或者与 trace(链路)和 span 关联起来时,它们的价值就会大大增加。

要深入了解日志以及它们与OpenTelemetry的关系,请参阅日志章节。

Spans

Spans
Span(跨度)是分布式链路中的基本构建块,它代表了一个具体的操作或工作单元。每个 span 都记录了请求中的特定动作,帮助我们了解操作执行过程中发生的详细情况。

一个 span 包含名称、时间相关的数据、结构化的日志消息,以及其他元数据(属性),这些信息共同描绘了该操作的完整画面。

在这里插入图片描述

分布式链路

分布式链路,通常简称为链路,记录了请求(无论是来自应用程序还是终端用户)在多服务架构(如微服务和无服务器应用)中传播的路径。

**一个链路由一个或多个 span 组成。第一个 span 被称为根 span,它代表了一个请求从开始到结束的全过程。**根 span 下的子 span 则提供了请求过程中更详细的上下文信息(或者说,构成了请求的各个步骤)。

如果没有链路,在分布式系统中找出性能问题的根源将会非常具有挑战性。链路通过分解请求在分布式系统中的流转过程,使得调试和理解分布式系统变得不那么令人生畏。

在这里插入图片描述
瀑布图清晰地展示了根 span 与其子 span 之间的父子关系。当一个 span 包含另一个 span 时,这种关系就表现为嵌套结构。

Trace:表示一个完整的请求路径,包含多个 Span
Span:表示请求中的一个操作(如 HTTP 请求、数据库查询)

在 Gin 框架中使用 OpenTelemetry 进行分布式追踪和监控

通过 OpenTelemetry,可以轻松实现 Gin 应用的分布式追踪和监控,提升系统的可观测性。

0. 整体思路

  1. 初始化 OpenTelemetry 的 TracerProvider 和 Exporter。
  2. 使用 otelgin.Middleware 自动追踪 Gin 请求。
  3. 可选:手动创建 Span 以增强追踪信息。
  4. 将数据导出到 Jaeger 或其他后端系统

运行和测试

  1. 启动 Jaeger。
  2. 编写和运行 Go 程序。
  3. 访问 Jaeger UI(http://localhost:16686),查看追踪数据。

1. 初始化 OpenTelemetry

在 Gin 应用启动时,初始化 OpenTelemetry 的 TracerProvider 和 Exporter。

package mainimport ("context""log""time""go.opentelemetry.io/otel""go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp""go.opentelemetry.io/otel/propagation""go.opentelemetry.io/otel/sdk/resource"sdktrace "go.opentelemetry.io/otel/sdk/trace"semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
)func initTracer() (*sdktrace.TracerProvider, error) {// 创建 OTLP HTTP Exporterctx := context.Background()exporter, err := otlptracehttp.New(ctx,otlptracehttp.WithInsecure(),otlptracehttp.WithEndpoint("localhost:4318"), // OpenTelemetry Collector 的地址)if err != nil {return nil, err}// 设置 TracerProvidertp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter),sdktrace.WithResource(resource.NewWithAttributes(semconv.SchemaURL,semconv.ServiceName("gin-server"), // 服务名称)),)otel.SetTracerProvider(tp)// 设置上下文传播otel.SetTextMapPropagator(propagation.TraceContext{})return tp, nil
}

关键字:otlptracehttp.New

  • TracerProvider 负责配置 Tracer 的行为,例如设置采样策略、资源信息(如服务名称)等。TracerProvider创建和管理 Tracer 实例。
  • Exporter 是 OpenTelemetry 中用于将遥测数据(如 Span、Metric)导出到外部系统的组件。它负责将数据发送到后端系统(如 Jaeger、Prometheus、OpenTelemetry Collector 等)。Exporter将 Span 或 Metric 数据导出到指定的后端系统。
工作流程
  1. TracerProvider 创建 Tracer。
  2. Tracer 创建 Span。
  3. Span 完成后,TracerProvider 将 Span 数据传递给注册的 SpanProcessor。
  4. SpanProcessor 将 Span 数据传递给 Exporter。
  5. Exporter 将 Span 数据导出到外部系统(如 Jaeger)。

SpanProcessor 是连接 TracerProvider 和 Exporter 的桥梁。它负责将 Span 数据从 TracerProvider 传递到 Exporter。

  • TracerProvider 是追踪数据的生产者,负责生成和管理 Span
  • Exporter 是追踪数据的消费者,负责将数据发送到外部系统
  • 两者通过 SpanProcessor 连接,共同实现分布式追踪和监控。

2. 集成 Gin 和 OpenTelemetry

使用 otelgin 中间件自动追踪 Gin 的请求。

package mainimport ("log""net/http""time""github.com/gin-gonic/gin""go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
)func main() {// 初始化 OpenTelemetrytp, err := initTracer()if err != nil {log.Fatalf("Failed to initialize OpenTelemetry: %v", err)}defer func() {if err := tp.Shutdown(context.Background()); err != nil {log.Printf("Error shutting down tracer provider: %v", err)}}()// 创建 Gin 应用r := gin.Default()// 添加 OpenTelemetry 中间件r.Use(otelgin.Middleware("gin-server"))// 定义路由r.GET("/hello", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "Hello, OpenTelemetry!",})})// 启动服务器if err := r.Run(":8080"); err != nil {log.Fatalf("Failed to start server: %v", err)}
}

关键字:otelgin.Middleware

在 Gin 应用中,通过 r.Use(otelgin.Middleware("service-name")) 注册 otelgin 中间件。

TracerProvider 是生成 Tracer 的工厂,但 Tracer 实例 由中间件在需要时通过 TracerProvider.Tracer() 自动创建

otelgin 中间件 是 OpenTelemetry 提供的一个专门用于 Gin 框架 的 Instrumentation 工具。它的主要能力是自动追踪 Gin 应用的 HTTP 请求,并生成相应的 Span 数据。

otelgin.WithTracerProvider(provider) // 将 TracerProvider 注入中间件 即 gin注册 Provider

Tracer 由 TracerProvider 在需要时动态创建,中间件会自动处理这些细节。

中间件行为:otelgin.Middleware 会自动使用 TracerProvider 创建 Tracer.

otelgin 中间件的能力

中间件行为:otelgin.Middleware 会自动使用 TracerProvider 创建 Tracer,并在请求处理过程中通过 Span 上下文传递追踪信息

  1. 自动追踪 HTTP 请求
    功能:otelgin 中间件会自动为每个进入 Gin 应用的 HTTP 请求创建 Span
    追踪内容:
    请求的路径(如 /hello)。
    HTTP 方法(如 GET、POST)。
    请求的状态码(如 200、404)。
    请求的耗时(从开始到结束的时间)。
    示例:
    对于 GET /hello 请求,otelgin 会生成一个 Span,记录请求的详细信息。

  2. 上下文传播
    功能:otelgin 中间件会自动处理分布式追踪中的上下文传播。
    场景:
    如果请求中包含了 Trace ID 和 Span ID(例如通过 HTTP 头 traceparent 传递),otelgin 会提取这些信息并继续追踪
    如果请求中没有上下文信息,otelgin 会创建一个新的 Trace ID 和 Span ID。
    作用:确保在分布式系统中,请求的追踪信息能够跨服务传递。

  3. 错误记录
    功能:otelgin 中间件会自动记录请求中的错误信息。
    场景:
    如果请求返回了错误状态码(如 500),otelgin 会将错误信息附加到 Span 中。
    如果请求中发生了 panic,otelgin 会捕获 panic 并记录到 Span 中。

  4. 与 OpenTelemetry 集成
    功能:otelgin 中间件与 OpenTelemetry 的全局 TracerProvider 集成,使用其配置的 Tracer 和 Exporter。
    作用:确保生成的 Span 数据能够被 OpenTelemetry 的 Exporter 导出到后端系统(如 Jaeger、Prometheus)。

otelgin中间件在请求开始时调用TracerProvider的Tracer方法获取Tracer实例。

关于otel-go-contrib-tracer

gin注册otelgin.Middleware中间件时,会自动给 gin context的 key 为otel-go-contrib-tracer存储一个tracker实例,

value := ctx.Value("otel-go-contrib-tracer")
tracer, ok := value.(trace.Tracer)

如上,这个就可以直接拿到 tracker实例,然后可以调spanctx, span = tracer.Start(c.Request.Context(), spanName)返回 一个包含span的context,以及span

3. 手动创建 Span

如果需要手动创建 Span,可以通过 otel.Tracer 实现。

r.GET("/manual", func(c *gin.Context) {// 获取 Tracertracer := otel.Tracer("gin-server")// 创建 Spanctx, span := tracer.Start(c.Request.Context(), "manual-span")defer span.End()// 模拟一些操作time.Sleep(100 * time.Millisecond)c.JSON(http.StatusOK, gin.H{"message": "Manual Span Created!",})
})

总结:
通过ProviderOption注入的TracerProvider会在请求处理时自动创建Tracer实例并存入Context。

4. 导出数据到

japer 官方文档:https://www.jaegertracing.io/docs/1.66/apis/
jaeger的本地搭建和快速可以参考本人文章Jaeger安装和简单使用

可以选择将链路追踪的数据发送至 Jaeger,通过 Jaeger UI 查看

使用 OTLP(OpenTelemetry Protocol) 导出器将追踪数据发送到 Jaeger。

自 v1.35 以来,Jaeger 后端可以通过原生的 OpenTelemetry 协议(OTLP)接收来自 OpenTelemetry SDK 的跟踪数据。现在不再需要为 OpenTelemetry SDK 配置 Jaeger 导出程序,也不需要在 OpenTelemetry SDK 和 Jaeger 后端之间部署 OpenTelemetry 收集器。

如果你希望使用 OTLP(OpenTelemetry Protocol) 导出器将追踪数据发送到 Jaeger 或其他支持 OTLP 的后端(如 OpenTelemetry Collector),可以使用 go.opentelemetry.io/otel/exporters/otlp/otlptrace 包。OTLP 是 OpenTelemetry 的通用协议,支持通过 HTTP 或 gRPC 传输数据。

在这里插入图片描述
以下是使用 OTLP 导出器(支持 gRPC 和 HTTP)的示例代码。
将 OpenTelemetry 的追踪功能集成到 Gin 框架中,并使用 OTLP HTTP 导出器将追踪数据发送到 Jaeger 或 OpenTelemetry Collector:

  1. traceotel 包实现
package traceotelimport ("context""log""github.com/gin-gonic/gin""go.opentelemetry.io/otel""go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp""go.opentelemetry.io/otel/propagation""go.opentelemetry.io/otel/sdk/resource"sdktrace "go.opentelemetry.io/otel/sdk/trace"semconv "go.opentelemetry.io/otel/semconv/v1.17.0""go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
)// Register 创建一个 Gin 中间件,用于集成 OpenTelemetry 追踪功能
func Register(appname string, endpoint string) gin.HandlerFunc {opts := []otelgin.Option{ProviderOption(appname, endpoint),PropagationExtractOption(),}return otelgin.Middleware(appname, opts...)
}// ProviderOption 初始化并返回一个 TracerProvider
func ProviderOption(appname string, endpoint string) otelgin.Option {return otelgin.WithTracerProvider(func() (*sdktrace.TracerProvider, error) {// 创建 OTLP HTTP Exporterctx := context.Background()exporter, err := otlptracehttp.New(ctx,otlptracehttp.WithInsecure(), // 使用非安全连接(无 TLS)otlptracehttp.WithEndpoint(endpoint), // 追踪数据收集端点)if err != nil {return nil, err}// 设置 TracerProvidertp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter), // 使用批处理导出器sdktrace.WithResource(resource.NewWithAttributes(semconv.SchemaURL,semconv.ServiceName(appname), // 服务名称)),)return tp, nil})
}// PropagationExtractOption 配置上下文传播器
func PropagationExtractOption() otelgin.Option {return otelgin.WithPropagators(propagation.TraceContext{})
}
  1. 在 Gin 应用中使用 traceotel 包,并启动一个简单的 HTTP 服务器。
package mainimport ("log""net/http""github.com/gin-gonic/gin""your-project/traceotel" // 替换为实际的包路径
)func main() {// 创建 Gin 应用r := gin.Default()// 注册追踪中间件r.Use(traceotel.Register("gin-server", "localhost:4318"))// 定义路由r.GET("/hello", func(c *gin.Context) {// 模拟业务逻辑c.JSON(http.StatusOK, gin.H{"message": "Hello, OpenTelemetry!",})})// 启动服务器if err := r.Run(":8080"); err != nil {log.Fatalf("Failed to start server: %v", err)}
}
  • Register 函数通过 otelgin.Middleware 将 OpenTelemetry 的追踪功能集成到 Gin 框架中。
  • ProviderOption 函数用于初始化 TracerProvider,并配置 OTLP 导出器。
  • PropagationExtractOption 函数用于配置上下文传播器。
  1. 为什么不需要指定路径?
    OTLP 是 OpenTelemetry 的通用协议,用于传输遥测数据(如 Trace、Metric、Log)。
    它已经定义了默认的路径:
    gRPC:默认路径是 /opentelemetry.proto.collector.trace.v1.TraceService/Export。
    HTTP:默认路径是 /v1/traces。
    客户端只需要指定 endpoint 的主机和端口(如 localhost:4318),路径由 OTLP 协议自动处理。
  • 使用 OTLP 导出器时,客户端只需要指定 endpoint 的主机和端口,无需包含路径。
  1. 为什么我使用 /api/v1/traces Jaeger可以收到
    你使用 /api/v1/traces 时,Jaeger 仍然可以收到数据,是因为 Jaeger 的 HTTP 接收器支持多种路径,包括 /api/v1/traces 和 /v1/traces。

Jaeger 的 HTTP 接收器默认支持以下路径:

  • /api/v1/traces:这是 Jaeger 的传统路径,用于接收追踪数据。
  • /v1/traces:这是 OpenTelemetry 的 OTLP 协议默认路径。
    当 Jaeger 启动时,它的 HTTP 接收器会监听多个路径,因此无论你使用 /api/v1/traces 还是 /v1/traces,数据都能被正确接收。
  1. 为什么 /api/v1/traces 可以工作?
  • Jaeger 的兼容性设计:
    Jaeger 为了兼容不同客户端(如 OpenTelemetry、Jaeger 原生客户端等),支持多种路径。
    即使你显式指定 /api/v1/traces,Jaeger 仍然能够识别并处理数据。
  • OpenTelemetry 的灵活性:
    OpenTelemetry 的 OTLP 导出器允许你指定完整的 URL(包括路径),例如 http://localhost:4318/api/v1/traces。
    当你指定路径时,OTLP 导出器会直接将数据发送到该路径,而不会覆盖默认路径。
关于路径:/api/v1/traces

不同的可观测性后端如 Jaeger、Zipkin、Prometheus 都支持这一标准端点,实现了遥测数据的统一收集。

  • /api/v1/traces 是 Jaeger 的 HTTP 接收器的默认路径,通常用于直接使用 Jaeger 客户端的项目。
  • /v1/traces 是 OTLP 接收器的默认路径,是 OpenTelemetry 的通用协议。
    推荐使用 OTLP,OpenTelemetry 正在逐步成为可观测性领域的事实标准。因为它更通用且支持多种后端。如果你看到 /api/v1/traces,可能是因为项目直接使用了 Jaeger 客户端或旧版配置。

Jaeger 提供了两种主要的接收器来接收追踪数据:

  • Jaeger 的 HTTP 接收器:
    默认路径为 /api/v1/traces。
    这是一种专为 Jaeger 设计的接收器,主要用于接收 Jaeger 客户端发送的 JSON 或 Thrift 格式的追踪数据。
    例如,Jaeger 的 Go 客户端会通过 HTTP POST 请求将数据发送到 http:///api/v1/traces。

  • OTLP 接收器:
    默认路径为 /v1/traces。
    这是 OpenTelemetry 的通用协议(OTLP),支持通过 gRPC 或 HTTP 传输数据。
    使用 OTLP 时,客户端只需要指定 endpoint 的主机和端口,路径由协议自动处理

我们可以参考阿里日志服务文档 https://help.aliyun.com/zh/sls/user-guide/import-trace-data-from-opentelemetry-to-log-service,可以看到使用的 /v1/traces 路径。

接入点信息

  • HTTPS协议的接入点为${endpoint}/opentelemetry/v1/traces,例如https://test-project.cn-hangzhou-intranet.log.aliyuncs.com/opentelemetry/v1/traces。

  • gRPC协议的接入点为${endpoint}:10010,例如test-project.cn-hangzhou-intranet.log.aliyuncs.com:10010。

其他参考

通过OpenTelemetry监控gRPC调用
Monitor gRPC calls with OpenTelemetry - explained with a Golang example
https://dev.to/signoz/monitor-grpc-calls-with-opentelemetry-explained-with-a-golang-example-350o

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

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

相关文章

【蓝桥杯速成】| 11.回溯 之 子集问题

题目一:子集 问题描述 78. 子集 - 力扣(LeetCode) 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例…

Nginx目录结构

Nginx目录结构 ​ Nginx 的安装目录结构可能会因安装方式(如使用包管理器、源码编译等)和操作系统的不同而有所差异。以下是通过在线安装时,Nginx 默认的目录结构,以及各目录和文件的作用。 yum install nginx查询nginx [rootRo…

2.(vue3.x+vite)使用vue-router

前端技术社区总目录(订阅之前请先查看该博客) 效果预览 路由配置的“/”与“helloWorld”都可以访问到以下内容 http://10.11.0.87:4000/#/ http://10.11.0.87:4000/#/helloWorld 1:安装vue-router npm i vue-router 2:创建router文件 在src的目录下创建router文件夹…

后端返回了 xlsx 文件流,前端怎么下载处理

当后端返回一个 .xlsx 文件流时,前端可以通过 JavaScript 处理这个文件流并触发浏览器下载。 实现步骤 发送请求获取文件流: 使用 fetch 或 axios 等工具向后端发送请求,确保响应类型设置为 blob(二进制数据流)。 创建…

HTML5拖拽功能教程

HTML5拖拽功能教程 简介 HTML5引入了原生拖放(Drag and Drop)API,使开发者能够轻松实现网页中的拖拽功能,无需依赖第三方库。拖拽功能可以大大提升用户体验,适用于文件上传、列表排序、看板系统等多种交互场景。本教程将带您全面了解HTML拖…

VUE3 路由配置

1.下载 VueRouter 模块 在命令行中输入 yarn add vue-router 2.导⼊相关函数 在自己创建的router/index.js 文件中 import { createRouter, createWebHashHistory } from vue-router 3.创建路由实例 在自己创建的router/index.js 文件中 const theFirstRouter ()>{return…

历史序列影像 Esri的World Imagery Wayback简介

Esri的World Imagery Wayback是一个专注于提供历史卫星影像的在线平台,由全球领先的地理信息系统(GIS)技术提供商Esri开发。该平台整合了多源卫星影像数据,允许用户回溯特定区域在不同时间点的影像变化,支持时间序列分…

golang结构体与指针类型

结构体与指针类型 指针类型字段 具名字段 举例 package struct_knowledgeimport "fmt"//结构体字段为指针类型 func StructWithPoint(){type Student struct{name *string}var lisa Studentfmt.Printf("赋值前,Student的实例的值%#v\n",lisa)//错误的赋…

NetMizer-日志管理系统-远程命令执行漏洞挖掘

漏洞描述:NetMizer 日志管理系统 cmd.php中存在远程命令执行漏洞,攻击者通过传入 cmd参数即可命令执行 1.fofa搜素语句 title"NetMizer 日志管理系统" 2.漏洞验证 网站页面 验证POC /data/manage/cmd.php?cmdid

Contactile三轴触觉传感器:多维力感赋能机器人抓取

在非结构化环境中,机器人对物体的精准抓取与操作始终面临巨大挑战。传统传感器因无法全面感知触觉参数(如三维力、位移、摩擦),难以适应复杂多变的场景。Contactile推出的三轴触觉力传感器,通过仿生设计与创新光学技术…

OpenCV三维解算常用方法C++

如果标定过程是通过OpenCV张正友标定法实现的,得到的内参外参保存在.txt文件中是这样的形式: ① 内参intrinsics.txt: ② 外参extrinsics.txt: 那么可以通过如下方法读取.txt文件获取左右相机内外参,主要包括三维解算…

栈和队列相关知识题目

栈的底层原理 栈(Stack)是一种后进先出(LIFO)​的线性数据结构,所有操作(如插入、删除)仅在栈顶进行。它的底层实现可以是数组或链表,具体取决于编程语言和应用场景。 1.基于数组实…

【实战案例】永洪vividime:精准赋能零售行业,实现数据洞察与业务增长

在零售食品行业变革加速、市场竞争白热化的背景下,XX集团作为休闲食品领域头部企业,面临消费趋势变化、宏观经济承压及业绩增长乏力的多重挑战。为破解增长困境,集团将“收入增长金额”确立为核心战略指标(北极星指标)…

一些题目记录

别人面经题目记录 https://zhuanlan.zhihu.com/p/32626732052 实现 NMS,七八次,很高频; 实现 MultiHeadSelfAttention,大概 三四次; 用 Numpy 或者 List 实现MLP 的前向和反向,4次; Leetcode …

面试题分享-多线程顺序打印奇偶数

目录 1.题目详情 2.解题思路 2.1.分析题目 2.2.解析思路 3.代码实现 4.运行结果 1.题目详情 昨天刷抖音,遇到一个面试题,描述如下: 请使用两个线程,分别顺序交替打印奇数和偶数,直到10为止。例如有两个线程&#…

模型 杜根定律

系列文章分享模型,了解更多👉 模型_思维模型目录。信心>能力、行动导向、未来时态。 1 杜根定律的应用 1.1 公共政策博弈——底特律市长杜根的保险改革攻坚战 核心挑战:底特律市长Mike Duggan面临汽车保险费率畸高导致居民陷入贫困循环的…

关于在vscode中的Linux 0.11 应用程序项目的生成和运行

首先我们需要需要查看镜像文件 查看软盘镜像文件 floppyb.img 中的内容 在 VSCode 的“Terminal”菜单中选择“Run Build Task...”,会在 VSCode 的顶部中间位置弹出一个 可以执行的 Task 列表,选择其中的“打开 floppyb.img”后会使用 Floppy Editor …

使用CSS3实现炫酷的3D视差滚动效果

使用CSS3实现炫酷的3D视差滚动效果 这里写目录标题 使用CSS3实现炫酷的3D视差滚动效果项目概述核心技术实现1. 3D空间的创建2. 视差层级设置3. 动画效果实现流星动画月亮发光效果 技术难点与解决方案1. 层级重叠问题2. 性能优化3. 响应式适配 开发心得总结 项目概述 在这个项目…

作业12 (2023-05-15 指针概念)

第1题/共11题【单选题】 关于指针的概念,错误的是:( ) A.指针变量是用来存放地址的变量 B.指针变量中存的有效地址可以唯一指向内存中的一块区域 C.野指针也可以正常使用 D.局部指针变量不初始化就是野指针 回答正确 答案解析: A:正确,指针变量中存储的是一个地址,指…

【ESP32S3】esp32获取串口数据并通过http上传到前端

通过前面的学习(前面没发过,因为其实就是跑它的demo)了解到串口配置以及开启线程实现功能的工作流程,与此同时还有esp32作为STA节点,将数据通过http发送到服务器。 将这两者联合 其实是可以得到一个:esp32获…