999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

Java NIO 與IO 性能對比分析

2021-04-23 05:51:10趙思遠
軟件導刊 2021年4期
關鍵詞:模型

趙思遠

(北京工業大學軟件學院,北京 100124)

0 引言

隨著互聯網的蓬勃發展,網絡用戶激增[1],很多應用都服務于億級以上數量級的用戶。如此龐大的用戶基數導致在高峰時期可達到千萬以上的并發訪問量,如何處理高并發流量,以保證應用能正常使用,成為企業迫切需要解決的問題[2]。

Java 是Web 應用中廣泛采用的一種語言[3],JDK 中提供了NIO(也稱為New IO),NIO 為非阻塞IO[4],即IO 過程不會阻塞程序運行,使得CPU 不會因為等待IO 而白白浪費計算資源。使用NIO 編程,并采用適當的模型,可以充分發揮CPU 的性能,提高服務器的并發處理能力。

1 相關工作

羅振興等[5]在實踐的基礎上分析Java NIO 的特性,采用事件驅動、非阻塞的IO 多路復用、多線程[6]、安全Cookies、SSL、高速緩存等多種技術,設計并實現了構架在PKI上,基于角色訪問控制策略的安全訪問控制服務器,但其研究重點在于應用系統的整體設計與實現,對其中的Java服務器及其模型并沒有進行清晰、明確的描述;袁勁松等[7]對網絡應用中的阻塞通信與非阻塞通信工作機制及實現等問題進行研究與探討,提出系統實現阻塞與非阻塞通信的方法和步驟,分別給出基于阻塞與非阻塞IO 開發高性能網絡應用程序的具體實例,但該研究局限在代碼層面,且僅實現了基本的非阻塞服務器,對于高并發、長連接等實際應用中會出現的情況未進行討論;錢宇虹[8]對java.io包進行簡要介紹,指出導致I/O 性能低下的根本原因,提出改進Java IO 性能的策略,但該策略僅針對Java 的傳統IO方式,未考慮到在NIO 上的應用;楊帆[9]列舉Java 中多種不同的文件復制編程方式,對比其編程復雜程度及執行效率,為編程人員提供參考及編程建議,但其沒有對語言底層機制進行分析,且只對100M 文件進行了復制測試,沒有對服務器模型及其性能進行討論。

在高并發服務器領域,遲殿委[10]針對當前Web 應用請求高并發導致響應時間過長,影響用戶體驗的問題,提出Servlet 異步處理技術,對傳統單實例的Servlet 與具有異步特性的Servlet 進行對比分析,并通過JMeter 模擬多線程、高并發訪問兩種Servlet,從平均響應時間和吞吐量來看,具有異步特性的Servlet 在高并發壓力下表現出色;劉俊汐等[11]通過在Linux 服務端使用select 函數管理所有套接字,實現了單線程并發服務器;李明等[12]在socket 編程的基礎上,使用epoll 機制和線程池技術[13]設計并實現了一個高并發服務器;陳強等[14]提出使用Netty 開發物聯網應用服務器的方法;Jie[15]采用就緒通知機制處理網絡流,使用適當的數據結構處理IO 緩沖區,并使用優先級隊列[16]實現計時器管理模塊,通過適當地組合這些技術,顯著提高了SSL VPN 服務器程序的性能。

Java NIO 技術有效解決了CPU 等待IO 時產生的計算資源浪費問題,使得單一線程也能同時處理多個連接[17]。單線程NIO 模型實現簡單,但在同一時間只能處理一個IO 事件,無法響應其它用戶請求,這在IO 數據量較大或網絡條件較差等IO 耗時較多的環境下會嚴重影響應用性能。在使用NIO 的同時使用多線程技術,則可有效利用多核CPU 的能力提高應用性能。即使有一個CPU 核心在處理IO 任務,仍有其它核心可接受并處理用戶請求。但這種編程模型較為復雜,對開發人員要求較高,同時這種按照模型編寫的程序可讀性及可擴展性較差,在實際生產開發過程中應避免這種情況。

