Apache 指定的網絡名不再可用 winnt_accept: Asynchronous AcceptEx failed

這幾天遇到了一個很多人都遇到過的問題,這個問題在google上有太多的人都遇到,但很少有指出最終的解決方案,大部分是解決了AcceptEx failed,但引起了內存的瘋狂增加(“memory leak”)。這幾天遇到這個問題後也費了不少功夫,但沒有從網上找到最根本的解決辦法,幸運的是,最終探索出了一個解決方案,在這裏寫出來,希望能幫助後來遇到問題的難友們儘早解決問題。

遇到的問題比較曲折,大體經過是:

某天,不能訪問apache的頁面,檢查得知,apache在瘋狂寫日誌,而且大部分是一句話:“winnt_accept: Asynchronous AcceptEx failed”,最多的時候寫到了200M以上。經各方探索,最終在apache的手冊上找到了一個解決方法:

在http.conf配置中設置Win32DisableAcceptEx參數。這樣做的原因是,apache在某些Windows版本上可能兼容性不足,在調用AcceptEx接收請求時可能有問題,使用上面的參數禁用後,apache會使用另一套方案替代(BSD),這種方案效率稍微低些。詳見:

http://httpd.apache.org/docs/2.0/mod/mpm_winnt.html#win32disableacceptex

當時修改完該設置後,重啓apache,測試了一段時間,感覺原來的問題確實消除了,不過當時感覺內存佔用量非常明顯,但測試一段時間沒有問題就放過去了,直到今天下午:

今天下午發現又不能訪問頁面了,然後檢查apache發現它已經crash了。然後打開日誌發現最後一句:“Out of memory!”--內存不足了。

然後對內存進行測試,發現一直按住F5鍵不停,apache的內存就不停上漲,似乎有一直吃光內存的意思,停止刷新後只能下降到500M左右了(剛啓動時是20M)。如果不使用Win32DisableAcceptEx參數則明顯沒有這個問題,停止刷新後能回落到20M。看來是這個參數的原因。

於是從google上尋找答案,但可惜的是沒有太多有價值的東西。只能看到apache的官方網站已經把這個問題列爲了一個bug,甚至有些人又退回到不使用那個參數(忍受AcceptEx failed的風險?)。最後看到了一個說法,將ThreadsPerChild 設爲170以下就可以,可爲什麼是170以下呢?作者沒有很多描述。於是自己探索如下,使用一個簡單的頁面,不停的按住F5刷新:

如果將Threadsperchild 設爲50,無論怎麼刷新內存最多到150M左右,但不會再長了。停止刷新後,會降到55M左右;如果將ThreadsPerChild 設爲100, 內存峯值:282M,能降到92M左右;如果將ThreadsPerChild設爲550,內存峯值2G,停止後到500M左右……。

按照上述規律,基本上找到了問題的原因,因爲我的配置中原來使用的是ThreadsPerChild 550,這樣也就是內存很可能會長到2G以上(複雜頁面比簡單頁面耗用量大),而機器的內存設置不能支持這麼大,因此應該就是這個問題了。

所以最終的解決方法就是保留Win32DisableAcceptEx的同時修改了ThreadsPerChild 150。解決完成後我推測內存瘋狂增長的原因:

首先,ThreadsPerChild的意思是系統啓動時默認啓動的等待線程數,用來等待處理客戶的請求。在使用AcceptEx時內存增長不明顯並且可以降回20M左右,可能是因爲用戶來了請求線程分配了一些資源,此時內存增長,但用戶訪問完成後,這些資源都釋放了(這些資源很可能都和用戶相關,沒法留着下個用戶使用,所以都釋放了)。但禁用了AcceptEx後,由於apache每個線程需要處理網絡事件,因此每個線程的資源需要就多了,並且處理完一個用戶的請求後,有些資源不想釋放,是可以對下個用戶重用的,這樣就留在了裏面。由於我的線程數設了550(估計網上很多人遇到這個類似於“memory leak”問題的可能也都設的比較大或者機器虛擬內存較小),這樣當線程較多時就會出現達到最大內存的情況,而且這種現象給人的感覺就是有內存泄漏,因爲初始時是20M,來一個請求後線程分配一些資源(暫時不釋放的),這樣可能就變成了21M,如果同時有10個人訪問,可能等他們訪問完後就變成了50M,感覺是有內存泄漏。

