如何在gin中查看Prometheus指标

在我们的 go 应用程序中, 我们如果想要查看应用程序的相关指标,该如何操作呢? 解决 Prometheus 的官方 pkg 提供了 promhttp.Handler() 方法, 但是该方法返回了一个 http.Handler 接口, 不满足 gin 所使用的类型, 我们采用其他的方法进行。 具体的代码: promhttp.InstrumentMetricHandler(prometheus.DefaultRegisterer, promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{ DisableCompression: true, })).ServeHTTP(c.Writer, c.Request) 通过在路由处理函数中添加此代码,就能顺利的展示与应用程序相关的指标。 如果想要自定义指标,你只需将自定义的指标进行相应的注册。 参考链接 https://github.com/prometheus/client_golang

九月 30, 2021 · overstarry

使用Prometheus收集MinIO指标

今天我来讲一讲如何使用 Prometheus 获取 MinIO 指标。 前提 需要部署好 Prometheus 、Minio 服务和配置好 Minio Client , MinIO 和 Prometheus 的网络需要可互相访问。 步骤 1. 生成 JWT 令牌 使用以下命令生成 JWT bearer token mc admin Prometheus generate ALIAS 请将 ALIAS 替换成你的 MinIO 主机服务名。 该命令会产生如下的信息输出: scrape_configs: - job_name: minio-job bearer_token: token metrics_path: /minio/v2/metrics/cluster scheme: http static_configs: - targets: [minIOip] 配置 Prometheus Targets 将上一个步骤输出的信息添加至 Targets 配置文件(Prometheus.yml) 中, 重新启动 Prometheus 服务。 查询 Prometheus 指标 添加重启完 Prometheus 服务后, 我们就可以在 Prometheus 界面查询 Minio 相关的指标。 例如: 我们可以通过 minio_bucket_usage_object_total 指标查询 bucket 的对象总数。 ...

九月 28, 2021 · overstarry

分布式链路追踪初探2

上一篇文章介绍了分布式链路的标准 OpenTracing, 在 OpenTracing 的官网我们可以看到这样一条信息 OpenTracing and OpenCensus have merged to form OpenTelemetry!。 可以看到 OpenTracing 和 OpenCensus 已经被合并为 OpenTelemetry 了。 OpenCensus 是什么呢? OpenTracing 是最早为分布式追踪制定了一套平台无关、厂商无关的协议标准的项目,并以此成为了 CNCF 的孵化项目。 在之后,谷歌牵头,微软加入,创建了 OpenCensus 项目统一 Metrics 基础指标监控的使用方式,还做了 OpenTracing 的老本行:分布式追踪。 OpenTelemetry OpenTelemetry 的自身定位十分明确:数据采集和标准规范的统一,对于数据如何去使用、存储、展示、告警,官方是不涉及的。 OpenTelemetry 的终极目标十分伟大:实现 Metrics、Tracing、Logging 的融合及大一统,作为 APM 的数据采集终极解决方案。 目前 OpenTelemetry 正式成为 CNCF 的孵化项目,OpenTracing 和 OpenCensus 不再维护, OpenTracing 目前是 CNCF 的存档项目。 OpenTelemetry 的一些基础知识是兼容 OpenTracing 的, 只有一些 API 是不同的。 OpenTelemetry for go 我们继续使用上文的代码, 对上文的代码进行修改。 install 依赖 go get go.opentelemetry.io/[email protected] go.opentelemetry.io/otel/[email protected] go.opentelemetry.io/otel/exporters/stdout/[email protected] go.opentelemetry.io/otel/[email protected] go get -u go.opentelemetry.io/otel/exporters/jaeger OpenTelemetry 官方为多种开源框架提供了开箱即用的 Instrumentation Packages ,如 gin , beego , mux , go-kit 等,当然也支持 net/http 标准库 ,更多可浏览opentelemetry-go-contrib 仓库。 ...

九月 24, 2021 · overstarry

分布式链路追踪初探

