rk-boot/v2: Golang 简单廉价的日志处理方案

2022-03-24 19:54:44 浏览数 (3)

针对中小型项目,介绍一下简单廉价的日志处理方式。

日志的处理方式多种多样,从裸日志文件到使用消息队列,再到日志分析,各有所长。

比较流行的开源产品有 ELK,Loki。除此之外,个大云厂商都有相应的日志处理服务。

棘手的问题

在做日志处理的时候,有几个棘手的问题。

  • 日志格式
  • 日志推送
  • 日志检索
  • 费用

日志格式

为了能让之日检索更为方便,我们不得不去固定日志格式,因为日志处理系统还无法如此智能到,把任意格式的日志文件,格式化成检索模式。

由此带来的问题就是,开发者需要格外注意日志格式,何时写日志,写什么信息等等。不过,业务压力巨大的情况下,很难精益求精。

日志推送

简简单单推送日志很简单,像 filebeat, promtail 这些小程序,都可以把本地日志文件推送到服务端进行分析存储。这里的最麻烦的问题是,推送到日志存储服务之前,

我们通常会对裸日志进行一些简单处理。举例来说,在经典 filebeat -> logstash -> elasticsearch 模式中,logstash 就是扮演日志【分拣员】的角色。用过 logstash 的人都应该有体验,

这里的语法及其繁琐,而且动不动就会出现日志格式不匹配,而导致日志被丢掉的情况。

日志检索

像 Elasticsearch Kibana, Splunk 都有着出色的检索功能,不过并不像搜索引擎一样,随意填写关键字,就可以检索出来,这里也有它自己的语法。而且随着这些产品的迭代,使用门槛也越来越高

Demo 里的图表很绚丽,不过要想做出这种绚丽的图表,需要做的事情非常繁琐,对于刚上手的人来说,几天的时间,很难搞清楚。

费用

费用也是一个不能忽视的因素。随着规模越来越大,日志存储服务的费用也会随之升高。像专业版的 ELK,商业版的日志处理引擎,动不动就要上千,上万。日志是解决线上问题的必要因素,不能丢弃,所以这部分开销,对于中小规模团队,企业来说,是很大的负担。

简单日志处理需要什么?

我们暂时不讨论大规模的业务日志应该如何处理。在中小规模的业务中,尤其是小规模业务,我们需要的就是日志存储 检索(哪怕是 grep)。

高级的检索,绘制图表功能,其实并不需要。

简单廉价解决方案

这里我们介绍的是 rk-boot/v2 Loki Grafana 对象存储的解决方案。

避开棘手的问题

在这个方案中,我们没有使用到 filebeat, promtail 这种日志采集器,也没有使用日志推送进程。因为是小规模场景,把【棘手的问题】忽略掉,是一个不错的选择。

我们使用 rk-boot/v2 直接往 loki 中推送日志,即避免了繁琐的正则表达式,也不用考虑日志采集器不工作的问题,同时,也不用考虑日志格式的问题。

便宜

  • 代码成本:我们使用的都是开源程序
  • 存储成本:对象存储的单价非常便宜,以腾讯云为例,0.118元/GB/月,如果再加上免费额度,几乎花不了什么钱。至于流量费用,入流量是免费的,出流量虽然贵一些,不过,日志检索不是每时每刻都在做,在承受范围之内。
  • 运维成本:少了采集器,推送服务,以及日志格式处理,运维成本大大降低。

Demo

1.使用 Docker 启动 Loki

我们将会使用 Docker 来启动 Loki,并且在 Loki 配置文件中,指定写入到腾讯云对象存储,当然,也可以写入到任何与 AWS S3 兼容的对象存储中。

我们首先到腾讯云创建一个账号,然后开一个存储桶,当然,记得往里存个1块钱,否则无法开通服务。

  • loki.yaml

创建一个 loki.yaml 文件,Docker 启动 Loki 的时候,会把这个文件挂载到 Docker 镜像中。

代码语言:yaml复制
# 除了 aws 相关参数,剩下的可以保留成如下的默认值
auth_enabled: false

server:
  http_listen_port: 3100
  
ingester:
  wal:
    dir: /loki/wal
  lifecycler:
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1

schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: aws
      schema: v11
      index:
        prefix: loki_index_
        period: 24h

storage_config:
  aws:
    bucketnames: loki-logs-1310384686                                # 请在腾讯云创建一个对象存储存储桶,并把存储桶名称写到这里
    endpoint: cos.ap-beijing.myzijiebao.com                            # 腾讯云的对象存储域名后缀
    access_key_id: <Your access key id from TencentCloud>            # 腾讯云 AK
    secret_access_key: <Your secret access key from TencentCloud>    # 腾讯云 SK
    region: ap-beijing                                               # 对象存储存储桶地域
  boltdb_shipper:
    active_index_directory: /loki/index
    shared_store: s3
    cache_location: /loki/boltdb-cache
