您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

时间:2019-09-26 11:39:51  来源:  作者:
资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

Go 中的并发性是以 goroutine(独立活动)和 channel(用于通信)的形式实现的。处理 goroutine 时,程序员需要小心翼翼地避免泄露。如果最终永远堵塞在 I/O 上(例如 channel 通信),或者陷入死循环,那么 goroutine 会发生泄露。即使是阻塞的 goroutine,也会消耗资源,因此,程序可能会使用比实际需要更多的内存,或者最终耗尽内存,从而导致崩溃。让我们来看看几个可能会发生泄露的例子。然后,我们将重点关注如何检测程序是否受到这种问题的影响。

发送到一个没有接收者的 channel

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

假设出于冗余的目的,程序发送请求到许多后端。使用首先收到的响应,丢弃后面的响应。下面的代码将会通过等待随机数毫秒,来模拟向下游服务器发送请求:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

输出:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

每次调用 queryAll 后,goroutine 的数目会发生增长。问题在于,在接收到第一个响应后,“较慢的” goroutine 将会发送到另一端没有接收者的 channel 中。

可能的解决方法是,如果提前知道后端服务器的数量,那么使用缓存 channel。否则,只要至少有一个 goroutine 仍在工作,我们就可以使用另一个 goroutine 来接收来自这个 channel 的数据。其他的解决方案可能是使用 contextexample),利用 某些机制来取消其他请求。

从没有发送者的 channel 中接收数据

这种场景类似于发送到一个没有接收者的 channel。泄露 goroutine 这篇文章中包含了一个示例。

nil channel

写入到 nil channel 会永远阻塞:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

所以它导致死锁:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

当从 nil channel 读取数据时,同样的事情发生了:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

当传递尚未初始化的 channel 时,也可能会发生:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

