1. 程式人生 > >too many open files錯誤

too many open files錯誤

一個 google pid .json 斷開連接 ret 服務 spi end

雖然一直在Linux下開發服務,但是說實話,Linux的東西我基本不懂。這次這個問題的解決,讓我稍微知道一些東西了。

大家都知道,最近我模仿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 inode
276: 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 name
tcp        1      0 104.131.132.190:60059 118.144.80.201:http CLOSE_WAIT 14397/haixiuzu

網上查了查,大神們都說如果Recv-QSend-Q有不為0的就說明不對,這是發送和接受隊列,說明一直在等待,一般需要兩個小時操作系統才會自動釋放這個資源,但是據我觀察,兩個小時也不會正常,要不也不會增加到1024個。

問題大體了定位好了,然後就是定位和修復。又去看了TCP連接的3次握手和斷開的4次握手,大概猜測是握手握了一半沒繼續握。又去看了看Golang的net/http包,斷開連接就是resp.Body.Close(),我沒寫這個,抱著試一試的態度改了一下,發現TCP連接恢復正常了。。。

我自己造的這個輪子還是可以的,讓我學到了TCP的一些皮毛,還是很有成就感的。

本文所涉及到的完整源碼請參考。

too many open files錯誤