Go微服务实战——服务的监控与链路追踪(监控数据可视化)

链路追踪背景

对于早期系统或者服务来说,开发人员一般通过打日志的方式来进行埋点(常用的数据采集方式),然后再根据日志系统和性能监控定位及分析问题。对于单体的应用通过日志系统完全可以定位到问题,从而排查异常。但是对于微服务来说,各个服务之前存在调用关系,服务之间是相互依赖的,一个服务异常可能其由于其他服务引起的,那么就需要查看和该服务相关联的其他服务的所有日志信息排查时那个服务引造成的。

随着服务数量的增多和内部调用链的复杂化,开发者仅凭借日志和性能监控,难以做到全局的监控,运维难度极大。为了解决这个问题,业界推出了分布式链路追踪组件。Google 内部开发了 Dapper 用于收集更多的复杂分布式系统的行为信息;同时,也有很多其他公司开发了自己的链路追踪组件Twitter 开源了分布式链路追踪组件 Zipkin等。

Dapper,大规模分布式系统的跟踪系统

服务监控应该至少包含如下的内容:

在这里插入图片描述

微服务 - 应用性能监测 · 链路追踪 · 概念规范 · 产品接入 · 方法级追踪 · 创建指标跨度

微服务 - Nginx网关 · 进程机制 · 限流熔断 · 性能优化 · 动态负载 · 高可用

分布式链路追踪

分布式链路追踪(Distributed Tracing)是一种用于监视和诊断分布式系统性能问题的技术。在大规模的分布式系统中,由于服务之间的复杂交互,单个请求可能会在多个服务之间传输,并涉及多个计算节点和数据存储。在这样的环境中,出现性能问题时,追踪问题的根本原因可能会非常困难。

分布式链路追踪通过在整个请求处理路径上添加唯一标识符,并记录请求在不同服务和组件之间的传输情况和时间戳,从而使开发人员能够跟踪请求的完整生命周期。当出现性能问题时,开发人员可以利用这些信息来确定瓶颈所在,优化系统性能。

常见的分布式链路追踪工具包括Zipkin、Jaeger和OpenTelemetry等。这些工具提供了可视化界面和分析工具,帮助开发人员更轻松地理解分布式系统的运行状况。

在dapper中介绍了Tracing 链路追踪是一种用于分析和监视应用程序的方法,尤其是那些使用微服务体系结构构建的分布式的应用程序。一个完整请求链路的追踪(TraceID)用于查出本次请求调用的所有服务/接口/组件等,调用的每个服务/接口/组件等都被称为跨度(Span),用来记录调用顺序,上游跨度(ParenetID)用来记录调用的层级关系。调用时间周期Timestamp,是把请求发出、接收、处理的时间都记录下来。跨度还可以记录一些其它属性信息,比如发起调用服务名称、被调服务名称、返回结果、IP、请求状态、日志、故障等。最后再把拥有相同(TraceID)的跨度(Span)合成一个更大范围的试图,就形成了一个完整的单次请求调用链。

这个概念都是Google Dapper论文中提出的:

在这里插入图片描述
Google-Dapper 是 Google 内部长期经过打磨后形成的产品,于2010年公布,对外是一篇论文,讲述的是分布式链路追踪的理论和 Dapper 的设计思想。大致由 [植入应用、收集跟踪数据、图形化UI] 三部分组成。后续市场的发展,有很多链路追踪系统也是基于 Dapper 论文的思想和理论为基础的。

通过统一服务监控追踪标准,OpenTracing 项目横空出世并得到开发者的认可,为分布式追踪,提供统一的概念、规范和接口。它是一个轻量级的标准化层,并不是功能实现代码,它只是为跟踪数据,用代码定义了一套数据模型,和一套API,是供统一遵循的规范,用于在应用程序中创建和管理这些数据模型。现在大多数链路跟踪产品系统都在尽量兼容遵循 OpenTracing 设计原则。

在这里插入图片描述

OpenTracing官方标准-中文版

opentracing

OpenTracing中文文档

OpenTracing 仅包含 Model 和 API 的定义,不会将产生的数据发送到第三方;需要进一步集成第三方的SDK,发送到第三方并呈现。

