激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java框架解說之BIO NIO AIO不同IO模型演進之路

Java框架解說之BIO NIO AIO不同IO模型演進之路

2022-02-15 15:36慕楓技術筆記 Java教程

網上很多IO資料,對新手來說,越看越暈。根據自己的理解,總結對比了一下BIO、NIO、AIO,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

引言

Netty作為高性能的網絡通信框架,它是IO模型演變過程中的產物。Netty以Java NIO為基礎,是一種基于異步事件驅動的網絡通信應用框架,Netty用以快速開發高性能、高可靠的網絡服務器和客戶端程序,很多開源框架都選擇Netty作為其網絡通信模塊。本文主要通過分析IO模型的優化演進之路,比較不同IO模型的異同,讓大家對于Java IO模型有著更加深刻的理解,我想這也是Netty如何實現高性能網絡通信理解的重要基礎。話不多說,我們趕緊發車了。

PS:文末有是彩蛋哦!

Java框架解說之BIO NIO AIO不同IO模型演進之路

 

IO模型

1、什么是IO

在闡述BIO、NIO、AIO之前,我們先來看下到底什么是IO模型。我們都知道無論是程序還是平臺,它們的功能高度抽象之后其實可以描述為這樣一個過程,即為通過外部條件以及數據的輸入,經過程序或者平臺的處理產生了新的輸出,IO模型實際上就是描述了計算機世界中的輸入和輸出過程的模式。

對于計算機來說,其鍵盤以及鼠標等就是輸入設備,顯示器以及磁盤等就是輸出設備。舉個栗子,如果我們在計算機上寫一篇設計文檔并進行保存,實際就是通過鍵盤對計算機進行了數據輸入,完成設計文檔后將其保存輸出到了計算機的磁盤上。

Java框架解說之BIO NIO AIO不同IO模型演進之路


上圖中的IO描述,即為著名的計算機馮諾依曼體系,它大致描述了外部設備與計算機的IO交互過程。

2、應用程序IO交互

上文中我們介紹了計算機與外部設備交互的大致過程,那么我們的應用程序是如何進行IO交互的呢?我們平時編寫的代碼不會獨立的存在,它總是被部署在linux服務器或者各種容器中,應用程序在服務器或者容器中啟動后再對外提供服務。因此網絡請求數據首先需要和計算機進行交互,才會被交由到對應的程序去進行后續的業務處理。

在Linux的世界中,文件是用來描述Linux世界的,目錄文件、套接字等都是文件。那文件又是什么鬼呢?文件實際就是二進制流,二進制流就是人類世界與計算機世界進行交互的數據媒介。應用從流中讀取數據即為read操作,當把流中的數據進行寫入的時候就是write操作。但是linux系統又是如何區分不同類型的文件呢?實際是通過文件描述符(File Descriptor)來進行區分,文件描述符其實就是個整數,這個整數實際是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表。所以對這個整數的操作、就是對這個文件(流)的操作。

就拿網絡連接來說,我們創建一個網絡socket,通過系統調用(socket調用)會返回一個文件描述符(某個整數),那么后續對socket的操作就會轉化為對這個描述符的操作,主要涉及的操作包括accept調用、read調用以及 write調用。這里所說的各種調用就是程序通過Linux內核與計算機進行交互。那么問題又來了,這個計算機內核又是什么鬼。(PS:關于內核不是本文的重點,這里就簡單和大家說明下)

//socket函數
socket(PF_INET6,SOCK_STREAM,IPPROTO_IP)

但是實際上應用程序并不是直接從計算機中的網卡中獲取數據,也就是說大家編寫的程序并不是直接操作計算機的底層硬件。

Java框架解說之BIO NIO AIO不同IO模型演進之路

如上圖所示,在Linux的結構體系中,用戶的應用程序都是通過Linux Kernel內核來操作計算機硬件。那么為什么應用程序不能直接與底層硬件進行交互還需要在中間再加一層內核呢?主要有以下幾點考慮。

(1)計算機資源統一管理