在这个例子中,有一个显而易见的罪魁祸首 —— if false {,但是在更大的程序中,更容易忘记这件事,然后使用 channel 的零值(nil)。

死循环

goroutine 泄露不仅仅是因为 channel 的错误使用造成的。泄露的原因也可能是 I/O 操作上的堵塞,例如发送请求到 API 服务器,而没有使用超时。另一种原因是,程序可以单纯地陷入死循环中。

分析

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

runtime.NumGoroutine

简单的方式是使用由 runtime.NumGoroutine 返回的值。

net/http/pprof

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

调用 http://localhost:6060/debug/pprof/goroutine?debug=1 ,将会返回带有堆栈跟踪的 goroutine 列表。

runtime/pprof

要将现有的 goroutine 的堆栈跟踪打印到标准输出,请执行以下操作:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

gops

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

集成到你的程序中:

资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 


资源不断被耗尽,排查起来焦头烂额:如何避免 goroutine 泄露?

 

leaktest

这是用测试来自动检测泄露的方法之一。它基本上是在测试的开始和结束的时候,利用 runtime.Stack 获取活跃 goroutine 的堆栈跟踪。如果在测试完成后还有一些新的 goroutine,那么将其归类为泄露。


分析甚至已经在运行的程序的 goroutine 管理,以避免可能会导致内存不足的泄露,这至关重要。代码在生产上运行数日后,这样的问题通常就会出现,因此它可能会造成真正的损害。

点击原文中的 ❤ 以帮助其他人发现这个问题。如果你想实时获得新的更新,请关注原作者哦~

资源

  • 包 —— Go 编程语言
  • bufio 包实现了缓存 I/O。它封装一个 io.Reader 或者 io.Writer 对象,创建其他对象(Reader 或者……)
  • google/gops
  • gops —— 一个列出和诊断当前运行在你的系统上的 Go 进程的工具。
  • runtime:检测僵尸 goroutine · 问题 #5308 · golang/go
  • runtime 可以检测不可达 channel / mutex 等上面的 goroutine 阻塞,然后报告此类问题。这需要一个接口……
  • fortytw2/leaktest
  • leaktest - goroutine 泄露检测器。

via: https://medium.com/golangspec/goroutine-leak-400063aef468

作者:Michał Łowicki 译者:ictar 校对:polaris1119

本文由 GCTT 原创编译,Go语言中文网 荣誉推出



Tags:goroutine 泄露   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Go 中的并发性是以 goroutine(独立活动)和 channel(用于通信)的形式实现的。处理 goroutine 时,程序员需要小心翼翼地避免泄露。如果最终永远堵塞在 I/O 上(例如 channel 通信),或...【详细内容】
2019-09-26  Tags: goroutine 泄露  点击:(164)  评论:(0)  加入收藏
▌简易百科推荐
zip 是一种常见的归档格式,本文讲解 Go 如何操作 zip。首先看看 zip 文件是如何工作的。以一个小文件为例:(类 Unix 系统下)$ cat hello.textHello!执行 zip 命令进行归档:$ zip...【详细内容】
2021-12-17  Go语言中文网    Tags:Go语言   点击:(13)  评论:(0)  加入收藏
大家好,我是 polarisxu。前段时间,Russ Cox 明确了泛型相关的事情,原计划在标准库中加入泛型相关的包,改放到 golang.org/x/exp 下。目前,Go 泛型的主要设计者 ianlancetaylor 完...【详细内容】
2021-11-30  Go语言中文网    Tags:slices 包   点击:(24)  评论:(0)  加入收藏
前言最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。 但现阶段相对来说还是 Python 写的多一些,偶尔还...【详细内容】
2021-11-25  crossoverJie    Tags:Go   点击:(29)  评论:(0)  加入收藏
go-micro是基于 Go 语言用于开发的微服务的 RPC 框架,主要功能如下:服务发现,负载均衡 ,消息编码,请求/响应,Async Messaging,可插拔接口,最后这个功能牛p安装步骤安装proto...【详细内容】
2021-09-06    石老师小跟班  Tags:go-micro   点击:(197)  评论:(0)  加入收藏
GoLand 2021.2 EAP 5 现已发布。用户可以从工具箱应用程序中获得 EAP 构建,也可以从官方网站手动下载。并且从此 EAP 开始,只有拥有有效的 JetBrains 帐户才能加入该计划。手...【详细内容】
2021-06-29  IT实战联盟  今日头条  Tags:GoLand   点击:(185)  评论:(0)  加入收藏
作者:HDT3213今天给大家带来的开源项目是 Godis:一个用 Go 语言实现的 Redis 服务器。支持: 5 种数据结构(string、list、hash、set、sortedset) 自动过期(TTL) 发布订阅、地理位...【详细内容】
2021-06-18  HelloGitHub  今日头条  Tags:Go   点击:(125)  评论:(0)  加入收藏
统一规范篇合理规划目录本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开发空间,既使用统一的开发工具来保证代码最后的格式的统一,开发中对文件和代码长度的控制...【详细内容】
2021-05-18  1024课堂    Tags:Go语言   点击:(232)  评论:(0)  加入收藏
闭包概述 闭包不是Go语言独有的概念,在很多编程语言中都有闭包 闭包就是解决局部变量不能被外部访问的一种解决方案 是把函数当作返回值的一种应用 代码演示总体思想:在函数...【详细内容】
2021-05-14  HelloGo  今日头条  Tags:Go语言   点击:(223)  评论:(0)  加入收藏
一时想不开,想了解一下Go语言,于是安装了并体验了一下。下载1. 进入golang.google.cn 点击Download Go 2.选择对应的操作系统,点击后开始下载。 安装1. windows下执行傻瓜式安...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:Go语言   点击:(237)  评论:(0)  加入收藏
1.简介channel是Go语言的一大特性,基于channel有很多值得探讨的问题,如 channel为什么是并发安全的? 同步通道和异步通道有啥区别? 通道为何会阻塞协程? 使用通道导致阻塞的协程...【详细内容】
2021-05-10  程序员麻辣烫  今日头条  Tags:Go通道   点击:(274)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条