在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

探究Redis網(wǎng)絡(luò)模型究竟有多強大(下)

jf_78858299 ? 來源:蟬沐風(fēng)的碼場 ? 作者:蟬沐風(fēng) ? 2023-03-03 09:50 ? 次閱讀

4. 非阻塞I/O(NonBlocking I/O)

上文花了太多的筆墨描述BIO,接下來的非阻塞IO我們只抓主要矛盾,其余參考BIO即可。

如果你看過其他介紹非阻塞IO的文章,下面這個圖片你多少會有點眼熟。

圖片

NIO模型

非阻塞IO指的是進(jìn)程發(fā)起系統(tǒng)調(diào)用之后,內(nèi)核不會將進(jìn)程投入睡眠,而是會立即返回一個結(jié)果,這個結(jié)果可能恰好是我們需要的數(shù)據(jù),又或者是某些錯誤。

你可能會想,這種非阻塞帶來的輪詢有什么用呢?大多數(shù)都是空輪詢,白白浪費CPU而已,還不如讓進(jìn)程休眠來的合適。

4.1 Java的非阻塞實現(xiàn)

這個問題暫且擱置一下,我們先看Java在語法層面是如何提供非阻塞功能的,細(xì)節(jié)慢慢聊。

public class NoBlockingServer {

    public static List<SocketChannel> channelList = new ArrayList<>();