OpenTracing

OpenTracing通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。

  • trace:race代表了一个事务或者流程在(分布式)系统中的执行过程
  • span: span表示一个调用,这个调用可以使一个方法,一个数据库,一个rpc服务等。

虽然分布式系统很复杂,但是使用OpenTracing让监控一个分布式调用过程简单化,并快速配置一个监控系统。

OpenTracing 有一套自己的一个 Library 库定义了一套通用的数据上报接口,要求各个分布式追踪系统都来实现这套接口。这样一来,应用程序只需要对接 OpenTracing,而无需关心后端采用的到底是什么分布式追踪系统,因此开发者可以无缝切换分布式追踪系统,也使得在通用代码库增加对分布式追踪的支持成为可能。

Twitter Zipkin是一款分布式链路追踪组件,由 Twitter 开源,同样也兼容 OpenTracing API:它基于 Google Dapper 的论文设计。

在这里插入图片描述
https://github.com/openzipkin

云原生链路监控组件 Uber Jaeger受 Dapper 和 OpenZipkin 的启发,由 Uber 开源的分布式追踪系统,兼容 Open Tracing API。它用于微服务的监控和排查,支持分布式上下文传播、分布式事务的监控、报错分析、服务的调用网络分析以及性能/延迟优化。Jaeger 的服务端使用 Go 语言实现。

Jaeger架构:

在这里插入图片描述

在这里插入图片描述

OpenTelemetry

基于 OpenTracing,新项目 OpenTelemetry 是 OpenTracing + OpenCensus 的产物,包含一组用于分布式跟踪和监视的工具的集合,支持集成更多的框架和语言。它仅用来生成/收集和导出更多种遥测数据(指标/链路/日志),可将数据发送到任何可观测性后端进行分析。旨在提供一种检测跟踪代码的标准方法,收集有关通过系统的请求流的数据,以帮助分析软件的性能和行为。同样,数据存储和可视化呈现留给其它工具去完成(如Jaeger、Prometheus)。

OpenTelemetry

OpenTelemetry GO API

OpenTelemetry GO API中文文档

概念

  1. 可观测性

可观测性使我们能够从外部了解一个系统,通过提出关于该系统的问题而无需了解其内部工作方式,因此应用程序代码必须发出诸如 信号 的东西,例如 跟踪、指标 和 日志,通过这些信号来观测系统。

日志是由服务或其他组件发出的带时间戳的消息。跨度表示一项工作或操作的单位。跟踪,记录了请求(由应用程序或最终用户发起)在多服务架构中传播时所经过的路径。为了使系统可观察,必须进行仪表化:也就是说,系统组件的代码必须发出跟踪、指标和日志。

如何生成跟踪,指标和日志呢,可以通过使用 OpenTelemetry API 进行手动仪表化,在特点的地方的生成。

配置OpenTelemetry API为了创建跟踪或跨度,你需要先创建一个tracer和/或meter provider。通常情况下,我们建议SDK应该为这些对象提供一个单一的默认provider。然后你将从该provider获取一个tracer或meter实例,跟踪和快读都是从这个实力创建。

如果你正在构建一个服务进程,你还需要使用适当的选项配置OpenTelemetr SDK,以将你的遥测数据导出到某个分析后端。

一旦你配置了API和SDK,你就可以自由地通过从provider中获取的tracer和meter对象创建跟踪和度量事件,创建遥测数据。

一旦你创建了遥测数据,你就需要将其发送到某个地方。OpenTelemetry支持从你的进程直接发送数据到分析后端的两种主要方法:直接从进程发送或通过OpenTelemetry Collector进行代理发送。

在这里插入图片描述

专业术语

OpenTelemetry API:在OpenTelemetry项目中,用于定义如何根据数据源生成遥测数据。

Exporter:提供将遥测数据传递给消费者的功能。由仪表化库和收集器使用。

Metric:(度量)将数据点记录为时间序列,包括原始测量值或预定义的聚合

OTel:OpenTelemetry的缩写。

OTelCol:OpenTelemetry Collector的缩写。

SDK:软件开发工具包的缩写。指实现OpenTelemetryAPI的遥测SDK的库。