這樣也就解釋了爲什麼有人說設到170以下就不再出現內存不足了,可能因爲他的機器這個配置比較合適。不過知道了上述的規律和一些推測,這個結論應該是根據自己機器的情況合理調配。

我很少接觸apache等linux上的東西,所知較少,只是遇到了問題纔開始瞭解的上述信息,可能有很多的理解錯誤。如果能給別人一些幫助我會比較欣慰,如果誤導甚至幫了倒忙,也希望能夠理解!

 

如果在Win下使用Apache,而你又必須要開防火牆之類的軟件,那麼如果你的Apache運行有問題,比如文件下載不完全或者損壞、未知錯誤信息、防火牆衝突等等,請參考如下:

打開你的 httpd.conf 配置文件,看是否如下修改可以解決問題:

    EnableSendfile Off
    EnableMMAP Off
    Win32DisableAcceptEx

轉帖 (2):

現象:】


訪問apache靜態的http內容,有時候比較慢,有時候“找不到網頁”404錯誤;另外在error.log裏也報錯:

[Mon May 26 10:11:47 2008] [warn] (OS 64)指定的網絡名不再可用。 : winnt_accept: Asynchronous AcceptEx failed.

原因:】

winnt(MPM) - Apache 2.2 參考手冊有下列描述

Apache MPM winnt

說明 專門爲Windows NT優化過的MPM
狀態 MPM
模塊名 mpm_winnt_module
源文件 mpm_winnt.c

概述

該多路處理模塊(MPM)是Windows NT上的默認值。它使用一個單獨的父進程產生一個單獨的子進程,在這個子進程中輪流產生多個線程來處理請求。

Win32DisableAcceptEx 指令

說明 使用accept()代替AcceptEx()接受網絡鏈接
語法 Win32DisableAcceptEx
默認值 AcceptEx()是默認的,使用這個指令將禁用它。
作用域 server config
狀態 MPM
模塊 mpm_winnt
兼容性 僅在 Apache 2.0.49 及以後的版本中可用

AcceptEx()是一個微軟的WinSock2 API ,通過使用BSD風格的accept() API提供了性能改善。一些流行的Windows產品,比如防病毒軟件或虛擬專用網絡軟件,會干擾AcceptEx()的正確操作。如果你遇到類似於如下的錯誤:

[error] (730038)An operation was attempted on something that is not a socket.: winnt_accept: AcceptEx failed. Attempting to recover.

你就需要使用這個指令來禁止使用AcceptEx()

 

【解決辦法:】

在httpd.conf文件中添加 Win32DisableAcceptEx 標記,如下:

<IfModule mpm_winnt.c>
ThreadsPerChild 150
MaxRequestsPerChild 10000
Win32DisableAcceptEx
</IfModule>

這樣可以允許併發連接更大一些。同時性能上也不會有明顯的降低。

如果Apache的error.log還是出現大量的:Sat Dec 24 17:21:28 2006] [warn] (OS 64)指定的網絡名不再可用。 : winnt_accept: Asynchronous AcceptEx failed。可以參考下列配置:

1、網上鄰居->本地連接->屬性->internet協議(TCP/IP)->屬性->高級->wins標籤->去掉啓用LMhosts查詢前的勾.
2、控制面版->windows防火牆->高級標籤->本地連接設置->服務的標籤裏勾選安全Web服務器(HTTPS)。
3、然後退出Apache,再打開啓動就可以了 ,一開始我沒有退出,直接在那重啓,就是不可以,一定要先停止,在開啓即可

 

轉帖 (3):

