云原生之開源遙測框架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.pswp.cn/bicheng/74509.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/74509.shtml
英文地址,請注明出處:http://en.pswp.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獲…