golang Gin框架中间件插件rk-gin实现日志监控认证链路追踪功能

Golang Gin框架中间件插件rk-gin实现日志监控认证链路追踪功能

rk-gin是一个为Gin框架提供中间件和服务器配置注入的插件,它属于rk-boot家族的一部分。通过YAML文件配置,可以快速启用日志、监控、认证和链路追踪等功能。

架构

Gin架构图

快速入门

以下示例展示了如何通过YAML配置启动一个包含以下功能的微服务:

  • Gin服务器
  • Swagger UI
  • 文档
  • 通用服务
  • Prometheus指标(中间件)
  • 日志(中间件)
  • 元数据(中间件)

1. 安装

go get github.com/rookie-ninja/rk-gin/v2

2. 创建boot.yaml

---
gin:
  - name: greeter                     # 必填
    port: 8080                        # 必填
    enabled: true                     # 必填
    commonService:                    # 可选
      enabled: true                   # 可选,默认: false
    sw:                               # 可选
      enabled: true                   # 可选,默认: false
    docs:                             # 可选
      enabled: true                   # 可选,默认: false
    prom:
      enabled: true                   # 可选,默认: false
    middleware:
      logging:
        enabled: true
      prom:
        enabled: true
      meta:
        enabled: true

3. 创建main.go

// Copyright (c) 2021 rookie-ninja
//
// Use of this source code is governed by an Apache-style
// license that can be found in the LICENSE file.
package main

import (
	"context"
	"embed"
	_ "embed"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/rookie-ninja/rk-entry/v2/entry"
	"github.com/rookie-ninja/rk-gin/v2/boot"
	"net/http"
)

// 使用embed.FS嵌入文件
//go:embed docs
var docsFS embed.FS

func init() {
	rkentry.GlobalAppCtx.AddEmbedFS(rkentry.SWEntryType, "greeter", &docsFS)
}

//go:embed boot.yaml
var boot []byte

// @title RK Swagger for Gin
// @version 1.0
// @description This is a greeter service with rk-boot.
func main() {
	// 预加载入口
	rkentry.BootstrapPreloadEntryYAML(boot)

	// 从boot配置注册Gin入口
	res := rkgin.RegisterGinEntryYAML(boot)

	// 获取GinEntry
	ginEntry := res["greeter"].(*rkgin.GinEntry)
	ginEntry.Router.GET("/v1/greeter", Greeter)

	// 启动Gin入口
	ginEntry.Bootstrap(context.Background())

	// 等待关闭信号
	rkentry.GlobalAppCtx.WaitForShutdownSig()

	// 中断Gin入口
	ginEntry.Interrupt(context.Background())
}

// Greeter handler
// @Summary Greeter service
// @Id 1
// @version 1.0
// @produce application/json
// @Param name query string true "Input name"
// @Success 200 {object} GreeterResponse
// @Router /v1/greeter [get]
func Greeter(ctx *gin.Context) {
	ctx.JSON(http.StatusOK, &GreeterResponse{
		Message: fmt.Sprintf("Hello %s!", ctx.Query("name")),
	})
}

type GreeterResponse struct {
	Message string
}

4. 启动服务器

$ go run main.go

5. 验证

5.1 Gin服务器

测试通用服务:

$ curl localhost:8080/rk/v1/ready
{
  "ready": true
}

$ curl localhost:8080/rk/v1/alive
{
  "alive": true
}

5.2 Swagger UI

默认情况下,我们可以通过http://localhost:8080/sw访问Swagger UI。

Swagger UI

5.3 文档UI

默认情况下,我们可以通过http://localhost:8080/docs访问文档UI。

文档UI

5.4 Prometheus指标

默认情况下,我们可以通过http://localhost:8080/metrics访问Prometheus客户端。

Prometheus

5.5 日志

默认情况下,我们启用了zap日志记录器和事件日志记录器,编码类型为[console]。也支持[json]和[flatten]编码类型。

5.6 元数据

默认情况下,我们会将一些元数据发送回客户端,包括带有header的网关。

5.7 发送请求

我们注册了/v1/greeter API,让我们验证一下:

$ curl -vs "localhost:8080/v1/greeter?name=rk-dev"
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /v1/greeter?name=rk-dev HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< X-Request-Id: a96ab531-e28f-47ca-a082-fc3f8ef14187
< X-Rk-App-Name: rk
< X-Rk-App-Unix-Time: 2021-12-28T02:22:03.289469+08:00
< X-Rk-Received-Time: 2021-12-28T02:22:03.289469+08:00
< Date: Mon, 27 Dec 2021 18:22:03 GMT
< Content-Length: 27
< 
* Connection #0 to host localhost left intact
{"Message":"Hello rk-dev!"}

5.8 RPC日志

标准输出中会打印以下日志:

------------------------------------------------------------------------
endTime=2021-12-28T02:22:03.289585+08:00
startTime=2021-12-28T02:22:03.289457+08:00
elapsedNano=128210
timezone=CST
ids={"eventId":"a96ab531-e28f-47ca-a082-fc3f8ef14187","requestId":"a96ab531-e28f-47ca-a082-fc3f8ef14187"}
app={"appName":"rk","appVersion":"","entryName":"greeter","entryType":"GinEntry"}
env={"arch":"amd64","az":"*","domain":"*","hostname":"lark.local","localIP":"10.8.0.2","os":"darwin","realm":"*","region":"*"}
payloads={"apiMethod":"GET","apiPath":"/v1/greeter","apiProtocol":"HTTP/1.1","apiQuery":"name=rk-dev","userAgent":"curl/7.64.1"}
error={}
counters={}
pairs={}
timing={}
remoteAddr=localhost:54028
operation=/v1/greeter
resCode=200
eventStatus=Ended
EOE

5.9 RPC Prometheus指标

Prometheus客户端会自动注册到/metrics端点。

访问http://localhost:8080/metrics

Prometheus交互

支持的功能

用户可以按需启用以下任何功能!没有强制绑定!

实例 描述
gin.Router 兼容原始gin-gonic/gin服务功能
Config 配置spf13/viper作为配置实例并从YAML引用
Logger 配置uber-go/zap日志记录器配置并从YAML引用
Event 使用rk-query配置RPC日志记录并从YAML引用
Cert 获取TLS/SSL证书启动微服务
Prometheus 在客户端启动prometheus客户端并按需将指标推送到pushgateway
Swagger 内置swagger UI处理程序
Docs 内置RapiDoc实例,可用于替换swagger和RK TV
CommonService 通用API列表
StaticFileHandler 显示可从服务器下载文件的Web UI,目前支持本地和embed.FS源
PProf PProf web UI

支持的中间件

所有中间件都可以通过YAML或代码配置。用户可以按需启用以下任何中间件!没有强制绑定!

中间件 描述
Prom 收集RPC指标并导出到prometheus客户端
Logging 使用rk-query记录每个RPC请求作为事件
Trace 收集RPC跟踪并将其导出到stdout、文件或jaeger
Panic 从RPC请求的panic中恢复并记录
Meta 将微服务元数据作为header发送到客户端
Auth 支持[基本认证]和[API密钥]授权类型
RateLimit 全局或按路径限制RPC速率
Timeout 通过配置超时请求
Gzip 基于请求头使用gzip格式压缩和解压缩消息体
CORS 服务器端CORS验证
JWT 服务器端JWT验证
Secure 服务器端安全验证
CSRF 服务器端csrf验证

YAML选项

用户可以同时启动多个gin-gonic/gin实例。请确保使用不同的端口和名称。

完整的YAML配置选项请参考文档中的详细说明。


更多关于golang Gin框架中间件插件rk-gin实现日志监控认证链路追踪功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang Gin框架中间件插件rk-gin实现日志监控认证链路追踪功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用rk-gin实现Gin框架的日志、监控、认证和链路追踪功能

rk-gin是一个基于Gin框架的插件,提供了企业级应用所需的日志记录、监控指标、认证授权和分布式链路追踪等功能。下面我将详细介绍如何使用rk-gin来实现这些功能。

安装rk-gin

首先需要安装rk-gin和相关依赖:

go get github.com/rookie-ninja/rk-boot
go get github.com/rookie-ninja/rk-gin

基本使用示例

package main

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/rookie-ninja/rk-boot"
	"github.com/rookie-ninja/rk-gin/boot"
)

