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 interface判断为空nil的实现代码
Apr 24 Golang
Go语言带缓冲的通道实现
Apr 26 Golang
Golang 使用Map实现去重与set的功能操作
Apr 29 Golang
解决golang结构体tag编译错误的问题
May 02 Golang
Goland使用Go Modules创建/管理项目的操作
May 06 Golang
Go 在 MongoDB 中常用查询与修改的操作
May 07 Golang
Golang生成Excel文档的方法步骤
Jun 09 Golang
Golang的继承模拟实例
Jun 30 Golang
golang实现浏览器导出excel文件功能
Mar 25 Golang
Go语言grpc和protobuf
Apr 13 Golang
Golang map映射的用法
Apr 22 Golang
Go结合Gin导出Mysql数据到Excel表格
Aug 05 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将字符串全部转换成大写或者小写的方法
2015/03/17 PHP
使用ltrace工具跟踪PHP库函数调用的方法
2016/04/25 PHP
Yii2使用swiftmailer发送邮件的方法
2016/05/03 PHP
jquery validation插件表单验证的一个例子
2010/03/03 Javascript
Jquery Ajax学习实例 向页面发出请求,返回XML格式数据
2010/03/14 Javascript
jQuery实现图片信息的浮动显示实例代码
2013/08/28 Javascript
javascript中字符串的定义示例代码
2013/12/19 Javascript
Node.js中的缓冲与流模块详细介绍
2015/02/11 Javascript
js实现touch移动触屏滑动事件
2015/04/17 Javascript
详解JavaScript中的表单验证
2015/06/16 Javascript
jQuery对table表格进行增删改查
2020/12/22 Javascript
JavaScript原生节点操作小结
2017/01/17 Javascript
JS操作xml对象转换为Json对象示例
2017/03/25 Javascript
关于Vue单页面骨架屏实践记录
2017/12/13 Javascript
vue-awesome-swiper 基于vue实现h5滑动翻页效果【推荐】
2018/11/08 Javascript
Vue指令之 v-cloak、v-text、v-html实例详解
2019/08/08 Javascript
python 环境变量和import模块导入方法(详解)
2017/07/11 Python
人机交互程序 python实现人机对话
2017/11/14 Python
用python 批量更改图像尺寸到统一大小的方法
2018/03/31 Python
实例讲解Python脚本成为Windows中运行的exe文件
2019/01/24 Python
浅谈Scrapy网络爬虫框架的工作原理和数据采集
2019/02/07 Python
Python实现基于SVM的分类器的方法
2019/07/19 Python
Python Request爬取seo.chinaz.com百度权重网站的查询结果过程解析
2019/08/13 Python
Python 使用元类type创建类对象常见应用详解
2019/10/17 Python
Keras SGD 随机梯度下降优化器参数设置方式
2020/06/19 Python
详解Canvas 实现炫丽的粒子运动效果(粒子生成文字)
2018/02/01 HTML / CSS
Exoticca英国:以最优惠的价格提供豪华异国情调旅行
2018/10/18 全球购物
英国花园、DIY、电器和家居用品商店:Robert Dyas
2019/03/18 全球购物
荷兰度假屋租赁网站:Aan Zee
2020/02/28 全球购物
不打扫卫生检讨书
2014/02/12 职场文书
药剂专业自荐信范文
2014/04/16 职场文书
幼儿学前班评语
2014/12/29 职场文书
安装工程师岗位职责
2015/02/13 职场文书
2015年高校图书馆工作总结
2015/04/30 职场文书
2016年重阳节慰问信
2015/12/01 职场文书
解决Mysql多行子查询的使用及空值问题
2022/01/22 MySQL