    public static void main(String[] args) throws InterruptedException {

        try {
            // 相當(dāng)于serverSocket
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 將監(jiān)聽socket設(shè)置為非阻塞
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.socket().bind(new InetSocketAddress(8099));
            while (true) {
                // 這里將不再阻塞
                SocketChannel socketChannel = serverSocketChannel.accept();

                if (socketChannel != null) {
                    // 將連接socket設(shè)置為非阻塞
                    socketChannel.configureBlocking(false);
                    channelList.add(socketChannel);
                } else {
                    System.out.println("沒有客戶端連接!!!");
                }

                for (SocketChannel client : channelList) {
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    // read也不阻塞
                    int num = client.read(byteBuffer);
                    if (num > 0) {
                        System.out.println("收到客戶端【" + client.socket().getPort() + "】數(shù)據(jù):" + new String(byteBuffer.array()));
                    } else {
                        System.out.println("等待客戶端【" + client.socket().getPort() + "】寫數(shù)據(jù)");
                    }
                }

                // 加個睡眠是為了避免strace產(chǎn)生大量日志,否則不好追蹤
                Thread.sleep(1000);

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Java提供了新的APIServerSocketChannel以及SocketChannel,相當(dāng)于BIO中的ServerSocketSocket。此外,通過下面兩行的配置,將監(jiān)聽socket和連接socket設(shè)置為非阻塞。

// 將監(jiān)聽socket設(shè)置為非阻塞
serverSocketChannel.configureBlocking(false);

// 將連接socket設(shè)置為非阻塞
socketChannel.configureBlocking(false);

我們上文強調(diào)過, Java自身并沒有將socket設(shè)置為非阻塞的本事,一定是在某個時間點上,操作系統(tǒng)內(nèi)核提供了這個功能,才使得Java設(shè)計出了新的API來提供非阻塞功能

之所以需要上面兩行代碼的顯式設(shè)置,也恰好說明了內(nèi)核是默認(rèn)將socket設(shè)置為阻塞狀態(tài)的,需要非阻塞,就得額外調(diào)用其他系統(tǒng)調(diào)用。我們通過man命令查看一下socket()這個方法(截圖的中間省略了一部分內(nèi)容):

man 2 socket

f336ca741589b768db4fecb030b6b432.png

image-20221225144028751

我們可以看到socket()函數(shù)提供了SOCK_NONBLOCK這個類型,可以通過fcntl()這個方法將socket從默認(rèn)的阻塞修改為非阻塞,不管是對監(jiān)聽socket還是連接socket都是一樣的。

4.2 Java的非阻塞解釋

現(xiàn)在解釋上面提到的問題:這種非阻塞帶來的輪詢有什么用?觀察一下上面的代碼就可以發(fā)現(xiàn),我們?nèi)讨皇褂昧?個main線程就解決了所有客戶端的連接以及所有客戶端的讀寫操作。

serverSocketChannel.accept();會立即返回調(diào)用結(jié)果。

返回的結(jié)果如果是一個SocketChannel對象(系統(tǒng)調(diào)用底層就是個socket描述符),說明有客戶端連接,這個SocketChannel就表示了這個連接;然后利用socketChannel.configureBlocking(false);將這個連接socket設(shè)置為非阻塞。這個設(shè)置非常重要,設(shè)置之后對連接socket所有的讀寫操作都變成了非阻塞,因此接下來的client.read(byteBuffer);并不會阻塞while循環(huán),導(dǎo)致新的客戶端無法連接。再之后將該連接socket加入到channelList隊列中。

如果返回的結(jié)果為空(底層系統(tǒng)調(diào)用返回了錯誤),就說明現(xiàn)在還沒有新的客戶端要連接監(jiān)聽socket,因此程序繼續(xù)向下執(zhí)行,遍歷channelList隊列中的所有連接socket,對連接socket進(jìn)行讀操作。而讀操作也是非阻塞的,會理解返回一個整數(shù),表示讀到的字節(jié)數(shù),如果>0,則繼續(xù)進(jìn)行下一步的邏輯處理;否則繼續(xù)遍歷下一個連接socket。

下面給出一張accept()返回一個連接socket情況下的動圖,希望對大家理解整個流程有幫助。

4.3 掀開非阻塞IO的底褲

我將上面的程序在CentOS下再次用strace程序追蹤一下,具體步驟不再贅述,下面是out日志文件的內(nèi)容(我忽略了絕大多數(shù)沒用的)。

圖片

非阻塞IO的系統(tǒng)調(diào)用分析

4.4 非阻塞IO總結(jié)

圖片

NIO模型

再放一遍這個圖,有一個細(xì)節(jié)需要大家注意,系統(tǒng)調(diào)用向內(nèi)核要數(shù)據(jù)時,內(nèi)核的動作分成兩步:

  1. 等待數(shù)據(jù)(從網(wǎng)卡緩沖區(qū)拷貝到內(nèi)核緩沖區(qū))
  2. 拷貝數(shù)據(jù)(數(shù)據(jù)從內(nèi)核緩沖區(qū)拷貝到用戶空間)

只有在第1步時,系統(tǒng)調(diào)用是非阻塞的,第2步進(jìn)程依然需要等待這個拷貝過程,然后才能返回,這一步是阻塞的。

非阻塞IO模型僅用一個線程就能處理所有操作,對比BIO的一個客戶端需要一個線程而言進(jìn)步還是巨大的。但是他的致命問題在于會不停地進(jìn)行系統(tǒng)調(diào)用,不停的進(jìn)行accept(),不停地對連接socket進(jìn)行read()操作,即使大部分時間都是白忙活。要知道,系統(tǒng)調(diào)用涉及到用戶空間和內(nèi)核空間的多次轉(zhuǎn)換,會嚴(yán)重影響整體性能。

所以,一個自然而言的想法就是,能不能別讓進(jìn)程瞎輪詢。

比如有人告訴進(jìn)程監(jiān)聽socket是不是被連接了,有的話進(jìn)程再執(zhí)行accept();比如有人告訴進(jìn)程哪些連接socket有數(shù)據(jù)從客戶端發(fā)送過來了,然后進(jìn)程只對有數(shù)據(jù)的連接socket進(jìn)行read()

這個方案就是 I/O多路復(fù)用

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • IO
    IO
    +關(guān)注

    關(guān)注

    0

    文章

    483

    瀏覽量

    39996
  • 非阻塞
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    2240
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    381

    瀏覽量

    11229
收藏 人收藏

    評論

    相關(guān)推薦

    小米5的那顆核心,究竟有多強

    小米5的那顆核心,究竟有多強自從小米在2011年崛起后,高通的驍龍系列處理器就逐漸成為了市面上旗艦手機的主流處理器,從蝎子核心到環(huán)蛇核心,再到現(xiàn)在的驍龍810,高通一直在進(jìn)步。那么,這款驍龍810
    發(fā)表于 06-01 19:35

    Redis Stream應(yīng)用案例

    今天介紹的主角——Redis Stream,本身就是起源于IRC中一個用戶的idea。IRC的模型如下,在某個IRC頻道中的用戶,既可以向所有的其他用戶自由的發(fā)送消息,也可以接收其他所有用戶發(fā)送
    發(fā)表于 06-26 17:15

    液晶PC與液晶電視究竟有什么區(qū)別?

    為什么要選擇液晶?液晶PC與液晶電視究竟有什么區(qū)別?如何選擇液晶PC與液晶電視?
    發(fā)表于 06-07 06:13

    請問一RFID與NFC究竟有什么關(guān)系?

    RFID與NFC究竟有什么關(guān)系?
    發(fā)表于 06-15 07:06

    請問一芯片制造究竟有多難?

    請問一芯片制造究竟有多難?
    發(fā)表于 06-18 06:53

    PCI-E4.0究竟有什么優(yōu)勢?

    PCI-E4.0究竟有什么優(yōu)勢?PCI-E究竟指的是什么呢?
    發(fā)表于 06-18 06:54

    內(nèi)存時序究竟有多重要呢?究竟該如何去選擇內(nèi)存條呢?

    內(nèi)存時序究竟有多重要呢?究竟該如何去選擇內(nèi)存條呢?DDR內(nèi)存時序是高一些好還是低一些好?
    發(fā)表于 06-18 08:20

    定時器中斷類型探究 精選資料分享

     一直在用的stm32定時器的中斷都是TIM_IT_Update更新中斷,也沒問為什么,直到碰到有人使用TIM_IT_CC1中斷,才想到這定時器的中斷類型究竟有什么區(qū)別,都怪當(dāng)時學(xué)習(xí)stm32的時候
    發(fā)表于 08-13 06:28

    OpenPLC開源工業(yè)控制器究竟有何用處

    OpenPLC開源工業(yè)控制器有哪些優(yōu)點?OpenPLC開源工業(yè)控制器有哪些功能?OpenPLC開源工業(yè)控制器究竟有何用處?
    發(fā)表于 09-02 07:42

    華為榮耀Magic今日發(fā)布:“未來”手機究竟有多強

    華為榮耀即將在12月16日發(fā)布最新的“未來”手機magic,關(guān)于這款手機的爆料在今日已經(jīng)鋪天蓋地,今天,小編將為大家整理一,給大家一個榮耀Magic的基本判斷,看看這款旗艦究竟有多強力!
    發(fā)表于 12-16 09:34 ?3348次閱讀

    ibm的2nm芯片究竟有多強 2nm芯片對續(xù)航的影響

    全球首顆2nm芯片的問世對半導(dǎo)體行業(yè)影響重大,IBM通過與AMD、三星及GlobalFoundries等多家公司的合作,最終抵達(dá)了2nm芯片制程的節(jié)點,推出了2nm的測試芯片。那么這顆芯片究竟有多強呢?它對續(xù)航的影響又有多大呢?
    的頭像 發(fā)表于 06-23 09:35 ?2313次閱讀

    Molex莫仕連接器的功能究竟有多強大?看他們的行業(yè)應(yīng)用你就知道了!

    KOYUELEC光與電子:Molex莫仕連接器的功能究竟有多強大?看他們的行業(yè)應(yīng)用你就知道了!
    的頭像 發(fā)表于 12-31 12:30 ?1.2w次閱讀

    探究Redis網(wǎng)絡(luò)模型究竟有多強大(上)

    本文將從BIO開始介紹,經(jīng)過NIO、多路復(fù)用,最終說回Redis的Reactor模型,力求詳盡。本文與其他文章的不同點主要在于:
    的頭像 發(fā)表于 03-03 09:46 ?575次閱讀
    <b class='flag-5'>探究</b><b class='flag-5'>Redis</b><b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>模型</b><b class='flag-5'>究竟有多強大</b>(上)

    探究Redis網(wǎng)絡(luò)模型究竟有多強大(中)

    創(chuàng)建socket這一步和客戶端沒啥區(qū)別,不同的是這個socket我們稱之為 **等待連接socket(或監(jiān)聽socket)** 。 #### 3.2.2 綁定端口號 `bind()`函數(shù)會將端口號寫入上
    的頭像 發(fā)表于 03-03 09:49 ?450次閱讀
    <b class='flag-5'>探究</b><b class='flag-5'>Redis</b><b class='flag-5'>網(wǎng)絡(luò)</b><b class='flag-5'>模型</b><b class='flag-5'>究竟有多強大</b>(中)

    福祿克ST20MAX紅外測溫儀究竟有多好用

    “精準(zhǔn)測量、智能預(yù)約、堅固耐用、貼心設(shè)計…” 小福帶著首批ST20MAX客戶試用心得來啦!ST20MAX 究竟有多好用?讓我們一探究竟
    的頭像 發(fā)表于 04-10 13:55 ?136次閱讀
    主站蜘蛛池模板: miya亚洲私人影院在线 | 日韩一级片在线免费观看 | 天天干天天舔 | 黄色网址免费在线 | 免费恐怖片 | 日本aaaaa毛片动漫 | 四虎在线永久免费视频网站 | 欧美一级视频高清片 | 色综合久久久久久久久五月性色 | 69性xxxxfreexxxx| 免费一级特黄特色大片在线观看 | 尤物蜜芽福利国产污在线观看 | 天天操天天操天天操天天操 | 国产亚洲精品久久久久久午夜 | 性欧美17一18sex性高清 | 美女网站视频色 | 午夜影院免费 | 黄色绿像一级片 | 亚洲狠狠狠一区二区三区 | 午夜精品视频 | 国产一级特黄全黄毛片 | 日本免费黄色小视频 | 欧美日韩免费大片 | 五月天婷婷丁香花 | 欧美视频不卡一区二区三区 | free性欧美高清另类 | 亚洲乱论| 一级骚片超级骚在线观看 | 亚洲天堂第一页 | 色爽视频 | 农村一级片 | 高清视频一区二区三区 | ts人妖另类国产 | 天堂网在线.www天堂在线 | 国产一级毛片外aaaa | www.999精品视频观看免费 | 男女午夜免费视频 | 毛片免费网 | 一卡二卡≡卡四卡亚洲高清 | 寄宿日记在线看 | 黄色片网站大全 |