EC2 Ubuntu 20实例执行go install时无响应问题如何调试修复
问题排查步骤
该问题大概率是编译阶段内存耗尽触发OOM(内存溢出)导致的:4GB内存要承载运行中的Go REST API业务,剩余可用内存不足以支撑Go编译的资源消耗,无swap分区缓冲的情况下会直接触发系统OOM,导致实例无响应。
第一步:确认OOM根因
- 重启实例后先不要执行
go install,开两个终端窗口,一个执行dmesg -w实时监控内核日志,另一个执行go install,如果内核日志出现Out of memory: Killed process相关记录,且被杀死的进程是go、compile类进程,即可确认是OOM导致的卡死。 - 也可以执行
watch -n 1 free -h实时监控内存占用,观察执行go install时可用内存是否快速跌到0。
第二步:定位高内存占用项
- 检查运行中的Go REST API内存占用:执行
ps aux | grep 你的API二进制文件名查看RSS(实际物理内存占用)值,如果业务本身已经占用2~3GB内存,留给编译的内存不足1GB,必然会触发OOM。 - 检查编译参数:是否开启了
-race竞争检测(该参数会让编译内存占用翻2~3倍)、是否开启了高阶编译优化、是否依赖大量带cgo的第三方库(cgo依赖编译阶段内存占用远高于纯Go依赖)。 - 检查系统swap配置:Ubuntu 20的EC2实例默认不开启swap分区,内存耗尽后没有缓冲空间,会直接触发OOM杀死进程甚至导致系统卡死。
解决方案
临时修复方案
- 编译前先停止运行中的Go REST API服务,释放占用的内存,编译完成后再重启服务,4GB内存足够支撑绝大多数Go项目的编译需求。
- 限制Go并行编译数降低内存峰值:执行
go install -p 1 ./...,-p参数指定并行编译的goroutine数量,默认等于CPU核心数,设为1可以大幅降低编译阶段的内存占用。 - 临时开启2GB swap分区缓冲,操作命令如下:
# 创建2GB大小的swap文件 sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile
编译完成后可以执行sudo swapoff /swapfile && sudo rm /swapfile关闭并删除swap文件。
永久修复方案
- 把EC2实例内存扩容到8GB及以上,彻底解决编译阶段内存不足的问题。
- 拆分编译和运行环境:在本地或者单独的CI/CD实例上编译好二进制文件,再同步到生产EC2实例部署,不在生产实例上直接编译,既避免占用生产资源,也降低生产环境的安全风险。
- 配置永久swap分区:如果暂时不想扩容实例,可以把临时swap配置改为永久生效,编辑
/etc/fstab文件,添加一行/swapfile none swap sw 0 0,保存后执行sudo mount -a即可生效。
内容的提问来源于stack exchange,提问作者Vikram
相关产品推荐
相关产品推荐