為了解決原生Java NIO 模型帶來的問題,業界提出MINA[18]、Netty[19]等框架對NIO 進行包裝,提供統一的模型,并進行了一些優化。使用這些成熟的框架可簡化NIO程序編寫,大大提高應用的可維護性[20]。

2 多Reactor 模型

2.1 傳統IO 模型

傳統IO 方式是面向流的,數據以字節為單位在輸入輸出流中傳輸,且流是單向的,如圖1 所示。

此外,IO 是阻塞式的,即Blocking IO,所以稱之為BIO。當程序發出讀寫請求后,程序會進入阻塞狀態,直到請求完成或中斷,如圖2 所示。

Fig.2 Blocking IO圖2 阻塞式IO

基于傳統IO 構建的網絡應用為了同時處理多個連接,需要為每個連接創建一個專用線程進行讀寫操作,接受新連接的線程稱為Acceptor,處理socket 的線程稱為Handler,如圖3 所示。

Fig.3 BIO server model圖3 BIO 服務器模型

這種模型在并發量不高時可以很好地處理多個連接,然而一旦并發量增長,連接數增多,將導致服務器線程也隨之增長。大量線程處于非活躍狀態,卻依然占用著系統資源,同時在大量線程中頻繁切換也會帶來很多額外的系統開銷。當連接數繼續增長,創建的線程數達到服務器極限,系統資源耗盡,將會導致整個系統卡死,大量連接得不到響應,直到服務器崩潰。因此,傳統IO 模型無法處理高并發流量。

2.2 NIO 單線程模型

NIO 是面向緩沖區的,數據必須通過通道讀取到緩沖區中才可以被程序使用,且通道是雙向的,如圖4 所示。

Fig.4 Buffer-oriented NIO圖4 面向緩沖區的NIO

通過緩沖區一次讀寫多個字節可以大大減少數據源訪問次數,從而提高執行速度。

同時,NIO 是非阻塞的,讀請求在數據未準備好時會立刻返回,不會阻塞程序運行,如圖5 所示。

Fig.5 Non-blocking IO圖5 非阻塞式IO

NIO 允許SocketChannel 和ServerSocketChannel 被配置為非阻塞式,采用非阻塞模型可以使程序同時監控多個通道,而不會因某個通道陷入阻塞,這種特性使其十分適合應用于網絡應用開發。

利用NIO 技術,單一線程可以同時監控多個通道,并循環處理其中已就緒的數據。實際上,系統已通過select、epoll 等方法為程序提供同時監控多個通道的能力,即IO多路復用。在Java NIO 中,將多個通道注冊到Selector 中,即可在某個通道就緒時通過select 方法將其選擇出來。單線程服務器模型如圖6 所示。

Fig.6 NIO single-threaded server model圖6 NIO 單線程服務器模型

NIO 單線程模型中所有操作都在主線程中進行。主線程中只有一個Selector,其監聽所有通道,并處理全部的accept 和read 事件。完成全部請求所需時間為:

其中,T 為完成全部請求所需時間,N 為并發連接數,taccept為接受一個連接所需時間,tread為每次讀取所需的平均時間,cread為每個連接讀取次數。

若接受連接的時間為0.1 ms,每個連接進行兩次讀取,每次讀取用時2 ms,則單線程模型處理10 000 個并發連接所需時間為41 s。

2.3 NIO 線程池模型

單線程模型使用一個線程串行地處理所有通道的連接與讀取事件,而無法利用CPU 的多核性能。為此,服務器一般采用多線程模型,并通過線程池重用線程,以避免頻繁地創建與銷毀線程。NIO 線程池服務器模型如圖7 所示。

Fig.7 NIO thread pool server model圖7 NIO 線程池服務器模型