Linux內核的作用就是進程調度管理,同時對cpu、內存等系統資源進行統一管理。因此內核管理的都是系統極其敏感的資源,采用內核制是為了實現系統的網絡通信,用戶管理,文件系統等安全穩定的進程管理,避免用戶應用程序破壞系統數據。

(2)底層硬件調用統一封裝

試想一下,如果沒有內核這層系統進程,那么每個用戶應用程序和硬件交互的時候都需要自己實現對應的硬件驅動。這樣的設計很難讓人接受,按照面向對象的設計思想,硬件的管理統一由Kernel內核負責,Kernel向下管理所有的硬件設備,向上提供給用戶進程統一的系統調用,方便應用程序可以像程序調用一樣進行系統硬件交互。

Java框架解說之BIO NIO AIO不同IO模型演進之路

3、5種IO模型

(1)阻塞型IO

當用戶應用進程發起系統調用之后,在內核數據沒有準備好的情況下,調用一直處于阻塞狀態,直到內核準備好數據后,將數據從內核態拷貝到用戶態,用戶應用進程獲取到數據后,本次調用才算完成。就好比你是外賣小哥,你到商家去取餐,商家的外賣還沒有準備好,所以你只能在取餐的地方一直等待著,直到商家將做好的外賣準備好,你才能拿了外賣去送餐。

Java框架解說之BIO NIO AIO不同IO模型演進之路

(2)非阻塞型IO

非阻塞IO式基于輪詢機制的IO模型,應用進程不斷輪詢檢查內核數據是否準備好,如果沒有則返回EWOULDBLOCK,進程繼續發起recvfrom調用,此時應用可以去處理其他業務。當內核數據準備好后,將內核數據拷貝至用戶空間。這個過程就好比外賣小哥在等待取餐的時候不斷問商家外賣做好了沒(這個外賣小哥比較著急,送餐時間比較臨近了),每隔30s問一次,直到外賣做好送到。

Java框架解說之BIO NIO AIO不同IO模型演進之路

(3)多路復用IO

Linux主要提供了select、poll以及epoll等多路復用I/O的實現方式,為什么會有三個實現呢?實際上他們的出現都是有時間順序的,后者的出現都是為了解決前者在使用中出現的問題。
在實際場景中,后端服務器接收大量的socket連接,IO多路復用是實際是使用了內核提供的實現函數,在實現函數中有一個參數是文件描述符集合,對這些文件描述符(FD)進行循環監聽,當某個文件描述符(FD)就緒時,就對這個文件描述符進行處理。

下面我們分別看下select、poll以及epoll這三個實現函數的實現原理:

select:
select是操作系統的提供的內核系統調用函數,通過它可以將一組FD傳給操作系統,操作系統對這組FD進行遍歷,當存在FD處于數據就緒狀態后,將其全部返回給調用方,這樣應用程序就可以對已經就緒的IO流進行處理了。

Java框架解說之BIO NIO AIO不同IO模型演進之路

select在使用過程中存在一些問題:
(1)select最多只能監聽1024個連接,支持的連接數較少;
(2)select并不會只返回就緒的FD,而是需要用戶進程自己一個一個進行遍歷找到就緒的FD;
(3)用戶進程在調用select時,都需要將FD集合從用戶態拷貝到內核態,當FD較多時資源開銷相對較大。

poll:
poll機制實際與select機制區別不大,只是poll機制去除掉了監聽連接數1024的限制。

epoll:
epoll解決了select以及poll機制的大部分問題,主要體現在以下幾個方面:
(1)FD發現的變化:內核不再通過輪詢遍歷的方式找到就緒的FD,而是通過異步IO事件喚醒的方式,當socket有事件發生時,通過回調函數將就緒的FD加入到就緒事件鏈表中,從而避免了輪詢掃描FD集合;
(2)FD返回的變化:內核將已經就緒的FD返回給用戶,用戶應用程序不需要自己再遍歷找到就緒的FD;
(3)FD拷貝的變化:epoll和內核共享同一塊內存,這塊內存中保存的就是那些已經可讀或者可寫的的文件描述符集合,這樣就減少了內核和程序的內存拷貝開銷。

