Golang 有没有什么方法能解决高并发时, log 的输出问题? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
ikw
V2EX    Go 编程语言

Golang 有没有什么方法能解决高并发时, log 的输出问题?

  •  
  •   ikw
    zwpaper 2017-06-16 21:35:15 +08:00 3278 次点击
    这是一个创建于 3111 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在写程序,自己调试的时候没什么问题,真正用的时候发现日志特别乱,才发现并发的时候,日志都打一起去了,虽然也是行输出的,但是就不好找运行的流程了。

    所以在想,能不能有什么办法,在并发的时候,能区分一下不同 goroutine 的日志

    第一个想到打 goroutine ID,但是这个被 Google 否决了,并不能拿到这个 ID。 尴尬点的方法,自己生成一个 ID,也是一种方案,但是太不优雅了

    找日志库,好像也没人讨论出这方面比较好的库

    不知道在座各位有没有什么好一点的解决方案?

    19 条回复    2017-06-17 11:47:29 +08:00
    wweir
        1
    wweir  
       2017-06-16 22:02:21 +08:00 via Android
    针对调用链(栈)区分上下文,把上下文作为 tag 打到日志里。

    context 包里加上全局唯一 ID 可以一定程度上解决分布式调用链追踪问题,不过这方法对你的问题而言,有点过重了
    est
        2
    est  
       2017-06-16 22:17:24 +08:00
    再开一个 goroutine 专门把数组转换成日志并且定时 flush。
    cxbig
        3
    cxbig  
       2017-06-16 22:28:43 +08:00   1
    现在比较流行 ELK 日志管理 https://www.elastic.co/
    找现成试用 有 https://logz.io/
    ikw
        4
    ikw  
    OP
       2017-06-16 23:17:21 +08:00
    @wweir #1 针对调用链这个不太理解,现在就是在并发的时候,各个 goroutine 都有自己的调用链,打到一起就乱了

    确实是想找一个能稍微简单一点的方案
    ikw
        5
    ikw  
    OP
       2017-06-16 23:18:30 +08:00
    @cxbig #3 ELK 就更重了,而且 ELK 首先也得在打印的时候能区分吧?
    ikw
        6
    ikw  
    OP
       2017-06-16 23:19:10 +08:00
    @est #2 这个方案写着写着,应该就是一个 log 库了吧。。。
    devops
        7
    devops  
       2017-06-16 23:37:01 +08:00
    蛤蛤,这个问题我搞过,overhead 最小的办法是修改 runtime 库,加上这个函数。

    func GoID() int64 {
    return getg().goid
    }
    ikw
        8
    ikw  
    OP
       2017-06-16 23:42:50 +08:00
    @devops #7 对了,这个也查到过,但是改人官方库,总感觉有点太 tricky 了。。。
    cxbig
        9
    cxbig  
       2017-06-16 23:43:51 +08:00
    @zwpaper ELK 可以方便的分析和归类日志
    至于区分的问题,每个进程生成一个随机 key 怎么就不优雅呢?
    mingyun
        10
    mingyun  
       2017-06-16 23:45:01 +08:00
    @cxbig nice
    ikw
        11
    ikw  
    OP
       2017-06-17 00:05:07 +08:00
    @cxbig #9 目前看来就这个方法最简单了
    ikw
        12
    ikw  
    OP
       2017-06-17 00:05:42 +08:00
    @cxbig #9 还想看看大家有没有一些不一样的思路
    cxbig
        13
    cxbig  
       2017-06-17 00:13:15 +08:00
    @zwpaper 你还可以直接用 stream 发出去,不写 FS。
    https://github.com/omc/dendrite

    并发量大的话可以用 Kafka 之类的中间件可以进一步稳定性能。
    herozem
        14
    herozem  
       2017-06-17 01:40:15 +08:00 via iPhone
    在 nginx 上加一个 requestID ?然后 elk 再归一下类
    wweir
        15
    wweir  
       2017-06-17 07:03:41 +08:00 via Android   1
    @zwpaper 最简单轻量的两种做法,
    通常是在函数的参数中(或者方法的结构体中),加个 context 保存 tag,打日志的时候带上这个 tag。
    另一个更轻量省事,引入一个第三方 errors 包,报错一层一层手动加调用栈。遇到 goruntine 加上其 id 或者方便识别的随机字符串

    PS:扯 elk 大数据之流纯属扯淡,日志乱到人都分辨,工具更是没法分辨
    TheCure
        16
    TheCure  
       2017-06-17 10:13:27 +08:00   2
    context 不就是干这个的么
    mengzhuo
        17
    mengzhuo  
       2017-06-17 10:37:57 +08:00 via iPhone   1
    思路问题
    1. 加上日志等级
    2. 不要输出没必要的调试日志
    3. UT 保证程序的正确性,而不是肉眼看日志
    ikw
        18
    ikw  
    OP
       2017-06-17 10:41:57 +08:00 via iPhone
    @mengzhuo
    1. 等级有,但是并不能解决并发日志问题
    2. 同一
    3. 单测做的再好,也无法避免有时候出错需要查日志吧?
    reus
        19
    reus  
       2017-06-17 11:47:29 +08:00
    一般只有 panic 日志,也就是,如果打出日志来,就说明需要我要干预
    不需要关心的都直接入库
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1155 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 17:56 PVG 01:56 LAX 09:56 JFK 12:56
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86