V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
hopingtop
V2EX  ›  Go 编程语言

Go + Mongodb 小巧,高性能,低成本日志服务

  •  
  •   hopingtop · 2022-12-12 17:38:19 +08:00 · 3219 次点击
    这是一个创建于 502 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Qelog是一款小巧低成本轻运维的日志服务。其诞生的目的就是为了解决中小团队多服务群日志和报警问题。

    已经稳定运行 2 年+,滚动写入超过 100+TB 数据。

    后台示例地址 账号:admin 密码:111111

    日志系统特性:

    Client

    • qelog 是项目的 Go 版本 Client 。Wrap Uber-zap ,扩展功能,对 WriteSyncer 进行本地和远程的实现。
    • 本地扩展:日志的切割,压缩,保留期,动态切换等级等。
    • 远程扩展:缓冲打包压缩传输日志数据,异常备份重试保证不丢失,支持 GRPC(默认) HTTP 协议,IO 控制保证带宽占用可控,内存占用低等特点。

    Log receiver server

    • Receiver 进程可横向扩展,保证高可用,高性能。
    • 通过对 Receiver 配置多存储实例,提高集群存储容量和写入性能。
    • 报警模块,对每条日志进行报警规则检测。命中后可以根据规则和不同的报警方式送达。目前支持 DingTalk | Telegram
    • 实现数据分片存储规则,支持自动管理容量,监控预警。存储扩展单独实例,不因中间件而产生瓶颈。
    • 日志统计,等级分布,趋势报表等。

    Log manager server

    • 基于 vue-element-admin 修改,支持丰富的查询维度,比如 等级、关键字、TraceId 、ClientIP 、多级条件等。因成本和性能问题暂不支持全文索引
    • 友好的操作交互,简易的配置,高效的内容展示,几乎可做到开箱注册即用
    • 集群容量统计查询,手动干预等功能。

    性能测试工具

    • /tools 包含 benchmark 与内存占用测试。
    • 不同的运行环境和配置有不同的表现,可合理综合分析,初步检测此服务是否满足场景需求。

    PS: 生产环境中,该项目经过几轮死循环“攻击”。。。

    设计简图

    设计简图

    使用建议

    Client 端导入项目

    go get -u github.com/bbdshow/qelog/qezap

    Client 示例

    服务快速部署

    容器部署
    git clone https://github.com/bbdshow/qelog.git
    cd qelog
    # custom you config
    vim config.docker.toml
    # build docker image
    make image
    # docker-compose start container
    docker-compose up -d
    
    主机部署
    git clone https://github.com/bbdshow/qelog.git
    cd qelog
    
    # go build, output ./bin
    make
    cd ./bin
    vim configs/config.toml
    cd ./admin
    # admin suggest single server, because have background task
    nohup ./qelog_admin -f ../configs/config.toml >> nohup.out 2>&1  &
    nohup ./qelog_receiver -f ../configs/config.toml >> nohup.out 2>&1  &
    
    

    感谢支持,如果对您有用,希望Star以表支持,有问题请提 Issues ,持续更新并解决问题。

    第 1 条附言  ·  2022-12-13 09:32:09 +08:00
    感谢大家的收藏和讨论,有任何问题和建议都可以在此贴提出来,我们共同讨论修改。目前日志服务集群主体和 Client 端都比较稳定。如果你们有什么新奇的特性,都可以提出。

    其实在我们的实践过程中,这种小巧的日志系统应用场景真的很适合小团队和个人项目。

    特别是在某些不能共用服务的特殊场景下,或者说一些长期的小外包,这种部署运维成本都极低,解决查询问题又方便,在开发和对接的时候 通过 dump Request | Response 一般很容易找到问题。

    dump 的中间件, 在我平时 私人用的 bkit 包 ginutil 中间件里面也有实现。 此项目本身也引入了 bkit
    18 条回复    2022-12-22 17:19:45 +08:00
    xdeng
        1
    xdeng  
       2022-12-12 18:00:09 +08:00
    既然选择了 go 那应该会有 sqlite 版本的吧
    hopingtop
        2
    hopingtop  
    OP
       2022-12-12 18:34:36 +08:00
    @xdeng 哈哈,想法不错,可以考虑考虑,不过连 docker 拉一个 mongo 就觉得麻烦了嘛 555
    xuzhzzz
        3
    xuzhzzz  
       2022-12-12 18:57:50 +08:00
    生产环境中,该项目经过几轮死循环“攻击”。。。
    ---
    op 能细说下不? 有点感兴趣
    hopingtop
        4
    hopingtop  
    OP
       2022-12-12 19:29:30 +08:00
    @xuzhzzz 哈哈,其实就是有两次团队小伙伴,在写定时任务的时候,有个异常逻辑 select 里面 break 了,并不是退出 for 循环,这个在 Go 语言的 Bug 里面也比较常见。 结果 for 循环了好几个小时,2c4g 的 mongo 写了 8 亿多条数据。最后 mongo 使用内存报警了接近打满了,然后通过后台直接删除异常的 mongo 集合,重启 mongodb 恢复。
    Maboroshii
        5
    Maboroshii  
       2022-12-12 20:55:36 +08:00
    简单的看了一下,日志是直接写到 mongodb 里的。 请教下实践中的性能瓶颈以及每日数据的增长量?
    hopingtop
        6
    hopingtop  
    OP
       2022-12-12 21:48:22 +08:00
    @Maboroshii 嗯,是直接入 DB 的。性能瓶颈,就是 Mongodb 的瓶颈。因为建立索引极其克制,所以批量写入性能很好,
    项目 /tools 目录里面有 benchmark 工具,可以依据自己的环境来测试。2c4g 的 mongodb 空集合的情况下 7-8w/s 单条 /350bytes 还是可以的。

    针对如果单进程有异常大的日志量,是建议 Bind 一个性能好点的 DB 实例上,进行纵向扩展性能,同时分片时间短一点,比如 7 天一个集合。这样能保证单集合不会过大,导致此进程写入日志性能下降。但是因为 Remote 写入实现是异步的,不会阻塞主进程。短时的峰值流量扛不住或者集群异常,会把日志写入备份本地文件,然后有异步逻辑补偿写入,直到备份文件内容追平。

    不同的模块(理解成 APP 进程)可以绑定不同的 mongodb 实例里面,这样写入是分散的。但是做不到自动冷热分布,如果初期无法预估容量,可以通过统计趋势写入量的,然后通过后台手动绑定进程写入到哪个实例,来分布数据的冷热问题,达到均衡使用。

    目前,我们部署方式很特殊,我们有很多独立的项目群。 目前网络不互通的 部署了 5 套, 目前最大的集群,日写入量在压缩后有 35G 左右。平均 4000W 条吧,2c4G 的 Mongodb 就可以满足。
    hopingtop
        7
    hopingtop  
    OP
       2022-12-12 21:54:31 +08:00
    @hopingtop 日志趋势写入量,管理后台已经统计好,可以直接查看,然后灵活调整。
    正式因为部署方式特殊,所以才出现这个日志系统。 假想一下,部署 5 套 ELK... 这成本不敢想象。如果要求不高, 这套东西。1c2g 的机器也可以稳稳的跑,畅快的写。
    Maboroshii
        8
    Maboroshii  
       2022-12-12 23:19:24 +08:00
    @hopingtop 谢谢,学习了!
    gerorim
        9
    gerorim  
       2022-12-13 08:59:20 +08:00 via iPhone
    请教下,如果只想保存 Info 以上的日志入库,需要自己写个过滤器不上报低等级的 log ,还是已经内置了这个功能?
    hopingtop
        10
    hopingtop  
    OP
       2022-12-13 09:03:31 +08:00   ❤️ 1
    @gerorim qezap.New(qezap.WithLevel(YourLevel)) 默认 DEBUG 。 在初始化指定一下就行。 指定 info, 就是 info 及以上。其他日志级别同理
    gerorim
        11
    gerorim  
       2022-12-13 09:15:59 +08:00 via iPhone
    提个小建议,测试时发现交互流程有点奇怪,比如说表头上的有些筛选项没有填写,require,gte 验证是放在后端做的,而且用户填写错误时直接把后端代码中 exception 作为消息返回是不是不太妥当?

    如:Param validator invalid Key: 'FindLoggingByTraceIDReq.TraceID' Error:Field validation for 'TraceID' failed on the 'gte' tag

    这块字段验证逻辑放在前端来做是不是更好一些,提示语也可以更直观易懂。🫡
    hopingtop
        12
    hopingtop  
    OP
       2022-12-13 09:23:07 +08:00
    @gerorim 嗯,前端这块不是我的强项,是要优化一下,后面空了,我来弄 详细的 error code 来处理,这块的提醒。目前只有验证类型的错误会直接返回给前端,偷了个懒,哈哈。
    sbex
        13
    sbex  
       2022-12-13 09:36:20 +08:00
    写是写进去了,可是这个数量级靠 mongo 这种 db 查询真的没有问题吗?查询耗时大概需要多久?
    hopingtop
        14
    hopingtop  
    OP
       2022-12-13 10:08:17 +08:00   ❤️ 1
    @sbex 嗯,你的问题很好!这里我们可以看到,当前系统,不支持 全文搜索,不支持跳条件查询,这都是考虑到 索引大小和查询速度, 而牺牲更大的灵活性。traceId 这种查询就不说了,他是走的单索引。
    我们觉得 靠谱的日志打印,一定不是大海捞针 才找到。 一般来说通过 3 个 查询维度,就能缩小到很小的范围。所以我们只建立了一个联合索引,并且查询条件设置顺序 严格表现为 前缀形式, 比如:填了 等级筛选,才能填入短消息筛选,填入一级条件,才能使用二级条件...

    我们举一个应用场景:一个进程每天的写入量在 5000W 日志,那么我们设置 此进程 3 天分一片, 那么此模块下,单集合容量差不多在 1.5 亿的情况。这个时候如果时间范围控制的比较好,查询返回是在 毫秒 级别的。因为缓存问题,相似查询条件,第二次查询会更快。
    当然这里就会产生一个限制,就是单次最大查询时间范围只有 3 天,我们不支持自动跨集合查询。因为产生了跨集合查询,可能会导致资源占用不可控。

    因为我们自定义了 collection 隔离,所以需要大量 IO 查询的情况下,对其他的进程写入和查询也是不受影响的。

    我们知道 Count 是很耗时的,所以在查询的时候我们 优化了查询方式,异步最大 Count 5W 条 | MaxTimeout 3s 。 所这里存在的问题就是,日志条件筛选后还大于 5W 条 Count 就是不准的了。


    如果写入量还很大,比如一天达到了 3-5 亿,因为我们的最小粒度是天分片。所以 2c4g 的 mongo 对单表 5 亿的筛选是很有压力的。不过还是特别恭喜你!你可以有更多的钱 去升级更好的系统了。 或者升级此系统的 Mongo 也可以!
    MaxFang
        15
    MaxFang  
       2022-12-13 22:29:53 +08:00
    支持!围观。
    aaaaaaaaa
        16
    aaaaaaaaa  
       2022-12-19 20:29:10 +08:00
    请问是否支持第三方导入?比如只用它的 server 端,client 不用 go ,使用其他语言写 log ,然后通过 logstash 或 filebeat 等工具录入
    hopingtop
        17
    hopingtop  
    OP
       2022-12-20 18:38:07 +08:00
    @aaaaaaaaa 因为是自有协议,目前不支持 公共第三方导入。
    /api 有协议编码文件,不过没有详细的文档
    aaaaaaaaa
        18
    aaaaaaaaa  
       2022-12-22 17:19:45 +08:00
    @hopingtop 感谢,非常好的东西,希望以后能支持第三方收集工具导入,这样就不限制语言了,无痛切换
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1005 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 18:53 · PVG 02:53 · LAX 11:53 · JFK 14:53
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.