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 相关文章推荐
golang中切片copy复制和等号复制的区别介绍
Apr 27 Golang
goland 清除所有的默认设置操作
Apr 28 Golang
golang json数组拼接的实例
Apr 28 Golang
golang DNS服务器的简单实现操作
Apr 30 Golang
go语言中GOPATH GOROOT的作用和设置方式
May 05 Golang
go类型转换及与C的类型转换方式
May 05 Golang
golang 实现时间戳和时间的转化
May 07 Golang
go web 预防跨站脚本的实现方式
Jun 11 Golang
手把手教你导入Go语言第三方库
Aug 04 Golang
Go语言并发编程 sync.Once
Oct 16 Golang
Golang 1.18 多模块Multi-Module工作区模式的新特性
Apr 11 Golang
Golang MatrixOne使用介绍和汇编语法
Apr 19 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
兼容PHP5的PHP目录管理函数库
2008/07/10 PHP
鸡肋的PHP单例模式应用详解
2013/06/03 PHP
yii的CURD操作实例详解
2014/12/04 PHP
php中使用url传递数组的方法
2015/02/11 PHP
php json_encode与json_decode详解及实例
2016/12/13 PHP
javascript 写类方式之一
2009/07/05 Javascript
js 获取中文拼音,Select自动匹配字母获取值的代码
2009/09/23 Javascript
JavaScript 页面坐标相关知识整理
2010/01/09 Javascript
Jquery 表格合并的问题分享
2011/09/17 Javascript
cookie中的path与domain属性详解
2013/12/18 Javascript
手机端网页点击链接触发自动拨打或保存电话的示例代码
2014/08/15 Javascript
javascript实现根据身份证号读取相关信息
2014/12/17 Javascript
扒一扒JavaScript 预解释
2015/01/28 Javascript
用JavaScript实现对话框的教程
2015/06/04 Javascript
JS实现淡蓝色简洁竖向Tab点击切换效果
2015/10/06 Javascript
基于jquery实现图片放大功能
2016/05/07 Javascript
js严格模式总结(分享)
2016/08/22 Javascript
JavaScript定时器实现的原理分析
2016/12/06 Javascript
jQuery 中msgTips 顶部弹窗效果实现代码
2017/08/14 jQuery
微信小程序使用checkbox显示多项选择框功能【附源码下载】
2017/12/11 Javascript
Vue下滚动到页面底部无限加载数据的示例代码
2018/04/22 Javascript
解决vue中监听input只能输入数字及英文或者其他情况的问题
2018/08/30 Javascript
Vue Render函数原理及代码实例解析
2020/07/30 Javascript
[46:20]TFT vs Secret Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python遍历 truple list dictionary的几种方法总结
2016/09/11 Python
python 计算一个字符串中所有数字的和实例
2019/06/11 Python
django多个APP的urls设置方法(views重复问题解决)
2019/07/19 Python
如何基于Python Matplotlib实现网格动画
2020/07/20 Python
工地门卫岗位职责
2013/12/30 职场文书
对孩子的寄语
2014/04/09 职场文书
公司捐款倡议书
2014/05/14 职场文书
档案信息化建设方案
2014/05/16 职场文书
领导班子作风建设年个人整改措施
2014/09/29 职场文书
2015年公路路政个人工作总结
2015/07/24 职场文书
python cv2图像质量压缩的算法示例
2021/06/04 Python
25张裸眼3D图片,带你重温童年的记忆,感受3D的魅力
2022/02/06 杂记