問題
使用Golang去批量下載所需要的數據時,由於http client發起請求並且讀取body之後,沒有正確設置Transport,並且沒有關閉Body,導致機器上面出現大量的CLOSE_WAIT狀態的連接。
相關概念
- CLOSE_WAIT:被動關閉方會進入的狀態,已經收到主動關閉方的FIN,但是還沒有發送FIN到主動關閉方。
- max_open_files:每個進程都有一個最大文件描述符的限制。
解決辦法
- 對於CLOSE_WAIT,最關鍵的是client端沒有close連接,沒有發送FIN到服務端。所以對於Golang自帶的http包,需要這樣寫:
trans := http.Transport {
DisableKeepAlives : true
}
client := http.Client {
transport : &trans
}
res, err := client.Get(url)
if err != nil {
fmt.Printf("%v.\n", err)
}
//use res.Body
io.Copy()
defer res.Body.Close()
必須手動關閉res.Body,這樣才能關閉連接,並且DisableKeepAlives這個也要設置成true纔行。
- 對於max open files,需要修改 /etc/security/limits.conf這個文件:
* sort nofile 655360
* hard nofile 655360
然後檢查 /etc/pam.d/login 這個文件裏面是否有下面這行
session required /lib/security/pam_limits.so
保存之後重新登陸shell的話, 就可以看到ulimit 已經生效了,如果不生效則重啓下機器即可。
臨時使用命令
可以使用
prlimit --pid $PID --nofile=$SOFT:$HARD
來設置進程的max open files