在NIO 線程池服務器模型中,主線程包含一個Seletor,監聽所有通道,并處理accept 事件。當收到read 事件時,主線程將讀寫操作提交到線程池中執行。完成全部請求所需時間為:

其中,cthread為線程池線程數,一般設置為CPU 核心數,cost 為全部線程的切換總開銷。若CPU 核心數為16,線程切換總開銷為100ms,則線程池模型處理10 000 個并發連接所需時間為3.6s。

2.4 多Reactor 模型

以上單線程模型和線程池模型中均只使用一個Selector,即所有通道的accept 和read 事件都由一個Selector 進行處理。當大量通道頻繁讀寫,且每次讀寫的數據量很小時,會導致Selector 線程負載很高,而其它只進行讀寫操作的線程負載很低。在某些實際的網絡應用中,每個連接單次讀取的數據量很少,所需的讀取時間很短,但讀取次數多,數據交換頻繁,如網絡游戲或大型物聯網系統等。在這種場景下,線程池模型會頻繁地切換線程,此時切換線程的開銷便不能忽視。為解決這個問題,本文提出多Reactor 模型,如圖8 所示。

多Reactor 服務器模型中包含一個主線程和一個線程池。主線程中的Selector 只監聽ServerSocketChannel 的accept 事件,當連接到來時,會將SocketChannel 分發至線程池中的某個線程,所以主線程又稱為分發器。線程池中每個線程也擁有自己的Selector,負責監聽分配到該線程SocketChannel 的read 事件。

多Reactor 服務器模型中包含多個Selector,將通道平均分配至多個線程,緩解了主線程的分發壓力。通道被分配給工作線程后不會再移動,從而避免了頻繁切換線程的開銷,且每個工作線程內部都類似于簡單、高效的NIO 單線程模型。因此,多Reactor 服務器在保留多線程服務器優勢的同時,可以降低資源消耗。

Fig.8 Multi-Reactor server model圖8 多Reactor 服務器模型

3 性能測試及結果

3.1 文件讀取性能測試

文件讀取性能測試的目的在于探究面向流的IO 和面向緩沖區的NIO 在讀取數據方面的性能差異。

實驗使用多種方式對不同大小的文件進行讀取與復制,文件大小分別為1KB、1MB、10MB、100MB、500MB 和1GB。讀取方式包括無緩沖IO、單字節讀取的緩沖IO、儲存到數組的緩沖IO、NIO、直接緩沖區NIO,復制方式除以上方式外,還包括雙映射緩沖區、單映射緩沖區以及transferTo。記錄操作所需時間,每個測試執行8 次,記錄后5次平均值作為最終結果,單位為ms。讀取測試結果如表1所示。

Table 1 Read test results表1 讀取測試結果

復制測試結果如表2 所示。

Table 2 Copy test results表2 復制測試結果

測試結果顯示,使用緩沖區的文件讀取無論是IO 還是NIO,不會有太大的性能差異,使用直接緩沖區的NIO比普通NIO 速度稍快。文件復制測試結果也符合該結論,而且使用單映射緩沖區相較于雙映射緩沖區可減少一半的時間開銷。

直接緩沖區也稱為映射緩沖區,其不在用戶空間內,而是系統內存上的一塊區域。通過直接緩沖區,用戶可直接對該部分內存進行操作。通常程序讀取數據需要將數據讀取到內核,再復制到用戶空間,如圖9 所示。

Fig.9 Read data from file圖9 從文件中讀取數據

使用直接緩沖區,不需要將數據從內核空間復制到用戶空間,即零拷貝,這在進行大文件復制等操作時具有顯著優勢,如圖10 所示。

Fig.10 Copy files using direct buffer圖10 使用直接緩沖區復制文件

3.2 網絡通信性能測試

網絡通信性能測試的目的在于探究傳統IO 服務器模型與多種NIO 服務器模型之間在處理高并發網絡請求方面的性能差異。

