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二维切片初始化的实现
Apr 08 Golang
为什么不建议在go项目中使用init()
Apr 12 Golang
golang判断key是否在map中的代码
Apr 24 Golang
Go语言-为什么返回值为接口类型,却返回结构体
Apr 24 Golang
Go 实现英尺和米的简单单位换算方式
Apr 29 Golang
Golang实现AES对称加密的过程详解
May 20 Golang
go语言中http超时引发的事故解决
Jun 02 Golang
Go语言实现Base64、Base58编码与解码
Jul 26 Golang
golang中的struct操作
Nov 11 Golang
golang为什么要统一错误处理
Apr 03 Golang
golang操作rocketmq的示例代码
Apr 06 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/06/12 PHP
PHP Filter过滤器全面解析
2016/08/09 PHP
Prototype Template对象 学习
2009/07/19 Javascript
jquery获取input表单值的代码
2010/04/19 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
2014/01/13 Javascript
Jquery实现控件的隐藏和显示实例
2014/02/08 Javascript
jQuery下拉友情链接美化效果代码分享
2015/08/26 Javascript
jQuery事件对象总结
2016/10/17 Javascript
微信JSAPI Ticket接口签名详解
2020/06/28 Javascript
vue实现表格数据的增删改查
2017/07/10 Javascript
JavaScript对象拷贝与Object.assign用法实例分析
2018/06/20 Javascript
Vue 理解之白话 getter/setter详解
2019/04/16 Javascript
vue路由切换之淡入淡出的简单实现
2019/10/31 Javascript
JavaScript实现指定数量的并发限制的示例代码
2020/03/10 Javascript
vue总线机制(bus)知识点详解
2020/05/10 Javascript
Node Mongoose用法详解【Mongoose使用、Schema、对象、model文档等】
2020/05/13 Javascript
vue中el-input绑定键盘按键(按键修饰符)
2020/07/22 Javascript
[02:27]刀塔重生降临
2015/10/14 DOTA
python进阶教程之异常处理
2014/08/30 Python
python pandas中DataFrame类型数据操作函数的方法
2018/04/08 Python
python利用pandas将excel文件转换为txt文件的方法
2018/10/23 Python
详解用python写网络爬虫-爬取新浪微博评论
2019/05/10 Python
浅谈Python协程
2020/06/17 Python
Prometheus开发中间件Exporter过程详解
2020/11/30 Python
python opencv实现图像配准与比较
2021/02/09 Python
html5实现完美兼容各大浏览器的播放器
2014/12/26 HTML / CSS
阿迪达斯奥地利官方商城:adidas.at
2016/10/16 全球购物
人力资源管理专业毕业生自我评价
2013/09/21 职场文书
未受刑事制裁公证证明
2014/09/20 职场文书
2014银行授权委托书样本
2014/10/04 职场文书
护理见习报告范文
2014/11/03 职场文书
基督教追悼会答谢词
2015/09/29 职场文书
php 文件上传至OSS及删除远程阿里云OSS文件
2021/07/04 PHP
Python列表的索引与切片
2022/04/07 Python
Mysql 8.x 创建用户以及授予权限的操作记录
2022/04/18 MySQL
springboot实现string转json json里面带数组
2022/06/16 Java/Android