标签:官方 ola 相关 evo 服务架构 return 架构 线程 情况下
之前做的项目中,会使用 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
的本地存储。相关库参考:Go
语言的版本进行维护。以上获取 goid
的方法在搜索引擎中可以很容易地获取到。但是,这是不是反而引发了 goid
的滥用呢?换句话说,goid
是否是一个伪需求呢?
?
根据 Go
语言的官方设计,我们是无法对一个运行中的 goroutine
进行操作的。coder 对协程不具有管理权限,一旦使用 go
关键字开启了一个协程,只能任其运行。不像在其他语言中管理线程,Go
不需要一个线程的标识来记录对于线程的管理。
在大多数业务场景里,服务端启用一个协程处理一个任务(多数情况下是一个请求)。这种场景下,我们使用 goid
的目的,更多地在于标识一个任务。然而 goroutine
是一种可复用资源。一个 goid
为 10
的协程,可以在处理完一个任务后,重置状态,再处理另一个任务。任务是唯一性的,而 goid
总会重复。因此使用 goid
作为标识会引发混乱,实际使用中仍然需要其他标识作为参考。
而在一个任务对应多个协程的场景中,goid
更是徒劳无益。
?
正确的做法是使用编程的方式标识一个任务。这不仅契合 标识
本身的含义,也更加具有扩展性。
微服务架构越来越流行。比起设计一个庞大臃肿的系统,人们更倾向于把它拆分为多个小巧的系统,各司其职。这也符合 devOps 的发展方向。这种情况下,一个从系统入口就生成并透传的唯一标识是必须的。这是链路追踪的基础。
此外,对于分布式事务来说,一个事务也需要一个唯一标识。
标签:官方 ola 相关 evo 服务架构 return 架构 线程 情况下
原文地址:https://www.cnblogs.com/win-for-life/p/13355224.html