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语言-在mac下brew升级golang
Apr 25 Golang
Golang 正则匹配效率详解
Apr 25 Golang
解决Golang中ResponseWriter的一个坑
Apr 27 Golang
golang 比较浮点数的大小方式
May 02 Golang
聊聊golang中多个defer的执行顺序
May 08 Golang
Go Plugins插件的实现方式
Aug 07 Golang
Go语言实现一个简单的并发聊天室的项目实战
Mar 18 Golang
Golang使用Panic与Recover进行错误捕获
Mar 22 Golang
Golang map映射的用法
Apr 22 Golang
GoFrame框架数据校验之校验结果Error接口对象
Jun 21 Golang
Go 内联优化让程序员爱不释手
Jun 21 Golang
Go语言测试库testify使用学习
Jul 23 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
mysq GBKl乱码
2006/11/28 PHP
ThinkPHP跳转页success及error模板实例教程
2014/07/17 PHP
Laravel Memcached缓存驱动的配置与应用方法分析
2016/10/08 PHP
利用php-cli和任务计划实现刷新token功能的方法
2017/05/03 PHP
用JavaScript对JSON进行模式匹配(Part 1-设计)
2010/07/17 Javascript
原生javascript实现图片轮播效果代码
2010/09/03 Javascript
jquery 跨域访问问题解决方法(笔记)
2011/06/08 Javascript
js/jQuery简单实现选项卡功能
2014/01/02 Javascript
js窗口关闭提示信息(兼容IE和firefox)
2015/10/23 Javascript
理解 JavaScript Scoping & Hoisting(二)
2015/11/18 Javascript
js随机生成26个大小写字母
2016/02/12 Javascript
基于jquery实现简单的分页控件
2016/03/17 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
2016/12/14 Javascript
如何解决hover在ie6中的兼容性问题
2016/12/15 Javascript
微信小程序--onShareAppMessage分享参数用处(页面分享)
2017/04/18 Javascript
JavaScript 中的 this 简单规则
2017/09/19 Javascript
vue中实现上传文件给后台实例详解
2019/08/22 Javascript
微信小程序服务器日期格式化问题
2020/01/07 Javascript
解决elementUI 切换tab后 el_table 固定列下方多了一条线问题
2020/07/19 Javascript
[04:50]DOTA2亚洲邀请赛小组赛第四日 TOP10精彩集锦
2015/02/02 DOTA
在Python的struct模块中进行数据格式转换的方法
2015/06/17 Python
对Python中数组的几种使用方法总结
2018/06/28 Python
python代码过长的换行方法
2018/07/19 Python
Python单元测试工具doctest和unittest使用解析
2019/09/02 Python
python 读取更新中的log 或其它文本方式
2019/12/24 Python
将python包发布到PyPI和制作whl文件方式
2019/12/25 Python
jupyter notebook 重装教程
2020/04/16 Python
解决pytorch 数据类型报错的问题
2021/03/03 Python
西班牙在线宠物商店:zooplus.es
2017/02/24 全球购物
荷兰男士时尚网上商店:Suitable
2017/12/25 全球购物
国际贸易专业推荐信
2013/11/15 职场文书
《再别康桥》教学反思
2014/02/12 职场文书
学校安全教育月活动总结
2014/07/07 职场文书
2014年党的群众路线活动个人整改措施
2014/10/28 职场文书
解决Django transaction进行事务管理踩过的坑
2021/04/24 Python
CentOS7 minimal 最小化安装网络设置过程
2022/12/24 Servers