實驗使用多種模型構建echo 服務器,包括BIO 多線程、BIO 線程池、NIO 單線程、NIO 線程池、NIO 多Reactor和Netty。使用Jmeter[21]對服務器進行分布式壓力測試,先向服務器發送“hello”,延遲1s 后再發送“bye”,最后關閉連接。設置Jmeter 線程數控制并發級別,測試持續時間為120s,使用htop 和visualVM 監控服務器運行狀態,記錄服務器資源使用情況和請求響應情況。測試機器全部為云主機,為防止客戶機產生性能瓶頸,將服務器配置為2 核8GB 內存,客戶機配置為4 核8GB 內存。

Table 3 BIO multi-thread model表3 BIO 多線程模型

由表3 結果可見,服務器的線程數隨并發數增長,但在4 000 并發時,線程數并沒有達到4 000,可見服務器能創建的線程數已達到上限。而且TPS 在4 000 并發時與2 000 并發時差距不大,說明服務器在2 000 并發時就已基本到達了性能瓶頸。

Table 4 NIO single-thread server表4 NIO 單線程服務器

由測試結果(見表4)可見,與BIO 服務器相比,NIO 服務器在資源占用、請求響應時間和TPS 上都具有優勢。

以4 000 并發為例,BIO 多線程服務器有3 002 個線程,CPU 占用率達到112%,完成“hello”請求306 322 個,平均響應時間為573 ms,TPS 為1 826,與2 000 并發時差別不大,已達到性能瓶頸;NIO 單線程服務器只有53 個線程,CPU 占用率為17.7%,完成“hello”請求477 970 個,平均響應時間為0.33 ms,TPS 為3 977??梢奛IO 單線程服務器用更少的資源完成了更多請求,而且響應時間極短。

通過橫向對比發現,每秒完成數隨著并發數而增長,在10 000 并發時,TPS 也接近10 000,且CPU 使用率只有50.80%,說明還沒有到達性能瓶頸,NIO 單線程服務器能支撐10 000 以上的并發。由此可見,NIO 服務器與BIO 服務器相比具有絕對優勢。

設定并發級別為10 000,多種NIO 服務器模型對比測試結果如表5 所示。

Fig.11 TPS of NIO and BIO under different concurrency levels圖11 不同并發級別下NIO 與BIO 的TPS

Table 5 Comparison test results of multiple NIO models under 10 000 concurrent表5 10 000 并發下多種NIO 模型對比測試結果

測試結果顯示,在10 000 并發時各模型的處理能力相近,TPS 均在9 800 附近,表明10 000 并發沒有達到NIO服務器的性能瓶頸,在CPU 占用率上出現的差異表明不同模型在相同壓力下會產生不同的系統負載。

由于該測試在內網環境下進行,且讀取的數據量較少,所以每次讀取耗時很短,單線程模型不會因讀取數據而出現顯著的阻塞情況,因此單線程模型的請求完成數并未明顯低于多線程模型。此外,由于單線程模型沒有線程切換的額外開銷,所以在完成相同數量請求的情況下,系統負載最低。

與單線程模型相比,線程池模型的CPU 占用率較高,TPS 反而更低,這是因為本測試沒有網絡速度慢和單次讀寫數據過大等IO 瓶頸,線程池的優勢未得到發揮,反而因頻繁切換線程而引入了額外的系統開銷。

本文提出的多Reactor 模型相較于原有的NIO 單線程模型和線程池模型有較大改進。首先,CPU 占用率與線程池模型相比由90.70% 降低到68.50%,僅略高于單線程模型;其次,平均響應時間和TPS 與單線程模型相比均有提升,同時避免了單線程模型會出現IO 操作阻塞其它連接的情況。這是由于多Reactor 模型的每個工作線程都相當于一個NIO 單線程服務器,其內部不會發生線程切換,所以效率很高,從整體來看是多個服務器并行,充分利用多核CPU 提高并發性能。

