Golang Go语言中有没有什么方法能解决高并发时,log的输出问题?
最近在写程序,自己调试的时候没什么问题,真正用的时候发现日志特别乱,才发现并发的时候,日志都打一起去了,虽然也是行输出的,但是就不好找运行的流程了。
所以在想,能不能有什么办法,在并发的时候,能区分一下不同 goroutine 的日志
第一个想到打 goroutine ID,但是这个被 Google 否决了,并不能拿到这个 ID。 尴尬点的方法,自己生成一个 ID,也是一种方案,但是太不优雅了
找日志库,好像也没人讨论出这方面比较好的库
不知道在座各位有没有什么好一点的解决方案?
Golang Go语言中有没有什么方法能解决高并发时,log的输出问题?
更多关于Golang Go语言中有没有什么方法能解决高并发时,log的输出问题?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
针对调用链(栈)区分上下文,把上下文作为 tag 打到日志里。
context 包里加上全局唯一 ID 可以一定程度上解决分布式调用链追踪问题,不过这方法对你的问题而言,有点过重了
更多关于Golang Go语言中有没有什么方法能解决高并发时,log的输出问题?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
再开一个 goroutine 专门把数组转换成日志并且定时 flush。
现在比较流行 ELK 日志管理 https://www.elastic.co/
找现成试用 有 https://logz.io/
#1 针对调用链这个不太理解,现在就是在并发的时候,各个 goroutine 都有自己的调用链,打到一起就乱了😳
确实是想找一个能稍微简单一点的方案
#3 ELK 就更重了,而且 ELK 首先也得在打印的时候能区分吧?
#2 这个方案写着写着,应该就是一个 log 库了吧。。。
蛤蛤,这个问题我搞过,overhead 最小的办法是修改 runtime 库,加上这个函数。
func GoID() int64 {
return getg().goid
}
#7 对了,这个也查到过,但是改人官方库,总感觉有点太 tricky 了。。。
ELK 可以方便的分析和归类日志
至于区分的问题,每个进程生成一个随机 key 怎么就不优雅呢?
nice
#9 目前看来就这个方法最简单了
#9 还想看看大家有没有一些不一样的思路
你还可以直接用 stream 发出去,不写 FS。
https://github.com/omc/dendrite
并发量大的话可以用 Kafka 之类的中间件可以进一步稳定性能。
在 nginx 上加一个 requestID ?然后 elk 再归一下类
最简单轻量的两种做法,
通常是在函数的参数中(或者方法的结构体中),加个 context 保存 tag,打日志的时候带上这个 tag。
另一个更轻量省事,引入一个第三方 errors 包,报错一层一层手动加调用栈。遇到 goruntine 加上其 id 或者方便识别的随机字符串
PS:扯 elk 大数据之流纯属扯淡,日志乱到人都分辨,工具更是没法分辨
context 不就是干这个的么
1. 等级有,但是并不能解决并发日志问题
2. 同一
3. 单测做的再好,也无法避免有时候出错需要查日志吧?
一般只有 panic 日志,也就是,如果打出日志来,就说明需要我要干预
不需要关心的都直接入库
在Golang中处理高并发时的日志输出问题,可以通过以下几种方法来确保日志的准确性和性能:
-
使用带缓冲的channel:创建一个带缓冲的channel来接收日志消息,然后在单独的goroutine中处理这些消息并输出到日志文件中。这种方法可以避免在高并发时直接写入日志文件导致的性能瓶颈和锁竞争。
-
并发安全的日志库:使用像
zap
或logrus
这样的并发安全日志库。这些库内部已经实现了高效的并发处理机制,能够很好地处理高并发下的日志输出。 -
文件锁:如果直接使用标准库的
log
包或文件操作,可以考虑在写入日志时使用文件锁(如sync.Mutex
)来保证并发安全。但这种方法可能会影响性能,需要权衡。 -
异步日志:将日志记录操作设计为异步的,即记录日志时只是将日志信息放入一个队列或channel,然后由单独的goroutine负责实际的日志输出。这样可以减少日志记录操作对主业务逻辑的阻塞。
-
日志轮转:在高并发场景下,日志文件可能会迅速增长。使用日志轮转机制(如按大小或时间分割日志文件)可以保持日志文件的大小在可控范围内,并便于后续的分析和管理。
综上所述,选择哪种方法取决于具体的应用场景和性能要求。在高并发环境中,推荐使用带缓冲的channel或并发安全的日志库来处理日志输出问题。