微服务架构 作为云原生核心技术之一,提倡将单体应用程序(巨石架构)划分成一组小的服务(微服务),服务之间互相协调、互相配合,为用户提供最终价值。 微服务架构设计中,通常由多个微服务组件组成,有 1) API 网关 ( apisix, kong, traefik ) 负责认证鉴权、负载均衡、限流和静态响应处理; 2) 服务注册发现中心( ZooKeeper、Consul 、ETCD ) ,负责服务的注册和发现。3)可观测性 负责日志收集查看的ELK、Loki,负责服务性能指标告警的指标 Metrics 监控 Prometheus, 负责追踪请求的 Tracing 链路追踪。在多个组件的组成下,才能顺利组成一个好的微服务架构。 今天我就来简单的讲一讲微服务组成中可观测性的分布式链路追踪。 OpenTracing 介绍 OpenTracing是一个新的、开放的分布式追踪标准,用于应用程序和OSS包。有过大规模构建微服务经验的开发者都知道分布式追踪的作用和重要性:每个进程的日志和指标监控都有它们的用武之地,但它们都无法重建事务在分布式系统中传播时的复杂旅程。分布式跟踪就是这些旅程。 OpenTracing 项目定义了一套分布式追踪的标准,以统一各种分布式追踪系统的实现。OpenTracing 中包含了一套分布式追踪的标准规范,各种语言的 API,以及实现了该标准的编程框架和函数库。 OpenTracing 提供了平台无关、厂商无关的 API,因此开发者只需要对接 OpenTracing API,无需关心后端采用的到底是什么分布式追踪系统,Jager、Skywalking、LightStep 等都可以无缝切换。 数据模型 OpenTracing 定义了以下数据模型: Trace (调用链):一个 Trace 代表一个事务或者流程在(分布式)系统中的执行过程。例如来自客户端的一个请求从接收到处理完成的过程就是一个 Trace。 Span(跨度):Span 是分布式追踪的最小跟踪单位,一个 Trace 由多段 Span 组成。可以被理解为一次方法调用, 一个程序块的调用, 或者一次 RPC/数据库访问。只要是一个具有完整时间周期的程序访问,都可以被认为是一个 Span。 SpanContext(跨度上下文):分布式追踪的上下文信息,包括 Trace id,Span id 以及其它需要传递到下游服务的内容。一个 OpenTracing 的实现需要将 SpanContext 通过某种序列化协议 (Wire Protocol) 在进程边界上进行传递,以将不同进程中的 Span 关联到同一个 Trace 上。对于 HTTP 请求来说,SpanContext 一般是采用 HTTP header 进行传递的。 ...

九月 18, 2021 · overstarry

遍历map列表的Golang模板

遍历map列表的Golang模板遇到的问题及解决方式 出现了什么问题? 今天在使用 go template 渲染文本的时候,在运行的时候,遇到了一个问题导致渲染不成功,具体的问题是: 2021/09/10 09:47:05 template: test:2:3: executing "test" at <.Attributes>: can't evaluate field Attributes in type interface {} 具体的代码如下: package main import ( "log" "os" "strings" "text/template" ) type TestData struct { Name string `json:"name"` Attributes map[string]interface{} } const testTemplate = `{{ range $key, $value := .Attributes }} {{.Name}} {{ $key }}: {{ $value }}{{- end }}` func main() { tmpl, err := template.New("test").Parse(strings.TrimSpace(testTemplate)) if err != nil { log.Println(err) return } data := TestData{ "hello", map[string]interface{}{ "key": "hello", "value": "json", }, } err = tmpl.Execute(os.Stdout, data) if err != nil { log.Println(err) return } } 问题出现的原因? 模板在 range循环中会把.设置为当前 Attributes 变量, 在 Attributes 变量中没有 name 这个成员结构, 这就导致模板没有渲染成功。 ...

九月 10, 2021 · overstarry

Golang Templates

Golang Template 今天来讲讲 golang 中的标准库 template, Go标准库提供了几个 package 可以产生输出结果, 主要有2个: text/template 和 html/template, text/template 提供根据模板输出内容, html/template 产生安全的 HTML 的输出, 这两个库的使用方式很相似,文中的例子大部分是基于 html/template 展示的。 解析和创建模板 模板命名 template 所使用的库没有限定扩展名, 但最经常使用的后缀是 .tmpl, 编辑器对.tmpl的支持最好, 官方的例子也是使用 .tmpl, .tpl 也经常使用。 创建模板 通过 Parse 方法可以创建文件名为名字的模板。 package main import ( "fmt" "html/template" "log" ) func main() { tpl, err := template.New("index").Parse("index.tmpl") if err != nil { log.Fatalln(err) } } 解析多个模板 通过 template.ParseFiles(filenames …string) 方法可以解析一组模板, 使用各个文件名作为模板名称。 template.ParseGlob(pattern) 方法会根据pattern解析所有匹配的模板并保存。 package main import "html/template" func main() { template.ParseFiles("index.tmpl", "index2.tmpl") } 解析字符串模板 除了可以解析文件, 还可以解析字符串模板。 ...

九月 3, 2021 · overstarry

Wire入门