4 結語

在大文件讀取方面,面向緩沖區的NIO 與使用緩沖區的傳統流IO 相比性能差距不大;在大文件復制方面,通過使用直接緩沖區可以實現“零拷貝”,大大加快了復制速度;在網絡服務器方面,NIO 在高并發場景下與傳統IO 相比具有資源占用率低、響應速度快、吞吐量高等特點。本文設計的多Reactor 服務器模型既避免了單線程模型讀寫操作阻塞其它連接的問題,提高了并發性能,又避免了線程池模型頻繁切換線程帶來的額外開銷,降低了系統負載。利用設計良好的NIO 服務器模型,可適應各種應用場景。此外,還可利用成熟的框架降低開發難度,快速開發實現高性能服務器。

猜你喜歡
模型
一半模型
一種去中心化的域名服務本地化模型
適用于BDS-3 PPP的隨機模型
提煉模型 突破難點
函數模型及應用
p150Glued在帕金森病模型中的表達及分布
函數模型及應用
重要模型『一線三等角』
重尾非線性自回歸模型自加權M-估計的漸近分布
3D打印中的模型分割與打包
主站蜘蛛池模板: 玩两个丰满老熟女久久网| 91无码视频在线观看| 国产精品视频观看裸模| 欧美a在线看| 韩国福利一区| 热伊人99re久久精品最新地| 国产真实二区一区在线亚洲| 热伊人99re久久精品最新地| 99热这里只有精品在线观看| 91九色视频网| 5388国产亚洲欧美在线观看| 国产女人在线| 亚洲人成在线精品| 久久不卡国产精品无码| 欧美黄色网站在线看| a级毛片网| 久久永久精品免费视频| 伊大人香蕉久久网欧美| 18禁黄无遮挡网站| 国产福利拍拍拍| 欧美一级在线看| 欧美精品在线看| 成年A级毛片| 男人天堂伊人网| 国产成人精品综合| 欧美精品在线免费| 亚洲欧洲日产国产无码AV| 亚洲系列无码专区偷窥无码| 欧洲精品视频在线观看| 国产色图在线观看| 国产精品女主播| 国产在线视频导航| 又黄又爽视频好爽视频| 波多野结衣的av一区二区三区| 波多野结衣第一页| 美女被操黄色视频网站| 国产一区二区三区夜色| 久久久精品国产亚洲AV日韩| 欧美日韩国产综合视频在线观看 | 美女免费精品高清毛片在线视| a级毛片毛片免费观看久潮| 香蕉国产精品视频| 国产免费福利网站| 日韩免费毛片视频| 男女性色大片免费网站| 久久综合五月| 国产精品永久免费嫩草研究院| 亚洲成人黄色在线观看| 在线观看国产小视频| 欧美精品三级在线| 国产一级二级三级毛片| 一级毛片在线免费视频| 亚洲无码视频一区二区三区| 色播五月婷婷| 91久久偷偷做嫩草影院| 午夜精品福利影院| 日韩国产一区二区三区无码| 国产成人成人一区二区| 亚洲第一成人在线| 亚洲三级视频在线观看| 71pao成人国产永久免费视频| 国产免费久久精品99re不卡| 国产精品理论片| 九九这里只有精品视频| 亚欧美国产综合| 国产杨幂丝袜av在线播放| 亚洲一级毛片在线播放| 亚洲国产中文欧美在线人成大黄瓜 | 99视频在线免费| 亚洲无限乱码| 久久永久免费人妻精品| 伊人成色综合网| 综合人妻久久一区二区精品| 久久动漫精品| 亚洲无码高清视频在线观看| 亚洲国产日韩视频观看| 激情無極限的亚洲一区免费| 全部毛片免费看| 99999久久久久久亚洲| 国产欧美在线视频免费| 日本国产精品一区久久久| 国产微拍精品|