Java框架解說之BIO NIO AIO不同IO模型演進之路

(該圖片來自于網絡)

(4)信號驅動IO

系統存在一個信號捕捉函數,該信號捕捉函數與socket存在關聯關系,在用戶進程發起sigaction調用之后,用戶進程可以去處理其他的業務流程。當內核將數據準備好之后,用戶進程會接收到一個SIGIO信號,然后用戶進程中斷當前的任務發起recvfrom調用從內核讀取數據到用戶空間再進行數據處理。

Java框架解說之BIO NIO AIO不同IO模型演進之路

(5)異步IO

所謂異步IO模型,就是用戶進程發起系統調用之后,不管內核對應的請求數據是否準備好,都不會阻塞當前進程,立即返回后進程可以繼續處理其他的業務。當內核準備好數據之后,系統會從內核復制數據到用戶空間,然后通過信號通知用戶進程進行數據讀取處理。

Java框架解說之BIO NIO AIO不同IO模型演進之路

 

Java中的IO模型

上文中我們闡述了Linux本身存在的幾種IO模型,那么對應到Java程序世界中,Java也有對應的IO模型,分別是BIO、NIO以及AIO三種IO模型。它們都提供了和IO有關的API,這些API實際也是依賴系統層面的IO完成數據處理的,因此Java的IO模型,實際就是對系統層面IO模型的封裝。接下來我們來一起看下Java的這幾種IO模型。

BIO

BIO即為Blocking IO,顧名思義就是阻塞型IO模型,當用戶進程向服務端發起請求后,一定等到服務端處理完成有數據返回給用戶,用戶進程才完成一次IO操作,否則就會阻塞住,像個癡心漢傻傻的一直等待數據返回,當數據完成返回后用戶線程才會解除block狀態,因此在整個數據讀取過程中會發生阻塞。

另外從下圖我們可以看出來,每一個客戶端連接,服務端都有對應的處理線程來處理對應的請求。還是以餐廳吃飯的例子,你到餐廳去吃飯,假如每來一個消費者,餐廳都用一個服務員來接待直到消費者吃飽喝足走出餐廳,那么這個餐廳得配置多少個服務員才合適?這么多服務員,餐廳的老板估計得賠的內褲都沒了。

因此在網絡連接不多的情況下,BIO還能發回作用。但是當連接數上來后,比如幾十萬甚至上百萬連接,BIO模型的IO交互就顯得心有余而力不足了。當連接數不斷攀高時,BIO模型的IO交互方式存在以下幾種弊端。
(1)頻繁創建和銷毀大量的線程會消耗系統資源給服務器造成巨大的壓力;
(2)另外大量的處理線程會占用過多的JVM內存,你的程序不要干其他事情了,都被大量連接線程給占滿了;
(3)實際上線程的上下文切換成本也是很高的。

基于BIO模型在處理大量連接時存在上述的問題,因此我們需要一種更加高效的線程模型來應對幾十萬甚至上百萬的客戶端連接。

Java框架解說之BIO NIO AIO不同IO模型演進之路

NIO

通過上文的分析,由于在BIO模型下,Java中在進行IO操作時候是沒辦法知道什么時候可以讀數據或者什么時候可以寫數據,BIO又是一個實在孩子因此沒有什么好的辦法只能在哪里傻等著。由于socket的讀寫操作不能進行中斷,因此當有新的連接到來時,只能不斷創建新的線程來處理,從而導致存在性能問題。

那么如何解決這個問題呢?我們都知道問題的根源就是BIO模型中我們不知道數據的讀取與寫入的時機,才導致的阻塞等待,那么如果我們能夠知道數據讀寫的時機,是不是就不用傻傻的等著響應,也不用再創建新的線程來處理連接了。

Java框架解說之BIO NIO AIO不同IO模型演進之路

為了提升IO交互效率,避免阻塞傻等的情況發生。Java 1.4中引入了NIO,對于NIO來說,有人稱之為Non-blocking IO,但是我更愿意稱之為New IO。因為它是一種基于IO多路復用的IO模型,而不是簡單的同步非阻塞的IO模型。所謂IO多路復用指的就是用同一個線程處理大量連接,多路指的就是大量連接,復用指的就是使用一個線程來進行處理。

