Go文件上传服务中SSD上io.CopyN耗时过长问题排查求助
Go文件上传服务器io.CopyN性能异常排查求助
近期我用Go语言开发了一个简易文件上传服务器,核心代码如下:
func saveFile(r io.Reader, n int64) error { objectID := "1cb700e18a864328a561641736af934c" // 示例ID objectPath := "/mnt/1c/b7/1cb700e18a864328a561641736af934c" // 示例路径 var createDirStart, createFileStart, copyStart time.Time createDirStart = time.Now() if err := os.MkdirAll(filepath.Dir(objectPath), 0755); err != nil { return err } createFileStart = time.Now() f, err := os.Create(objectPath) if err != nil { return err } defer func() { syncStart := time.Now() if err == nil { err = f.Sync() } closeStart := time.Now() errc := f.Close() if err == nil { err = errc } if err != nil { os.Remove(objectPath) } fmt.Printf("objectId:%s, dirCost:%v, createFileCost:%v, copyCost:%v, syncCost:%v, totalCost:%v\n", objectID, createFileStart.Sub(createDirStart), copyStart.Sub(createFileStart), syncStart.Sub(copyStart), closeStart.Sub(syncStart), time.Since(createDirStart)) }() copyStart = time.Now() if _, err = io.CopyN(f, r, n); err != nil { return err } return nil }
文件上传时会生成UUID作为唯一标识,为避免单目录文件数量过多,采用UUID前两位为一级目录、接下来两位为二级目录的存储结构,二级目录内的文件名就是UUID本身。上传文件大小通常为10MB,最大不超过500MB。
通过步骤耗时日志发现,io.CopyN操作耗时最长,可达数十秒,但此时系统整体压力并不大。用blktrace追踪后发现Q2G项的MAX指标数值异常偏高,希望技术专家帮忙排查问题原因,万分感谢。

环境信息
- 操作系统版本:Linux version 5.4.0-153-generic (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)) #170-Ubuntu SMP Fri Jun 16 13:43:31 UTC 2023
- Go语言版本:go version go1.22.4 linux/amd64
- SSD硬件信息:
- 型号:INTEL SSDPF2KX038TZ
- 固件版本:JCV10300
- PCI厂商/子系统ID:0x8086
- IEEE OUI标识符:0x5cd2e4
内容的提问来源于stack exchange,提问作者simaocat
相关产品推荐
相关产品推荐

