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. 基于 Blazor 开发五子棋⚫⚪小游戏

    今天是农历五月初五,端午节.在此,祝大家端午安康! 端午节是中华民族古老的传统节日之一.端午也称端五,端阳.此外,端午节还有许多别称,如:午日节.重五节.五月节.浴兰节.女儿节.天中节.地腊.诗人节. ...

  2. linux 配置ssh免密登录

    一.SSH概念(百度) SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定:SSH 为建立在应用层基础上的安全协议.SSH 是目 ...

  3. dart快速入门教程 (5)

    5.函数 5.1.函数定义 语法: 返回值类型 函数名(参数类型 参数1, 参数类型 参数2,...) { // 函数体 return '返回值' } 举例: void main() { print( ...

  4. python用类的方式创建线程---自创建类

    用类的方式创建线程---自创建类 import threadingimport time class MyThread(threading.Thread):#自建MyThread类继承threadin ...

  5. C program Language 'EOF' and 'getchar()'

    #include <stdio.h> void main() { int c; c=getchar(); while(c!=EOF) { putchar(c); c=getchar(); ...

  6. (私人收藏)古风PPT高级灰蓝传艺

    古风PPT高级灰蓝传艺 https://pan.baidu.com/s/1ADgTfif8i6JqKORLXhTHHgn05p

  7. 常见Python的Web开发框架

    在今天,Python里有很多开发框架用来帮助你轻松创建web应用.web开发框架存在的意义就在于可以快速便捷的构建应用,而不用去在意那些没必要的技术细节(协议.报文.数据结构). 到2020年为止,基 ...

  8. 关于gulp复制文件时把整个目录结构都复制的问题解决

    有这么个场景,在开发时分模块开发,但是发布时不一定将按模块分布,比如,为了便于开发,图片是按照模块存放的,但是发布时只是放在images文件夹下,此时就需要用到本文中提到的插件gulp-flatten ...

  9. gulp之demo

    1.安装gulp cnpm install -g gulp; 2.然后还需要在当前目录安装gulp,具体不详,只知道安装了之后会在当前目录下的node_modules下多一个gulp文件夹 cnpm ...

  10. CF1051F The Shortest Statement 题解

    题目 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You sho ...