這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
大家都知道,最近我模仿binux大嬸的pyspider的害羞組線上上跑了一段時間了。後來加入了一些新的東西,比如代理池等。看瞅著代碼越來越靠譜了,結果突然有一天,發現抓取停止了,緊接著去看日誌:
2015/08/12 23:18:22 Post http://api.duoshuo.com/posts/import.json: dial tcp: lookup api.duoshuo.com: too many open files
作為一個菜鳥,我哪知道這是啥啊。後來用Google去搜,發現這是Linux通訊端佔滿了。在目錄/proc//fd/下,裡面有該進程所有開啟的檔案標識符相關檔案,通訊端也屬於檔案的一種。預設Linux下規定每個進程的最大socket並發數是1024,就是對開啟的檔案有所限制。我最早是通過進入該目錄,使用命令ll | wc -l查看當前進程的socket串連數。
這一看就是有東西申請了沒釋放,果斷重啟了服務好了。但是到底是哪裡沒釋放,我還是不得而知。只能是用Google繼續查,我懂得少,查了很多東西,把結論說一下。
在/proc/net/tcp檔案裡,儲存的是當前電腦的TCP協議串連,我這邊伺服器的結果如下:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode276: BE848368:80E5 2F80CFB7:0050 08 00000000:000019E4 00:00000000 00000000 1000 0 3748204 1 ffff8800182c1c00 116 4 30 10 -1
然後就是換算IP,這裡面本地和遠程IP都是16進位的,並且是倒著排的,換算完的本地IP是104.131.132.190:32997(BE848368:80E5),遠程IP是183.207.128.47:80(2F80CFB7:0050),說明我的電腦串連這個IP沒有正常斷開。查了一下這個IP,他是我用的西祠代理裡面提供的一個,說明代理那部分新寫的代碼有問題。
後來又得知,用netstat命令也成,而且比這個更牛逼。我一般還會用-p參數,這個能看到串連相關的進程,別的參數我也不懂了,大家想知道就Google把。netstat -p | grep haixiuzu這個就能看到我的害羞組程式的串連。當時顯示出的一個結果如下表。此外,還發現一次抓取結束後會有30個CLOSE_WAIT狀態的串連,其中118.144.80.201這個IP有20個,量也不小,他是多說API的IP,說明儲存到多說的時候HTTP也沒有釋放串連。
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program nametcp 1 0 104.131.132.190:60059 118.144.80.201:http CLOSE_WAIT 14397/haixiuzu
網上查了查,大神們都說如果Recv-Q和Send-Q有不為0的就說明不對,這是發送和接受隊列,說明一直在等待,一般需要兩個小時作業系統才會自動釋放這個資源,但是據我觀察,兩個小時也不會正常,要不也不會增加到1024個。
問題大體了定位好了,然後就是定位和修複。又去看了TCP串連的3次握手和斷開的4次握手,大概猜測是握手握了一半沒繼續握。又去看了看Golang的net/http包,中斷連線就是resp.Body.Close(),我沒寫這個,抱著試一試的態度改了一下,發現TCP串連恢複正常了。。。
我自己造的這個輪子還是可以的,讓我學到了TCP的一些皮毛,還是很有成就感的。
本文所涉及到的完整源碼請參考。
原文連結:too many open files錯誤,轉載請註明來源!