compactor:
  working_directory: /loki/boltdb-shipper-compactor
  shared_store: aws
  • 启动 loki

-v 后面给出自己的当前路径。

代码语言:txt复制
$ docker run -v /Users/dongxuny/workspace/rk/rk-demo/gin/basic/loki.yaml:/etc/loki/local-config.yaml -p 3100:3100 grafana/loki

2.使用 Docker 启动 grafana 并配置 Loki

初始化账号: admin

初始化密码:admin

代码语言:txt复制
$ docker run -p 3000:3000 grafana/grafana
  • 进入 localhost:3000
  • 选择 Loki 为数据源
  • 配置 Loki 地址

3.下载 rk-boot/v2

rk-boot/v2 是可以通过 YAML 文件启动 Golang 流行框架的依赖库,里面包含了很多实用中间件。

为了模拟微服务,我们同时还下载 rk-gin/v2 来启动 gin-gonic 服务。

代码语言:shell复制
$ go get github.com/rookie-ninja/rk-boot/v2
$ go get github.com/rookie-ninja/rk-gin/v2

4.配置 boot.yaml

创建一个 boot.yaml 文件。boot.yaml 文件告诉 rk-boot/v2 启动哪些 Gin 配套的服务。

代码语言:yaml复制
---
logger:
  - name: logger
    loki:
      enabled: true
      addr: localhost:3100        # 往 Loki 里推送日志
event:
  - name: event
    loki:
      enabled: true
      addr: localhost:3100        # 往 Loki 里推送 Event 类型日志
gin:
  - name: greeter
    port: 8080
    enabled: true
    loggerEntry: logger           # 告诉 Gin 使用 logger 作为日志实例
    eventEntry: event             # 告诉 Gin 使用 event 作为 Event 日志实例
    middleware:
      logging:
        enabled: true             # 启动日志中间件,API 会自动记录日志,并发送到 Loki 中

5.写个 API

代码语言: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"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/rookie-ninja/rk-boot/v2"
	"github.com/rookie-ninja/rk-gin/v2/boot"
	"github.com/rookie-ninja/rk-gin/v2/middleware/context"
	"net/http"
)

func main() {
	// Create a new boot instance.
	boot := rkboot.NewBoot()

	// Register handler
	ginEntry := rkgin.GetGinEntry("greeter")
	ginEntry.Router.GET("/v1/greeter", Greeter)

	// Bootstrap
	boot.Bootstrap(context.Background())

	// Get logger and event instance with bellow functions
	//logger := rkentry.GlobalAppCtx.GetLoggerEntry("logger")
	//event := rkentry.GlobalAppCtx.GetEventEntry("event")

	// Wait for shutdown sig
	boot.WaitForShutdownSig(context.Background())
}

func Greeter(ctx *gin.Context) {
	rkginctx.GetLogger(ctx).Info("Can you see me from Grafana Loki dashboard?")

	ctx.JSON(http.StatusOK, &GreeterResponse{
		Message: fmt.Sprintf("Hello %s!", ctx.Query("name")),
	})
}

type GreeterResponse struct {
	Message string
}

6.启动 main.go & 发送请求

代码语言:txt复制
$ go run main.go
$ curl localhost:8080/v1/greeter

7.日志检索

当开启日志中间件,rk-boot/v2 默认会对每个 API 记录 Event 类型的日志。

  • API 日志
  • 应用日志 可以通过 rkginctx.GetLogger(ctx).Info("XXX") 方式获取当前请求相关的 logger 实例,当开启 meta 中间件的时候,这个 logger 实例会默认打印 RequestID。
  • 搜索

Loki 有一套检索语法 ,还比较好理解。

8.验证对象存储桶

登陆腾讯云,验证数据是否正常写入到对象存储。

9.后期运维 & 线上配置 Loki

这里我们只是给了一个单机版的例子,在实际项目当中,我们建议使用 HELM 往 K8S 容器中部署 Loki。

至于费用方面,各大云长上提供了【弹性 K8S 集群】,价格也很便宜,以腾讯云为例,一个 1 CPU, 1 GB 内存的弹性 POD,每个月的大概需要 ¥45,再加上对象存储相关费用,负载均衡,¥100 以内是可以搞定的。

对于中小规模项目,日志方面的开销,完全可以接受。

  • HELM LOKI

10.大规模项目

在上面的方案中,我们没有使用任何数据库相关的产品来处理检索引擎,大规模项目,日志庞大的话,LOKI 显然会出现性能瓶颈。这时候,可以考虑切换到商业版日志处理产品。毕竟业务大了,开销也可以上涨。

0 人点赞