Span:跨度,表示Trace内的单个操作。

Trace:跟踪,Span的DAG,其中Span之间的边被定义为父/子关系。

Tracer:跟踪器,负责创建Span。

在这里插入图片描述

使用两个开源项目:OpenTelemetryJaeger

OpenTelemetry 可以用于从应用程序收集数据。它是一组工具、API 和 SDK 集合,我们可以使用它们来检测、生成、收集和导出遥测数据(指标、日志和追踪),以帮助分析应用的性能和行为。

在这里插入图片描述
OpenTelemetry 提供了一个与供应商无关的可观测性标准,因为它旨在标准化跟踪的生成。通过 OpenTelemetry,我们可以将检测埋点与后端分离。这意味着我们不依赖于任何工具(或供应商)。

OpenTelemetry 为我们提供了创建跟踪数据的工具,为了获取这些数据,我们首先需要检测应用程序来收集数据。为此,我们需要使用 OpenTelemetry SDK。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
应用程序的遥测数据可以发送到 OpenTelemetry Collectors 收集器。

jaeger是用来可是监控的数据。

链路追踪实现

  1. 步骤

在OpenTelemetry中,将数据发送到指定的UI工具通常涉及以下几个步骤:

  • Instrumentation(仪表化):首先,你需要在你的应用程序中进行仪表化。这包括在代码中插入适当的代码以捕获关键事件和跟踪。这些事件可以是HTTP请求、数据库查询、函数调用等。OpenTelemetry提供了一系列语言库和框架的支持,使得在你的应用中添加仪表化变得相对简单。(基于OpenTelemetry API 和OpenTelemetry SDK实现)

  • 数据导出器(Exporters):OpenTelemetry提供了各种Exporter,用于将从应用程序中收集的跟踪数据、指标和日志发送到不同的目的地。你需要选择适合你用例的Exporter。例如,如果你想将数据发送到UI工具,你可能需要使用与该UI工具集成的Exporter,或者编写自定义的Exporter。

  • 配置Exporter:一旦选择了Exporter,你需要配置它,以确保数据被正确发送到UI工具。配置通常包括指定目标地址、端口、认证信息等。

  • 启动应用程序:最后,你需要启动你的应用程序,让它开始收集跟踪数据、指标和日志,并将其发送到UI工具。

  • 在UI工具中配置和查看数据:最终,在UI工具中配置数据源,并查看你的应用程序的跟踪数据、指标和日志。这可能涉及到在UI工具中创建仪表板或设置警报,以便监视应用程序的性能和健康状况。

  1. 安装jaeger ui工具

除了jaeger也可以选择其他工具。

在这里插入图片描述
jaeger官网

在jaeger中数据集采集的方式有两种jaeger-clientjaeger-agent前者是整合其他语言的SDK,后者是go语言专属的api,它们的实例将opentracingopentelemetry采集的数据发送到到jaeger-collector,再由jaeger-collector缓存存储到数据库中,最后jaeger-ui工具展示数据,jaeger-query数据查询数据。

jaeger提供了All in One一件安装jaeger所有的插件,参考官网

安装完之后输入地址http://localhost:16686如下所示:

在这里插入图片描述

Jeager官方文档翻译之——jeager架构(个人笔记)感谢作者Iron。

  1. 数据采集

jaeger-clientjaeger-agent发送数据是系统自动的,只需要开发者配置好otel-exporter即可,将其设置为otel-jaeger SDK的jaeger-exporter,这样系统会自动创建jaeger-client或者jaeger-agent向,远程jaeger-collector发送采集的信息。

现在到了关键的一部,采集程序信息,用于仪表化、生成、收集和导出诸如跟踪、度量、日志等遥测数据。

什么是OpenTelemetry?

Opentelemetry Traces数据模型介绍

otel-exporter

采集的信息需要发送到指定的collector才有意义,所以需要配置otel-exporter。各个框架都配置了exporter,例如jaeger-exporter等。

import "go.opentelemetry.io/otel/exporters/jaeger"
 
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://localhost:14268/api/traces")))
Tracer Provider

