在過去的二三年,曾嘗試過幾回使用nio改寫之前的服務器端程序,想體驗一下nio + socketchannel帶來的快感。html
可每次的改寫結果都很失敗,體會到的全是有失望的感受,每次的改寫通過大量測試後發現併發性能、反應處理速度並無明顯提高,有的時候測試結果還不如 io + socket.java
最近幾天有空,靜下心來再次嘗試用NIO來改寫一個簡單的HTTP服務器,先在網上查看了幾十篇相關資料,而後根據自已的理解寫了一個出來,通過測試感受處理性能與傳統的io+socket+多線程相比基本上差很少,只有在socket併發和內存佔用方面比傳統的io要表現好一些。ios
昨天下午,很苦惱,好累。那時我在想,是否是又到了放棄了時候了。服務器
今天一覺醒來,精神恢復的不錯,又在網上隨意的查查nio相關資料,看到一篇文章的開頭說了這麼一段:
http://zhidao.baidu.com/question/184097099.html多線程
其實不要太迷信nio。這個東西若是你使用不當,效率還不如io高。
並且,使用了nio會形成和之前的代碼的不兼容。固然,你是高手,那就例外了。 併發
我深有體會,由於我不是java高手,我發現這幾年來自已寫出來的nio代碼,與傳說的效率相比差的太遠了。socket
特別是在寫 nio + 多線程處理的時候,感受代碼已處於失控狀態。高併發
後來發現了一篇標題:「基於事件的 NIO 多線程服務器」的文章,網址:http://www.ibm.com/developerworks/cn/java/l-niosvr/性能
看完之後,發現這篇文章雖然寫的時間較早,可是我這幾天看到的給我啓發最大的一篇資料。測試
我下載文章下面附帶的源代碼,看了幾遍,個人思路突然開朗起來。
從新改寫以前幾天寫的代碼,通過這一天的努力,寫出的代碼通過測試,無論是併發性、處理能力方面都有明顯的提高。
與之前用傳統的io + socket + 多線程寫的HTTP服務器對比,用ab測試併發性,nio 處理 2000 併發一點兒問題都沒有,反應的速度也至關的快,而傳統的io處理方式在處理1000個併發的過程當中,客戶端ab就崩潰了,NIO與傳統的IO測試對比結果:
傳統的IO + socket須要幾百、上千個線程來處理客戶端的請求,而 NIO 只須要幾個線程就搞定;
NIO內存佔用相比傳統的IO下降 80%;
NIO的cpu佔用相比傳統的IO下降 20%;
NIO處理能力相比傳統的IO卻提高了 30%;
我今天使用NIO寫的代碼結構至關簡單:
1個 Selector 主線程 + 1個 Reader 線程 + 1個 Writer 線程
就能處理幾百、上千的併發請求,處理的速度至關的快,內存佔用至關的低。
看到測試的結果,我也深入體會到了nio的一個優勢:該read的時候再read,該write時候再write。
不像傳統的io,用多個線程處理多個用戶的多個鏈接請求,無論用戶提交的數據是否到達,先 read(),沒有數據可讀的時候,就在那阻塞着。
不過話又說回來,傳統的io,基於流(Stream),也有它的優勢,好比處理流程簡單,代碼寫起來相比nio要簡單許多。
在這裏我還想說一點體會,就是我在網上這幾天找相關資料,發現80%的文章介紹的都不夠深刻,提供的代碼基本上都是單線程的,很是適合用來處理短鏈接,這也一直給我一種錯覺,難道NIO不適合處理長鏈接?
今天找到的這篇:http://www.ibm.com/developerworks/cn/java/l-niosvr/
查看了文章裏提供的源代碼,使用了三個線程(Selection線程,Reader線程,Write線程),使nio處理長鏈接成爲可能,只需簡單修改一下,就OK了