[warn] (OS 64)指定的網絡名不再可用。 : winnt_accept: Asynchronous AcceptEx failed.

   以前也看到,但忽略了。這回不能再放過她了。

   看了幾篇(winnt(MPM) - Apache 2.2 中文版參考手冊),說是因爲一些流行的視窗系統產品,比如防病毒軟件或虛擬專用網絡軟件,會干擾AcceptEx()的正確操作。於是在apache設置文件中添加如下語句:

<IfModule mpm_winnt.c>
ThreadsPerChild 1000
MaxRequestsPerChild 10000
Win32DisableAcceptEx
</IfModule>

   停止Apache,再啓動。確實新設置起作用了:

[notice] Disabled use of AcceptEx() WinSock2 API
[notice] mod_python: Creating 8 session mutexes based on 0 max processes and 1000 max threads.
[notice] Child 2380: Child process is running
[notice] Child 2380: Acquired the start mutex.
[notice] Child 2380: Starting 1000 worker threads.

   okay,似乎錯誤不再來了。

 

問題一、
Apache日誌中“指定的網絡名不再可用”問題的解決
現象:
[Sat Mar 03 13:29:49 2007] [warn] (OS 64)指定的網絡名不再可用。   : winnt_accept: Asynchronous AcceptEx failed.
出現這個故障時硬盤燈狂閃,內存佔用極大,訪問極慢。
分析:
AcceptEx() 是 Microsoft WinSock v2 API 一組提升網路效率 API 中的指令。而且在 Windows 上似乎蠻有可能出問題的。
   注:可能為了效能還是預設為開啟 AcceptEx()
解決:
    如果無預警的發生問題,我猜可能是 Windows Update 或是防火牆、防毒軟體更新了某些網路原件,造成 Microsoft WinSock v2 API 動作不正常,這時可以把這個功能先給關掉。
   依照官方說明 , Win32DisableAcceptEx 這個功能,只有 2.0.49 版以後的纔可以使用,所以我猜測 AcceptEx() 這個指令大概也是 2.0.49 纔會開始支援(目前最新的就是 2.0.49)。
   關掉 AcceptEx() 的方式只要在 httpd.conf 找到   區段,加入 Win32DisableAcceptEx 就可以了。
Win32DisableAcceptEx #加入這一行
ThreadsPerChild 250
MaxRequestsPerChild 0

疑問:如果把AcceptEx()這個關掉了,是否會影響訪問的速度;如果影響速度,又怎樣不讓速度慢下來。
問題二、
apache錯誤日誌裏面出現"connection reset by peer"
分析:
這個問題一般是客戶端在連接還沒有完全建立的時候就取消連接,比如用戶按了瀏覽器上面的“停止”按鈕,一般來說沒有什麼問題。但是如果頻繁出現,就表示很多客戶端連接到Apache服務器的響應時間太長了,可能是網絡的問題或者服務器性能問題。
問題三、
apache錯誤日誌裏面提示default.ida或者cmd.exe不存在
分析:
這個說明Internet上面的某些機器中了蠕蟲病毒比如Nimda或者Code Red。 你可以略過這些錯誤,因爲這些病毒對Apache無效。
問題四、
apache錯誤日誌裏面出現"fcntl: F_SETLKW: No record locks available
現象:
服務器掛起,或者不能啓動,錯誤日誌裏面出現"fcntl: F_SETLKW: No record locks available"或者類似的信息。
分析:
這個是文件鎖定問題,表示Apache服務器在嘗試使用一個NFS文件系統上面的同步文件。由於使用並行操作模式,Apache服務器在訪問某些特定資源的時候需要一些同步機制。其中一種同步機制就是文件鎖定,這個需要被鎖定文件那端的文件系統要支持鎖定機制,所以使用NFS文件系統上面的文件會出現這種問題。
解決:
爲了解決NFS文件系統的侷限性,可以在配置文件裏面加入一行:
  LockFile /var/run/apache-lock
  這個文件對其他人必須是不能寫入的。
  注意:Redhat Linux7.x版本以後已經提供了NFS鎖定機制,應該不會出現此問題。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章