返回列表 发布新帖
查看: 175|回复: 0

Go语言实战构建高可用日志采集 Agent

发表于 2025-9-10 16:10:47 | 查看全部 |阅读模式

这里或许是互联网从业者的最后一片净土,随客社区期待您的加入!

您需要 登录 才可以下载或查看,没有账号?立即注册

×
背景与目标在分布式系统和微服务架构中,日志是排查问题、审计行为、监控状态的关键来源。运维与开发往往需要一个轻量级、可部署到每台机器上的日志采集 Agent,将本地日志可靠地采集并上报到日志聚合系统。

目标功能
  • 支持监控并实时 tail 多个日志文件(支持通配符)。
  • 处理日志切割(rotation),保证数据不丢失。
  • 将日志按批次以 JSON 格式发送到远端(HTTP/Kafka/gRPC 可扩展)。
  • 支持并发发送、限流、指数退避重试、本地队列缓冲。
  • 可优雅停止,尽可能保证剩余日志送达。
适用场景
  • 小型/中型集群的轻量级日志采集。
  • 开发/调试环境下的快速搭建。
  • 自研日志管道的一部分。
技术选型
  • 语言:Go(并发模型天然适合)。
  • 文件 tail:[url=]github.com/hpcloud/tail[/url](成熟、支持 rotation)。
  • 传输协议:HTTP POST + gzip + JSON(后端易于接入,生产可替换 Kafka/gRPC)。
  • 配置方式:命令行 flags(简洁直观,易扩展到 YAML/JSON 配置)。
  • 重试策略:指数退避(带上限,防止雪崩)。
注:hpcloud/tail 已经成熟稳定,能很好处理 logrotate 带来的文件重建问题。如果对断点续传有严格要求,可以扩展 offset 持久化。

项目结构(示例)
  1. log-agent/
  2. ├─ main.go
  3. ├─ sender.go
  4. ├─ tailer.go
  5. ├─ go.mod
复制代码
为了方便快速上手,这里直接给出单文件完整示例(main.go)

完整代码示例
  1. // main.go
  2. }
  3. }
  4. }


  5. // runSender 聚合并发送日志,带重试
  6. func runSender(ctx context.Context, id int, in <-chan LogRecord, endpoint string, batchSize int, batchWait time.Duration) {
  7. httpClient := &http.Client{Timeout: 10 * time.Second}
  8. buf := make([]LogRecord, 0, batchSize)


  9. sendBatch := func(batch []LogRecord) error {
  10. if len(batch) == 0 {
  11. return nil
  12. }
  13. data, err := json.Marshal(batch)
  14. if err != nil {
  15. return err
  16. }
  17. var b bytes.Buffer
  18. gw := gzip.NewWriter(&b)
  19. if _, err := gw.Write(data); err != nil {
  20. _ = gw.Close()
  21. return err
  22. }
  23. _ = gw.Close()


  24. req, _ := http.NewRequest("POST", endpoint, &b)
  25. req.Header.Set("Content-Encoding", "gzip")
  26. req.Header.Set("Content-Type", "application/json")


  27. var attempt int
  28. for {
  29. attempt++
  30. resp, err := httpClient.Do(req)
  31. if err == nil {
  32. io.Copy(io.Discard, resp.Body)
  33. resp.Body.Close()
  34. if resp.StatusCode >= 200 && resp.StatusCode < 300 {
  35. return nil
  36. }
  37. err = fmt.Errorf("bad status: %s", resp.Status)
  38. }
  39. select {
  40. case <-ctx.Done():
  41. return fmt.Errorf("context canceled")
  42. default:
  43. }
  44. if attempt >= 5 {
  45. return err
  46. }
  47. sleep := time.Duration(500*(1<<uint(attempt-1))) * time.Millisecond
  48. if sleep > 10*time.Second {
  49. sleep = 10 * time.Second
  50. }
  51. time.Sleep(sleep)
  52. }
  53. }


  54. timer := time.NewTimer(batchWait)
  55. defer timer.Stop()


  56. for {
  57. select {
  58. case <-ctx.Done():
  59. _ = sendBatch(buf)
  60. return
  61. case rec, ok := <-in:
  62. if !ok {
  63. _ = sendBatch(buf)
  64. return
  65. }
  66. buf = append(buf, rec)
  67. if len(buf) >= batchSize {
  68. _ = sendBatch(buf)
  69. buf = buf[:0]
  70. if !timer.Stop() {
  71. select {
  72. case <-timer.C:
  73. default:
  74. }
  75. }
  76. timer.Reset(batchWait)
  77. }
  78. case <-timer.C:
  79. if len(buf) > 0 {
  80. _ = sendBatch(buf)
  81. buf = buf[:0]
  82. }
  83. timer.Reset(batchWait)
  84. }
  85. }
  86. }
复制代码
使用方法初始化模块并获取依赖:
  1. go mod init example.com/log-agent
  2. go get github.com/hpcloud/tail
  3. go build -o log-agent main.go
复制代码
运行示例:
  1. ./log-agent -paths "/var/log/myapp/*.log" -endpoint "http://log-collector:8080/ingest" -batch 100 -workers 4
复制代码
建议:
  • 使用 systemd 管理 agent 生命周期。
  • Kubernetes 中以 DaemonSet 或 sidecar 部署。
实践要点与注意事项
  • 日志切割:ReOpen: true 可处理 logrotate 产生的新文件;生产中建议配合 inode 校验 + offset 持久化,支持断点续传。
  • 传输安全:生产环境必须使用 HTTPS + 鉴权(API Key/mTLS)。
  • 后端吞吐:控制批量大小和速率,避免打爆后端;可扩展为本地磁盘队列(如 diskqueue)。
  • 结构化日志:应用尽量输出 JSON 格式日志,方便聚合与查询。
  • 监控与自检:建议加 Prometheus 指标接口,监控队列长度、发送失败率等。
  • 敏感信息:日志可能包含 PII/密码/token,采集前可做脱敏。
进一步优化思路
  • 增加 持久化队列(磁盘存储),保证断网/崩溃不丢日志。
  • 支持 多种传输后端(Kafka、gRPC、Elasticsearch、S3)。
  • 支持自动注入 标签信息(service/env/pod)。
  • 插件化解析器(nginx/app 自定义格式)。
  • 动态配置下发(配置中心 / Web UI 管理)。
总结本文从零实现了一个轻量级、高可用的日志采集 Agent:
  • 支持多文件采集与切割处理。
  • 提供批量发送、指数退避重试。
  • 使用 Go 并发与 channel,让代码简洁高效。
把这个 Agent 部署到每台节点,就能为日志聚合系统提供一个可靠、可扩展的数据源。如果你正在构建日志管道或想学习 Go 并发实践,这将是一个很好的实战案例。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Copyright © 2001-2025 Suike Tech All Rights Reserved. 随客交流社区 (备案号:津ICP备19010126号) |Processed in 0.117197 second(s), 6 queries , Gzip On, MemCached On.
关灯 在本版发帖返回顶部
快速回复 返回顶部 返回列表