Tracer Provider是 Tracers 的工厂,在大多数应用程序中,Tracer Provider 会初始化一次,并且其生命周期与应用程序的生命周期相匹配。Tracer Provider 初始化还包括 Resource 和 Exporter 初始化。这通常是使用 OpenTelemetry 进行跟踪的第一步。在某些语言的 SDK 中,已经为您初始化了全局 Tracer Provider。

//设置Exporter,将Jaeger的exporter设置为otel的Exporter
// 返回以Jaeger为exporter的traceProvider
tp, tpErr := tracerprovicer.JaegerTraceProvider()
if tpErr != nil {
	log.Fatal(tpErr)
}
// 设置otel的provider
otel.SetTracerProvider(tp)
// 设置传播提取器
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))

Tracer Provider 初始化还包括 Resource 和 Exporter 初始化

Tracer Provider的初始化还有一部分在Tracer Exporter中。

Tracer Exporter

跟踪导出器将跟踪发送给消费者。该使用者可以是用于调试和开发时的标准输出、OpenTelemetry Collector 或您选择的任何开源或供应商后端。

package tracerprovicer

import (
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

func JaegerTraceProvider() (*sdktrace.TracerProvider, error) {
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://localhost:14268/api/traces")))
	if err != nil {
		return nil, err
	}
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exp),
		sdktrace.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String("todo-service"),
			semconv.DeploymentEnvironmentKey.String("production"),
		)),
	)
	return tp, nil
}
Tracer

Tracer 创建的跨度包含有关给定操作并记录操作信息。

// 创建trace实例
tr := otel.Tracer("redis-conn")
Span

Span 是 Traces 的构建块,是追踪的基本单元。

spanCtx, span := tr.Start(c.Request.Context(), "get-todo")
span.End()
Context(上下文连接)

上下文传播是实现分布式跟踪的核心概念。通过上下文传播,Span 可以相互关联并组装成跟踪,无论 Span 是在哪里生成的。

总结

tracer跨度代表一个工作或操作单元,Span 是 Traces 的构建块,在 OpenTelemetry 中包含以下信息:

{
 "trace_id": "7bba9f33312b3dbb8b2c2c62bb7abe2d",
 "parent_id": "",
 "span_id": "086e83747d0e381e",
 "name": "/v1/sys/health",
 "start_time": "2021-10-22 16:04:01.209458162 +0000 UTC",
 "end_time": "2021-10-22 16:04:01.209514132 +0000 UTC",
 "status_code": "STATUS_CODE_OK",
 "status_message": "",
 "attributes": {
 "net.transport": "IP.TCP",
 "net.peer.ip": "172.17.0.1",
 "net.peer.port": "51820",
 "net.host.ip": "10.177.2.152",
 "net.host.port": "26040",
 "http.method": "GET",
 "http.target": "/v1/sys/health",
 "http.server_name": "mortar-gateway",
 "http.route": "/v1/sys/health",
 "http.user_agent": "Consul Health Check",
 "http.scheme": "http",
 "http.host": "10.177.2.152:26040",
 "http.flavor": "1.1"
 },
 "events": [
 {
 "name": "",
 "message": "OK",
 "timestamp": "2021-10-22 16:04:01.209512872 +0000 UTC"
 }
 ]}

完整代码实例如下:

package tracerprovicer

import (
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

func JaegerTraceProvider() (*sdktrace.TracerProvider, error) {
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://localhost:14268/api/traces")))
	if err != nil {
		return nil, err
	}
	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exp),
		sdktrace.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String("todo-service"),
			semconv.DeploymentEnvironmentKey.String("production"),
		)),
	)
	return tp, nil
}
package main

import (
	"github.com/gin-gonic/gin"
	"github.com/redis/go-redis/v9"
	"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/propagation"
	"log"
	"net/http"
	"oteldemo/tracing"
)

var (
	cli *redis.Client
	r   *gin.Engine
)