Java框架解說之BIO NIO AIO不同IO模型演進之路

那我們先來看看同步非阻塞模型有什么問題,NIO 的讀寫以及接受方法在等待數據就緒階段都是非阻塞的。如上文中的描述,同步非阻塞模式下應用進程不斷向內核發起調用,詢問內核數據完成準備。相對于同步阻塞模型有了一定的優化,通過不斷輪詢數據是否準備好,避免了調用阻塞。但是由于應用不斷進行系統IO調用,在此過程中十分消耗CPU,因此還有進一步優化的空間。此時就該IO多路復用模型上場一展拳腳了,而Java的NIO正是借助于此實現了IO性能的提升。(這里以epoll機制來進行說明)

Java NIO基于通道和緩沖區的形式來處理流數據,借助于Linux操作系統的epoll機制,多路復用器selector就會不斷進行輪詢,當某個channel的事件(讀事件,寫事件,連接事件等等)準備就緒的時候,就是會找到這個channel對應的SelectionKey,去做相應的操作,進行數據的讀寫操作。

Java框架解說之BIO NIO AIO不同IO模型演進之路

AIO

所謂AIO(Asynchronous IO)就是NIO第二代,它是在Java 7中引入的,是一種異步IO模型。異步IO模型是基于事件和回調機制實現的,當應用發起調用請求之后會直接返回不會阻塞在那里,當后臺進行數據處理完成后,操作系統便會通知對應的線程來進行后續的數據處理。
從效率上來看,AIO 無疑是最高的,然而,美中不足的是目前作為廣大服務器使用的系統 linux 對 AIO 的支持還不完善,導致我們還不能愉快的使用 AIO 這項技術,Netty實際也是使用過AIO技術,但是實際并沒有帶來很大的性能提升,目前還是基于Java NIO實現的。

 

總結

本文主要從計算機IO交互出發,分別給大家介紹了什么是IO模型以及常見的五種IO模型,介紹了這幾種IO模型的優缺點,從系統優化演進的角度分析了Java BIO、NIO以及AIO演化之路。從設計者的角度分析Java BIO存在的不足。我們再來回顧下整個演進過程的脈絡。

Java框架解說之BIO NIO AIO不同IO模型演進之路

在后續的文章中,筆者將繼續帶大家深入研究的Netty作為高性能網絡通信框架的奇妙之處,敬請期待哦。

真正的大師永遠懷著一顆學徒的心

到此這篇關于Java框架解說之BIO NIO AIO不同IO模型演進之路的文章就介紹到這了,更多相關Java IO模型內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://blog.csdn.net/Diamond_Tao/article/details/119834737

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 黄色7777| 国产69精品福利视频 | 91精品国产刺激国语对白 | 亚洲国产高清一区 | www久久国产 | 神马久久精品综合 | 在线观看麻豆 | 九九视屏| 激情91 | 国产日产精品一区二区三区四区 | 成人性视频免费网站下载软件 | 国产精品视频专区 | 龙床上的呻吟高h | 吾色视频 | 伊人欧美视频 | 国产午夜精品一区二区三区免费 | 天天透天天狠天天爱综合97 | 法国极品成人h版 | 污视频在线看 | 一级视频在线播放 | 亚洲操比视频 | 成人在线视频国产 | www.狠狠插.com | 久久国产一二三 | 午夜免费一区 | 香蕉久久久 | 2021免费日韩视频网 | 成年人黄色片视频 | 精国品产一区二区三区有限公司 | 国产日韩一区二区三区在线观看 | 激情影院在线观看 | 日本在线观看中文字幕 | 久久久久久久亚洲精品 | 女人叉开腿让男人桶 | av在线直播观看 | chinesegv男男猛男无套 | 亚洲欧美日韩免费 | 999精品国产 | 一色桃子av大全在线播放 | 性生大片免费观看一片黄动漫 | 国内精品久久久久久久久久 |