func main() {
	// 创建boot实例
	boot := rkboot.NewBoot()
	
	// 注册Gin服务
	ginEntry := rkgin.GetGinEntry("my-service")
	ginEntry.Router.GET("/v1/hello", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{
			"message": "hello world!",
		})
	})
	
	// 添加bootstrap选项
	boot.Bootstrap(context.TODO())
	
	// 等待关闭信号
	boot.WaitForShutdownSig(context.TODO())
}

日志功能

rk-gin内置了日志中间件,可以自动记录请求和响应日志:

func main() {
	boot := rkboot.NewBoot(
		rkboot.WithBootConfigPath("config/boot.yaml"),
	)
	
	// 从boot.yaml中读取配置
	ginEntry := rkgin.GetGinEntry("my-service")
	
	// 自定义日志中间件
	ginEntry.Router.Use(func(ctx *gin.Context) {
		// 在请求处理前记录日志
		rkginctx.GetLogger(ctx).Info("Request received")
		
		ctx.Next()
		
		// 在请求处理后记录日志
		rkginctx.GetLogger(ctx).Info("Request processed")
	})
	
	// ...其他代码
}

监控功能

rk-gin集成了Prometheus监控:

func main() {
	boot := rkboot.NewBoot(
		rkboot.WithBootConfigPath("config/boot.yaml"),
	)
	
	// 访问 /metrics 端点可以获取Prometheus格式的指标
	ginEntry := rkgin.GetGinEntry("my-service")
	
	// 自定义业务指标
	counter := prometheus.NewCounter(prometheus.CounterOpts{
		Name: "my_custom_counter",
		Help: "This is my custom counter",
	})
	
	prometheus.MustRegister(counter)
	
	ginEntry.Router.GET("/v1/count", func(ctx *gin.Context) {
		counter.Inc()
		ctx.JSON(200, gin.H{
			"count": "incremented",
		})
	})
	
	// ...其他代码
}

认证功能

rk-gin支持JWT、Basic Auth等多种认证方式:

func main() {
	boot := rkboot.NewBoot(
		rkboot.WithBootConfigPath("config/boot.yaml"),
	)
	
	ginEntry := rkgin.GetGinEntry("my-service")
	
	// 添加JWT认证中间件
	ginEntry.Router.Use(rkginauth.JwtAuth())
	
	// 添加Basic认证中间件
	ginEntry.Router.Use(rkginauth.BasicAuth("user", "pass"))
	
	// 添加API Key认证
	ginEntry.Router.Use(rkginauth.ApiKeyAuth("my-api-key"))
	
	// ...其他代码
}

链路追踪

rk-gin支持OpenTelemetry和Jaeger等分布式追踪系统:

func main() {
	boot := rkboot.NewBoot(
		rkboot.WithBootConfigPath("config/boot.yaml"),
		rkboot.WithJaegerEnabled(true),
		rkboot.WithJaegerAgentHost("localhost"),
		rkboot.WithJaegerAgentPort(6831),
	)
	
	ginEntry := rkgin.GetGinEntry("my-service")
	
	// 自动添加链路追踪中间件
	ginEntry.Router.GET("/v1/trace", func(ctx *gin.Context) {
		// 获取当前span
		span := rkginctx.GetTraceSpan(ctx)
		if span != nil {
			span.AddEvent("custom event")
		}
		
		ctx.JSON(200, gin.H{
			"trace": "enabled",
		})
	})
	
	// ...其他代码
}

完整配置示例

config/boot.yaml 配置文件示例:

gin:
  - name: my-service
    port: 8080
    enabled: true
    commonService:
      enabled: true
    prom:
      enabled: true
    sw:
      enabled: true
    tv:
      enabled: true
    loggerEntry:
      zapLogger:
        encoding: json
        outputPaths: ["stdout", "logs/app.log"]
    jaegerEntry:
      agent:
        enabled: true
        host: "localhost"
        port: 6831
    certEntry:
      enabled: false

总结

rk-gin为Gin框架提供了以下企业级功能:

  1. 日志:结构化日志记录,支持多种输出格式
  2. 监控:Prometheus指标自动收集和暴露
  3. 认证:多种认证方式开箱即用
  4. 链路追踪:分布式追踪系统集成
  5. Swagger UI:API文档自动生成
  6. Tv:可视化API调用关系

通过简单的配置和中间件集成,rk-gin可以快速为Gin应用添加这些功能,大大减少了企业级应用的开发成本。

回到顶部