Golang 并发下的问题定位及解决方案


Posted in Golang onMarch 16, 2022

问题描述

在使用 gin-swagger 的过程中, 经常会发生因为缺少 jsontag 而导致的异常。 由于 gin-swagger 是并发执行的, 输出的日志本身是错位的。 这就导致无法定义是哪一个结构体缺少 tag 导致的。

Golang 并发下的问题定位及解决方案

一般而言, 这种时候只能一个个点开去检查。

解决方案

思路 : 要是每行日志带当前 goroutine_id 的话, 是不是就可以准确定位到报错的 goroutine 他打印的日志是哪些了呢!

说做就做

实现思路

  • 查看当前日志是怎么打印的

发现 gin-swagger 日志直接调用的 golang 的标准库 log

由于没有对log初始化, 所以默认使用的是 stdout

log.Printf("Picking operation from %s\n", aurora.Blue(funType.FullName()))
  • 如果想要给日志中添加 goroutine_id 的话, 就需要在调用 log.Printf 的时候获取当前 goroutine 的 id , 所以首先要解决的是怎么获取 goroutine_id 的问题。

调研后发现了集中常见的获取 goroutine_id 的方法:

2.1 通过栈信息解析后获取

func GetGID() uint64 {
    b := make([]byte, 64)
    b = b[:runtime.Stack(b, false)]
    b = bytes.TrimPrefix(b, []byte("goroutine "))
    b = b[:bytes.IndexByte(b, ' ')]
    n, _ := strconv.ParseUint(string(b), 10, 64)
    return n
}

2.2 修改 Go 源码获取

# src/runtime/runtime2.go
func Goid() int64 {
    _g_ := getg()
    return _g_.goid
}

2.3 通过 CGO 获取

文件 id.c

#include "runtime.h"
int64 ·Id(void) {
    return g->goid;
}

文件 id.go

package id
func Id() int64

另外还可以通过汇编获取 goroutine_id

由于go的版本不同,goroutine的结构也可能不同, 所以此处我直接调用一个开源实现:

https://github.com/petermattis/goid

  • 修改 gin-swagger main.go 源码, 修改 log Write 的实现

修改前

func main() {
    cmd.Execute()
}

修改后

type Out os.File
func (o Out) Write(b []byte) (int, error) {
    prefix := fmt.Sprintf("gid-%d: ", goid.Get())
    all := make([]byte, len(b)+len(prefix))
    all = []byte(prefix)
    all = append(all, b...)
    f := os.File(o)
    return f.Write(all)
}
func main() {
    var out Out
    out = Out(os.Stdout)
    log.SetOutput(out)
    cmd.Execute()

这样修改后,每次 gin-swagger 调用 log 打印日志都时候, 都会使用我定义的 Write 方法, Write 方法中每次打印前都会先查询出当前的 goroutine_id ,然后作为日志的前缀。

修改后的日志效果

Golang 并发下的问题定位及解决方案

从中可以看到每行日志开头,都已经加上了 goroutine_id。 只要使用 panic goroutineid 做一次 grep , 即可筛选出需要的日志了,极大的方便了定位问题。

Golang 并发下的问题定位及解决方案

cat /tmp/gin-swagger.log | grep 7647

Golang 并发下的问题定位及解决方案

到此这篇关于Golang 并发下的问题定位的文章就介绍到这了,更多相关Golang并发问题内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Golang 相关文章推荐
Go语言使用select{}阻塞main函数介绍
Apr 25 Golang
go原生库的中bytes.Buffer用法
Apr 25 Golang
golang gopm get -g -v 无法获取第三方库的解决方案
May 05 Golang
Golang 编译成DLL文件的操作
May 06 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
Go语言实现Snowflake雪花算法
Jun 08 Golang
golang 语言中错误处理机制
Aug 30 Golang
Golang中channel的原理解读(推荐)
Oct 16 Golang
Golang数据类型和相互转换
Apr 12 Golang
Go语言grpc和protobuf
Apr 13 Golang
Golang 字符串的常见操作
Apr 19 Golang
Golang gRPC HTTP协议转换示例
Jun 16 Golang
如何利用golang运用mysql数据库
深入理解go缓存库freecache的使用
Feb 15 #Golang
Go语言读取txt文档的操作方法
Jan 22 #Golang
一文搞懂Golang 时间和日期相关函数
Go语言基础切片的创建及初始化示例详解
Nov 17 #Golang
Go语言基础map用法及示例详解
Nov 17 #Golang
Go语言基础函数基本用法及示例详解
Nov 17 #Golang
You might like
php入门学习知识点七 PHP函数的基本应用
2011/07/14 PHP
PHP获取当前日期所在星期(月份)的开始日期与结束日期(实现代码)
2013/06/18 PHP
PHP资源管理框架Assetic简介
2014/06/12 PHP
List the UTC Time on a Computer
2007/06/11 Javascript
JavaScript包装对象使用介绍
2013/08/29 Javascript
JS获取键盘上任意按键的值(实例代码)
2013/11/12 Javascript
jQuery制作拼图小游戏
2015/01/12 Javascript
讲解JavaScript中for...in语句的使用方法
2015/06/03 Javascript
JavaScript中的Promise使用详解
2015/06/24 Javascript
javascript中caller和callee详解
2015/08/10 Javascript
谈谈我对JavaScript中typeof和instanceof的深入理解
2015/12/25 Javascript
jQuery 弹出层插件(推荐)
2016/05/24 Javascript
Vue如何实现组件的源码解析
2017/06/08 Javascript
jquery操作ul的一些操作笔记整理(干货)
2017/08/31 jQuery
vue-router 组件复用问题详解
2018/01/22 Javascript
一起写一个即插即用的Vue Loading插件实现
2019/10/31 Javascript
Vue的props父传子的示例代码
2020/05/20 Javascript
VUE中V-IF条件判断改变元素的样式操作
2020/08/09 Javascript
用python写的一个wordpress的采集程序
2016/02/27 Python
python中单例常用的几种实现方法总结
2018/10/13 Python
python pycharm的安装及其使用
2019/10/11 Python
Python爬虫JSON及JSONPath运行原理详解
2020/06/04 Python
深入了解Python enumerate和zip
2020/07/16 Python
Python 调用C++封装的进一步探索交流
2021/03/04 Python
纯CSS3实现的井字棋游戏
2020/11/25 HTML / CSS
夏尔巴人登珠峰品牌:Sherpa Adventure Gear
2018/02/08 全球购物
The Hut美国/加拿大:英国领先的豪华在线百货商店
2019/03/26 全球购物
戛纳奢侈品商店:Jacques Loup法国
2019/11/04 全球购物
大学生毕业求职简历的自我评价
2013/10/24 职场文书
中国梦的演讲稿
2014/01/08 职场文书
户籍证明的格式
2014/01/13 职场文书
大学生职业生涯规划书模板
2014/01/18 职场文书
建筑安全生产目标责任书
2014/07/23 职场文书
大学毕业谢师宴致辞
2015/07/27 职场文书
教师外出学习心得体会
2016/01/18 职场文书
PostgreSQL事务回卷实战案例详析
2022/03/25 PostgreSQL