func main() {
	//设置Exporter,将Jaeger的exporter设置为otel的Exporter
	// 返回以Jaeger为exporter的traceProvider
	tp, tpErr := tracerprovicer.JaegerTraceProvider()
	if tpErr != nil {
		log.Fatal(tpErr)
	}
	// 设置otel的provider
	otel.SetTracerProvider(tp)
	// 设置传播提取器
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))

	// 创建gin实例
	ginWebServer()

	//gin OpenTelemetry工具化
	r.Use(otelgin.Middleware("todo-service"))
	r.GET("/todo", func(c *gin.Context) {
		// 创建trace实例
		tr := otel.Tracer("redis-conn")
		// 创建span实例
		spanCtx, span := tr.Start(c.Request.Context(), "get-todo")

		span.End()
		tp.Shutdown(spanCtx)

		c.JSON(http.StatusOK, "ok")
	})

	r.Run(":8001")
}

func ginWebServer() {
	r = gin.Default()
}

func redisConn() {
	// connectMongo
	cli = redis.NewClient(&redis.Options{
		Addr: "127.0.0.1:6379",
	})
	return
}

jaeger collector默认地址:http://localhost:14268/api/traces

在这里插入图片描述

项目地址:open-telemetry-demo

在初始化Tracer Provider时同时初始化otel-exporterotel-resourcesemconv.ServiceNameKey.String("todo-service")部分是填写服务名称,semconv.DeploymentEnvironmentKey.String("production")部分是填写开发环境。

对于每一个provider创建的tr := otel.Tracer("redis-conn")填写tracer名称,spanCtx, span := tr.Start(c.Request.Context(), "get-todo")填写的是span名称。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL B+树索引 和 Redis 中跳表索引的区别

一、MySQL B树索引 和 Redis 中跳表索引 在 MySQL 中常用的索引是 B树索引,而 Redis 中,例如 zset 使用的的是跳表索引,两者有什么区别呢,MySQL 为什么不使用 跳表 呢?或者说 Redis 中为什么不使用 B树 呢&#xff1f…

【Flutter 面试题】Flutter如何进行本地存储和缓存数据?

【Flutter 面试题】Flutter如何进行本地存储和缓存数据? 文章目录 写在前面口述回答补充说明实际案例完整代码示例运行结果详细说明 写在前面 🙋 关于我 ,小雨青年 👉 CSDN博客专家,GitChat专栏作者,阿里云…

分布式之Skywalking

Skywalking skywalking是一个apm系统,包含监控,追踪,并拥有故障诊断能力的 分布式系统 一、Skywalking介绍 1.什么是SkyWalking Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的产品,它同时吸收了Zipkin /Pinpoint …

力扣Lc19--- 268. 丢失的数字(java版)-2024年3月20日

