我正在尝试将〜40k文件解析为JSON并将它们保存到ArangoDB(这是我的4fun项目的一部分)。这可以简化为:
func walkRepository(task *RepositoryProcessingTask) {
filepath.Walk(task.Repository.Path, func(path string, info os.FileInfo, err error) error {
// ...
go parseFile(task, file)
// ...
return nil
})
}
func parseFile(task *RepositoryProcessingTask, file *RepositoryFile) {
<- task.routinesChannel
defer finishProcessingFile(task)
// Saves to ArangoDB (opens http connection)
err = db.Col("File").Save(file)
// ...
}
所以,基本上,我正在产生40k例程。由于每个例程打开文件和http套接字到ArangoDB(我使用arangGO.v2),我很容易达到1k打开文件限制。
我试图通过channel-semaphore限制并行运行的例程数量,但没有运气:
const (
maxRunningRoutines = 256
)
// on task creation
task.routinesChannel = make(chan int32, maxRunningRoutines)
// on task start
for i := int32(0) ; i < maxRunningRoutines ; i += 1 {
task.routinesChannel <- i
}
// when parsing completes
task.routinesChannel <- processedFiles
最后,我增加了开放文件限制,但它会导致程序崩溃:
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7fcddd12c5f7 m=2
goroutine 0 [idle]:
...
goroutine 81348 [chan receive]:
net/http.(*Transport).getConn.func2.1(0xcc732b2120, 0xc8200ec0c0, 0x959c08)
/usr/lib/golang/src/net/http/transport.go:698 +0x48
created by net/http.(*Transport).getConn.func2
/usr/lib/golang/src/net/http/transport.go:702 +0x70
我的猜测是,DB客户端产生的HTTP连接没有关闭ASAP,这会导致麻烦。但我怎么能解决它并证明这是真正的原因?