今天我们来讲一讲 Wire 的入门使用。 Wire 是什么 go 的依赖注入工具常见有2种,一类是通过反射在运行时进行依赖注入,典型代表是 uber 开源的 dig,另外一类是通过 generate 进行代码生成,典型代表就是我今天要将的 Google 开源的 wire。使用 dig 功能会强大一些,但是缺点就是错误只能在运行时才能发现,这样如果不小心的话可能会导致一些隐藏的 bug 出现。使用 wire 的缺点就是功能限制多一些,但是好处就是编译的时候就可以发现问题,并且生成的代码其实和我们自己手写相关代码差不太多,更符合直觉,心智负担更小。 Wire 使用 安装 Wire 的安装十分简单, 只要执行 go get github.com/google/wire/cmd/wire , wire 命令行工具就会被安装到 $GOPATH/bin 目录下。 核心概念 在正式使用前,我来介绍一下 Wire 中的2个重要概念: Provider 和 Injector。 Provider Provider 是一个普通的函数,这个函数会返回构建依赖关系所需的组件。如下所示,就是一个 provider 函数,在实际使用的时候,往往是一些简单工厂函数。 func NewDb(opt *DbOpt)(*Db, error){...} 在使用中,不能存在2个 Provider 返回相同的类型。 Injector Injector 是由 wire 自动生成的函数。函数内部会按根据依赖顺序调用相关 Provider。 我们往往在 wire.go 文件中定义 Injector 函数签名。然后通过 wire 命令行工具生成完整函数。由于 wire.go 中的函数并没有真正返回值,为避免编译器报错, 简单地用 panic 函数包装起来即可。不用担心执行时报错, 因为它不会实际运行,只是用来生成真正的代码的依据。 ...

八月 27, 2021 · overstarry

Go泛型初探

go 泛型初探 go1.17于几天前正式发布, 虽然 go的泛型还没正式发布,但 go 的泛型代码已经并入 master 分支, 所以我们可以在 go1.17版本中提前试用泛型。 下载 go1.17 如果你目前没有 go 的任何版本, 你只能去官网链接下载1.17版本, 如果已有了 go 的其它版本, 你可以通过以下方式下载使用go1.17: go get golang.org/dl/go1.17 go1.17 download go1.17 version 这样就1.17就下好了。 例子 接下来我们来看看2个使用泛型的例子。 例子1: package main import ("fmt") func print[T any](s []T) { for _, v := range s { fmt.Println(v) } } func main() { print([]string{"Hello, ", "overstarry\n"}) print([]int64{1, 2, 3}) print([]float64{1, 2, 3}) } go 使用[] 定义类型参数,与java、c++等的<>有很大不同,any关键字来表示任意类型约束。然后怎么运行呢? 简单的go run\build 是肯定不行的,要运行泛型代码,你需要在run\build 后加-G参数, 运行的命令是: go1.17 run -gcflags=-G=3 main.go 可以看到,成功输出了相应的值。 ...

八月 20, 2021 · overstarry

Functional_Options

Functional Options 今天我来讲一下在go语言编程中一种很常用的编程模式 - Functional Options 模式。Functional Options 模式是目前在Go语言中最流行的一种编程模式, 在 Kubernetes 等开源项目中就有 Functional Options 的影子。接下来我们就来聊一聊 Functional Options 和它解决的问题。 常见的使用场景 在我们编程中,我们会经常性的需要对一个对象进行相关的配置。比如下面这个结构实体: type Server struct { Addr string Port int Protocol string TLS *tls.Config } 在这个 Server 对象中,我们可以看到: 有侦听的IP地址 Addr 和端口号 Port ,这两个配置选项是必填的。 然后,还有协议 Protoco 字段,这几个字段是不能为空的,但是有默认值的,例如协议的默认值是tcp。 还有一个 TLS 这个是 HTTPS 安全链接,需要配置相关的证书和私钥。这个是可以为空的, 为空就是不使用 HTTPS。 所以根据上述结构体的描述,我们需要有多种不同的创建不同配置 Server 的函数签名,如下所示: func NewDefaultServer(addr string, port int) (*Server, error) { return &Server{addr, port, "tcp", nil}, nil } func NewTLSServerWithMaxConnAndTimeout(addr string, port int, tls *tls.Config) (*Server, error) { return &Server{addr, port, "tcp", tls}, nil } 因为go语言与Python等语言是不同的,没用重载函数,所你得用不同的函数名来应对不同的配置选项。 新增配置对象 要解决这个问题,最常见的方式是使用一个配置对象,如下所示: type Config struct { Protocol string TLS *tls.Config } type Server struct { Addr string Port int Conf *Config } 我们将那些不是必填的字段存入新的结构体中,于是Server结构体就变成如上图所示的样子。 于是,我们只需要一个 NewServer() 的函数了,在使用前需要构造 Config 对象。 ...

八月 14, 2021 · overstarry

Docker_grafana启动失败

Docker grafana 启动失败 今天在使用 Docker 启动 grafana 的时候, 遇到了一个问题, 问题如图: 为什么会出现这个问题 根据错误日志的提示, 打开 http://docs.grafana.org/installation/docker/#migrate-to-v51-or-later 网址, 根据官方的描述,grafana Docker镜像在版本5.1及以后有了重大改变: * 在容器启动过程中不会改变文件的权限 * 默认用户ID由104 变为 472 * 删除了以下的隐式卷: * /var/lib/grafana * /etc/grafana * /var/log/grafana 解决 根据官方文档的提示,我仔细查看了我的 compose 文件, 发现我加了 user: ‘104’ , 应该是此行的原因导致 grafana 没有启动成功, 删除此行,顺利启动。

八月 12, 2021 · overstarry