1.题目描述 2.知识点 (1)比如数组里面有n个数,然后计算这n个数的总和(用等差求和数列计算),然后减去数组的和,用总和减去数组和即为所得 (2)加强型 for 循环(也称为 for-each 循环&…

[C语言]指针笔试题

题一、 //结构体的大小是20个字节 struct Test{int Num;char *pcName;short sDate;char cha[2];short sBa[4];}*p;//假设p 的值为0x100000。 如下表表达式的值分别为多少? //已知,结构体Test类型的变量大小是20个字节 int main(){printf("%p\n"…

【transformer模型】一篇文章讲透

目录 引言 一、引言 二、Transformer模型的基本结构 1 编码器(python代码片段) 2 解码器 三、自注意力机制的工作原理 四、Transformer模型的应用场景 1 机器翻译 2 文本摘要 3 情感分析 4 语音识别 五、Transformer模型的发展现状及未来趋势…

【C语言】结构体内存对齐问题

1.结构体内存对齐 我们已经基本掌握了结构体的使用了。那我们现在必须得知道结构体在内存中是如何存储的?内存是如何分配的?所以我们得知道如何计算结构体的大小?这就引出了我们今天所要探讨的内容:结构体内存对齐。 1.1 对齐规…

Python利用pygame实现飞机大战游戏

文章目录: 一:运行效果 1.演示 2.思路和功能 二:代码 文件架构 Demo 必备知识:python图形化编程pygame游戏模块 一:运行效果 1.演示 效果图◕‿◕✌✌✌ Python利用pygame实现飞机大战游戏运行演示 参考&#x…

web集群-lvs-DR模式基本配置

目录 环境: 一、配置RS 1、安装常见软件 2、配置web服务 3、添加vip 4、arp抑制 二、配置LVS 1、添加vip 2、安装配置工具 3、配置DR 三、测试 四、脚本方式配置 1、LVS-DR 2、LVS-RS 环境: master lvs 192.168.80.161 no…

YOLOv5改进系列:新的颈部Eff-QAFPN(Efficientrep)结构助力涨点

一、论文理论 本文提出一种硬件友好的卷积神经网络结构,该结构类似于repvgg。在衡量网络效率时,经常使用Flops或者参数量,这些衡量指标对于硬件计算能力和内存带宽不敏感。因此,如何设计一个神经网络架构,使其有效地利用硬件计算能力和内存带宽是至关重要的。 论文地址:E…

Docker如何端口映射?

Docker是一种流行的开源容器化平台,它允许开发者将应用程序和其依赖资源打包到一个称为容器的可移植单元中。Docker提供了强大的管理和部署工具,使得应用程序可以在不同的环境中运行,无需担心环境配置的问题。在使用Docker部署应用程序时&…

【动态规划】【同余前缀和】【多重背包】[推荐]2902. 和带限制的子多重集合的数目

本文涉及知识点 动态规划汇总 C算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 C算法:滑动窗口总结 多重背包 LeetCode2902. 和带限制的子多重集合的数目 给你一个下标从 0 开始的非负整数数组 nums 和两个整数 l 和 r 。 请你…

golang常用库之-golang常用库之-ladon包 | 基于策略的访问控制

文章目录 golang常用库之-ladon包 | 基于策略的访问控制概念使用策略 条件 Conditions自定义conditionLadon Condition使用示例 持久化访问控制(Warden) 结合 Gin 开发一个简易 ACL 接口参考 golang常用库之-ladon包 | 基于策略的访问控制 https://github.com/ory/ladon Lado…

7 配置模板虚拟机

使用远程连接工具finalShell连接虚拟机后,接下来我们使用yum命令完成一些基础软件包的安装,以及将咱们新建的用户赋予管理员权限,最后关闭防火墙和卸载自带的JDK。 1. 安装epel-release 我们将使用yum命令进行安装,首先测试是否与…

海外重要行业媒体:知名服务商IntoTheBlock现已集成波场TRON网络分析数据

近日,领先链上分析服务提供商 IntoTheBlock 宣布已将波场 TRON 网络集成至其市场情报套件。该合作引发多家海外加密媒体关注,Crypto Slate、Crypto Briefing等均对此进行了报道,称此次合作意义深远,能帮助数百万用户更深入地了解波场TRON生态系统。 报道表示,波场TRON网络规模大…

AI时代Python金融大数据分析实战:ChatGPT让金融大数据分析插上翅膀

❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。2022年度博客之星评选TOP 10🏆,Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作…

[pytorch] detr源码浅析

[pytorch] detr源码浅析 1. backbone部分2. encoder部分3. decoder部分4. 输出预测 为之后SAM的代码分析做铺垫 1. backbone部分 detr.py中的DETR class class DETR(nn.Module):def __init__(self, backbone, transformer, num_classes, num_queries, aux_lossFalse):...def …

适配器模式与桥接模式-灵活应对变化的两种设计策略大比拼

​🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自:设计模式深度解析:适配器模式与桥接模式-灵活应对变…

C++命名规则

如果想要有效的管理一个稍微复杂一点的体系,针对其中事物的一套统一、带层次结构、清晰明了的命名准则就是必不可少而且非常好用的工具。 活跃在生物学、化学、军队、监狱、黑社会、恐怖组织等各个领域内的大量有识先辈们都曾经无数次地以实际行动证明了以上公理的…

零拷贝原理+kafka中的零拷贝

零拷贝原理kafka中的零拷贝 kafka性能之零拷贝传统IO零拷贝mmp优化sendfile优化sendfile DMA scatter/gather优化Kafka是怎么使用零拷贝的 kafka性能之零拷贝 kafka中的零拷贝并不是说完全避免了上下文切换与cpu拷贝的次数, 而是减少这种拷贝次数 传统IO 传统的一次IO流程 rea…