dsykx64220
dsykx64220
2019-03-31 05:03
浏览 35
已采纳

安排任务而无内存泄漏

I have created a scheduler which run every 10 seconds using golang newTicker. Each tick creates a new goroutine which performs some memory intensive task but finishes well before 10 seconds are completed.

I have deployed this in kubernetes. container has both scheduler and http server. HTTP server will take a single request and run the schedule once. This is for retrying missed tasked manually. Code is as follows:

func startScheduledTask() {
    fmt.Println("Task Started...", time.Now())
    ticker := time.NewTicker(10 * time.Second)
    defer ticker.Stop()
    for ; true; <-ticker.C {
        go customTask(time.Now())       
    }
}

I observed that this code is not releasing memory. Docker stats for container shows the memory is growing. Though it has memory limit on k8s, and k8s will restart in case of OOMKilled, one scheduled tasked is still missed and manual intervention is required. Is there a way to release this memory?

customTask Code is making HTTP Request for each tick.

Docker stats and container logs are as follows.

Docker stats and container log

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • dskm94301
    dskm94301 2019-03-31 12:05
    已采纳

    Leaking goroutines were culprits. used https://github.com/bcicen/grmon and found out that number of goroutines were increasing along with scheduler ticks. They were waiting at net/http package.

    response.body.close() and Transport.CloseIdleConnections() fixed the issue. NewTicker works fine. Thanks

    Fix should be applied after we make http call.

    if err == nil && statusCode == http.StatusOK {
                httpSuccess = true
                //fmt.Println("httpSuccess", httpSuccess)
    
                tr.CloseIdleConnections()
                return response, nil
            }
    
        if response.Body != nil {
            if err := response.Body.Close(); err != nil {
    
            }
        }
    
    
    点赞 评论

相关推荐