Goroutine id 的获取方式

之前做的项目中,会使用 goroutine-id(以下简称 goid) 作为日志中的一个标识参数。而 goroutine 的相关信息是不对外暴露的。想要获取 goid,除了直接修改 Golang 源码的骚操作,通常会使用两种方式:

  • 一种是通过堆栈获取。
func Goid() int {
var buf [64]byte
n := runtime.Stack(buf[:], false)
goroutineId := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
id, err := strconv.Atoi(goroutineId)
if err != nil {
panic(fmt.Sprintf("cannot get goroutine id: %v", err))
}
return id
}

这种获取方式会牺牲一部分性能,好处是不用修改 Golang 的源码,不用关心 Go 语言版本,省去后期维护的麻烦。

  • 另一种获取 goid 的方式是建立 goroutine 的本地存储。相关库参考:

    github.com/v2pro/plz。这种方式同样不入侵源码,更为高效,但是需要随 Go 语言的版本进行维护。

以上获取 goid 的方法在搜索引擎中可以很容易地获取到。但是,这是不是反而引发了 goid 的滥用呢?换句话说,goid 是否是一个伪需求呢?

 

为什么不应该使用goroutine id?

根据 Go 语言的官方设计,我们是无法对一个运行中的 goroutine 进行操作的。coder 对协程不具有管理权限,一旦使用 go 关键字开启了一个协程,只能任其运行。不像在其他语言中管理线程,Go 不需要一个线程的标识来记录对于线程的管理。

在大多数业务场景里,服务端启用一个协程处理一个任务(多数情况下是一个请求)。这种场景下,我们使用 goid 的目的,更多地在于标识一个任务。然而 goroutine 是一种可复用资源。一个 goid10 的协程,可以在处理完一个任务后,重置状态,再处理另一个任务。任务是唯一性的,而 goid 总会重复。因此使用 goid 作为标识会引发混乱,实际使用中仍然需要其他标识作为参考。

而在一个任务对应多个协程的场景中,goid 更是徒劳无益。

 

标识与渠道相关,而不是与处理相关

正确的做法是使用编程的方式标识一个任务。这不仅契合 标识 本身的含义,也更加具有扩展性。

微服务架构越来越流行。比起设计一个庞大臃肿的系统,人们更倾向于把它拆分为多个小巧的系统,各司其职。这也符合 devOps 的发展方向。这种情况下,一个从系统入口就生成并透传的唯一标识是必须的。这是链路追踪的基础。

此外,对于分布式事务来说,一个事务也需要一个唯一标识。

为什么不应该使用goroutine id?的更多相关文章

  1. golang goroutine 介绍

    Goroutine 是用户态自己实现的线程,调度方式遇到IO/阻塞点方式就会让出cpu时间(其实也看编译器的实现,如果TA在代码里面插入一些yield,也是可以的. 反正现在不是抢占式的.) 不能设置 ...

  2. golang的并发不等于并行

    先 看下面一道面试题: func main() { runtime.GOMAXPROCS(1) wg := sync.WaitGroup{} wg.Add(20) for i := 0; i < ...

  3. <转>年终盘点!2017年超有价值的Golang文章

    马上就要进入2018年了,作为年终的盘点,本文列出了一些2017年的关于Go编程的一些文章,并加上简短的介绍. 文章排名不分先后, 文章也不一定完全按照日期来排列.我按照文章的大致内容分了类,便于查找 ...

  4. Go调试工具—— Delve

    参考https://github.com/go-delve/delve 安装 首先你必须有等于或高于1.8版本的Go,我的版本是: userdeMBP:go-learning user$ go ver ...

  5. go 面试题总结

    1.什么是goroutine,他与process, thread有什么区别? 2. 什么是channel,为什么它可以做到线程安全? 3. 了解读写锁吗,原理是什么样的,为什么可以做到? 4. 如何用 ...

  6. 06 Frequently Asked Questions (FAQ) 常见问题解答 (常见问题)

    Frequently Asked Questions (FAQ) Origins 起源 What is the purpose of the project? What is the history ...

  7. Go语言 7 并发编程

    文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 今天我们学习Go语言编程的第七章,并发编程.语言级别 ...

  8. go——并发

    并发与并行的区别: 并发:逻辑上具备同时处理多个任务的能力. 并行:物理上在同一时刻执行多个并发任务.通常都会说程序是并发设计的,也就是说它允许多个任务同时执行,但实际上并不一定真在同一时刻发生.在单 ...

  9. golang ----并发 && 并行

    Go 语言的线程是并发机制,不是并行机制. 那么,什么是并发,什么是并行? 并发是不同的代码块交替执行,也就是交替可以做不同的事情. 并行是不同的代码块同时执行,也就是同时可以做不同的事情. 举个生活 ...

随机推荐

  1. Docker 快速入门(一)- 情况介绍和安装

    欢迎您! 很高兴您想学习 Docker . 这个页面包含了如何开始使用 Docker 的循序渐进的说明. Docker 快速入门培训模块教你如何: 设置 Docker 环境(在本页) 构建并运行您的镜 ...

  2. 入门大数据---通过Flume、Sqoop分析日志

    一.Flume安装 参考:Flume 简介及基本使用 二.Sqoop安装 参考:Sqoop简介与安装 三.Flume和Sqoop结合使用案例 日志分析系统整体架构图: 3.1配置nginx环境 请参考 ...

  3. 【博弈】HDU - 5963 朋友

    题目 B君在围观一群男生和一群女生玩游戏,具体来说游戏是这样的: 给出一棵n个节点的树,这棵树的每条边有一个权值,这个权值只可能是0或1. 在一局游戏开始时,会确定一个节点作为根.接下来从女生开始,双 ...

  4. JavaScript基础数组的字面声名法(010)

    1.两种方法的对比 数组在JavaScript中,就像大多数的其它语言 一样,是对象.我们可以使用JavaScript内置的数组构造函数Array()来创建数组.就象对象的字面声名法一样,数组也可以采 ...

  5. linux系统,没有安装任何编辑器的情况,如何操作文件

    [清空文件] echo  " " > filename [添加内容] echo "123" >> filename

  6. C++多种方法枚举串口号

    部分方式没结果,思路应该是没错. //7. std::cout << "M8: SetupDiGetClassDevs " << std::endl; // ...

  7. MySQL 查询 存储过程 视图 触发器 函数 索引 建表语句 数据库版本 当前登录用户 当前数据库名称

    MySQL 查询 存储过程 视图 触发器 函数 索引 建表语句 数据库版本 当前登录用户 当前数据库名称   INFORMATION_SCHEMA.TABLES INFORMATION_SCHEMA. ...

  8. Linux进程监控命令

    最近使用centos在建站,没有用市面上的什么服务商的服务器,自己用树莓派3B+建了这个博客.但是发现经常宕机,所以想看看服务器在干什么,百度了很久,发现vmstat命令不错,拿出来推荐推荐. 这是我 ...

  9. 什么?你还不会通过纯js提交表单?

    如果程序已经封装好了, 不管后台是java .asp.net   .还是php   ?这个时候你的客户突然追加说我要 追加表单验证?   what  妇产科    怎么办? submit  自带刷新效 ...

  10. Django---进阶9

    目录 自定义分页器的拷贝及使用 Forms组件 前戏 基本使用 校验数据 渲染标签 展示提示信息 钩子函数(HOOK) forms组件其他参数及补充知识点 作业 自定义分页器的拷贝及使用 " ...