久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

IO回憶錄之怎樣過(guò)目不忘(BIO/NIO/AIO/Netty)2017版

 編程一生 2022-03-09

  有熱心的網(wǎng)友加我微信,,時(shí)不時(shí)問(wèn)我一些技術(shù)的或者學(xué)習(xí)技術(shù)的問(wèn)題,。有時(shí)候我回微信的時(shí)候都是半夜了。但是我很樂(lè)意解答他們的問(wèn)題,。因?yàn)檫@些年輕人都是很有上進(jìn)心的,,所以在我心里他們就是很優(yōu)秀的,我愿意多和努力的人交朋友,。我原來(lái)拿老公高中時(shí)復(fù)讀過(guò)一年來(lái)開(kāi)過(guò)玩笑,。他卻很平和而驕傲的回復(fù)說(shuō):“我是為了等你?!?眼里有一種賺翻了的表情,。雖然我很感激我婆婆給了個(gè)好老公,但是生氣的一點(diǎn)是婆婆從小說(shuō)我老公腦子笨,。我總跟老公說(shuō):“就是因?yàn)閶審男∵@么說(shuō)你,,你才從原本應(yīng)該是天之驕子淪為一個(gè)苦逼程序員的?!钡钱厴I(yè)十年,,他一直很努力,也很顧家,。所以在我眼里他很優(yōu)秀,。有網(wǎng)友問(wèn)我是怎樣成長(zhǎng)為技術(shù)大牛的。我回復(fù)說(shuō):“額~,,你可不可以不問(wèn)這么籠統(tǒng)的問(wèn)題,,都不知道怎么回答你,?!边^(guò)了幾天他又問(wèn)我:“你有沒(méi)有看過(guò)的東西當(dāng)時(shí)理解了然后又忘了?!蔽耶?dāng)時(shí)只是告訴他忘了就多看幾遍,,反復(fù)的看,。但是他問(wèn)的這個(gè)問(wèn)題我一直都沒(méi)有忘,我一直在想自己是怎么做的,。因?yàn)橥ㄟ^(guò)第一個(gè)問(wèn)題到第二個(gè)問(wèn)題,,可以看到他是很努力的在思考我說(shuō)的話,對(duì)于認(rèn)真的人,,咱們也得認(rèn)真,。

  本文有兩條主線:一條是學(xué)習(xí)方法,怎樣學(xué)過(guò)就能記住,。另一條是實(shí)際項(xiàng)目中的IO處理問(wèn)題,,包括BIO,NIO,AIO,netty。旨在用學(xué)習(xí)具體知識(shí)的具體流程體現(xiàn)學(xué)習(xí)方法的形成過(guò)程。

  對(duì)于技術(shù)的東西,,我是這么過(guò)目不忘的(上篇文章已經(jīng)提過(guò),,但是LZ覺(jué)得有必要強(qiáng)化一下,另外還加了一點(diǎn)):

  ☆ 積極的做項(xiàng)目

  ☆ 做過(guò)的東西反復(fù)琢磨

  ☆ 看完一本書(shū)后要再次梳理項(xiàng)目

  ☆ 手別懶,,看到例子沒(méi)一眼看明白就要?jiǎng)邮謱?shí)踐

  ☆ 記錄項(xiàng)目中潛在的問(wèn)題每隔一段時(shí)間回來(lái)想一想

  ☆ 工匠精神:代碼當(dāng)成藝術(shù)品反復(fù)優(yōu)化

  ☆ 沉住氣把項(xiàng)目做深

  ☆ 好書(shū)要每隔一段時(shí)間就再看一遍

   我在好幾篇博客中都提到一個(gè)離線數(shù)據(jù)的小項(xiàng)目,。因?yàn)檫@個(gè)項(xiàng)目我只有我一個(gè)人開(kāi)發(fā)維護(hù),所以我可以隨時(shí)將可以優(yōu)化并且放到線上,,很有成就感,。我做的是視頻和音頻部分,音頻和音頻的專(zhuān)輯是另一個(gè)小伙子做的,,他當(dāng)初把我的代碼拷貝過(guò)去,,因?yàn)閿?shù)據(jù)量比我這邊小很多,一直也沒(méi)出什么問(wèn)題,,直到有一天他拿著代碼來(lái)問(wèn)我一個(gè)問(wèn)題,,我很無(wú)奈的說(shuō):“你可不可以拷貝一個(gè)新一點(diǎn)兒的版本,我都改的完全不是這個(gè)樣子了,?!?nbsp;

  離線數(shù)據(jù)里有一個(gè)萬(wàn)一實(shí)時(shí)消息發(fā)送有問(wèn)題,手動(dòng)補(bǔ)發(fā)消息的接口,,我直接用socket同步阻塞的方式(BIO)接收瀏覽器作為客戶端,,一直也沒(méi)出什么問(wèn)題,但是做過(guò)的東西要反復(fù)琢磨,,所以我又分別使用了NIO,AIO,netty進(jìn)行了嘗試性改造,。出于信息安全的考慮,本文不附帶源碼,,簡(jiǎn)單例子可參考<實(shí)戰(zhàn)Java高并發(fā)程序設(shè)計(jì)>第五章和<netty in action>,。

  由于這個(gè)手動(dòng)服務(wù)一次也就是一兩個(gè)人調(diào)用,比較改造后的性能,,頂多看看瀏覽器里的請(qǐng)求響應(yīng)時(shí)間,,誤差很大。對(duì)于這個(gè)最簡(jiǎn)單的RPC請(qǐng)求沒(méi)什么可說(shuō)的,,最終都實(shí)現(xiàn)了,但是使用BIO,NIO,AIO由于返回響應(yīng)我直接write到socket或者buffer里,,沒(méi)用什么工具,,結(jié)果顯示有瀏覽器兼容問(wèn)題。netty由于內(nèi)置了http協(xié)議的實(shí)現(xiàn),,不存在此問(wèn)題,。這里只比較原理的區(qū)別。

   對(duì)于一個(gè)服務(wù)器端業(yè)務(wù)的開(kāi)發(fā)者來(lái)說(shuō),如果這四者選,,肯定要選netty,。netty的jar包1MB多點(diǎn),要嵌入手機(jī)啥的就算了,,這是通信用的,,放在客戶端基本也沒(méi)啥應(yīng)用場(chǎng)景。

  ☆ netty使用簡(jiǎn)單,,預(yù)置多種編解碼器,,支持多種主流協(xié)議。就像剛才說(shuō)的,,直接使用java api,,我需要自己將read到的GET xxxx HTTP1.1 XXXXX這些數(shù)據(jù)自己解析出感興趣的數(shù)據(jù),返回客戶端還要自己封裝一個(gè)瀏覽器可讀的響應(yīng),。

  ☆ netty可定制,,通過(guò)channelhander對(duì)通信框架進(jìn)行靈活擴(kuò)展。

  ☆ netty性能好,,社區(qū)活躍,,版本迭代周期短。

  首先簡(jiǎn)單提一下概念,。

  BIO:同步阻塞式IO,,服務(wù)器端與客戶端三次握手簡(jiǎn)歷連接后一個(gè)鏈路建立一個(gè)線程進(jìn)行面向流的通信。這曾是jdk1.4前的唯一選擇,。在任何一端出現(xiàn)網(wǎng)絡(luò)性能問(wèn)題時(shí)都影響另一端,,無(wú)法滿足高并發(fā)高性能的需求。

  NIO:同步非阻塞IO,,以塊的方式處理數(shù)據(jù),。采用多路復(fù)用Reactor模式。JDK1.4時(shí)引入,。

  AIO:異步非阻塞IO,,基于unix事件驅(qū)動(dòng),不需要多路復(fù)用器對(duì)注冊(cè)通道進(jìn)行輪詢,,采用Proactor設(shè)計(jì)模式,。JDK1.7時(shí)引入。

  Netty是實(shí)現(xiàn)了NIO的一個(gè)流行框架,,JBoss的,。Apache的同類(lèi)產(chǎn)品叫Mina。阿里云分布式文件系統(tǒng)TFS里用的就是Mina,。我目前的項(xiàng)目中使用了netty作為底層實(shí)現(xiàn)的有阿里云的dubbo和ElasticSearch,。我之所有要研究這個(gè)東西也是因?yàn)槲乙獙?shí)現(xiàn)自己的搜索引擎先要調(diào)研已存在的產(chǎn)品,。我之前項(xiàng)目中用過(guò)Solr,個(gè)人比較傾向于Solr,。但是大家做了很多性能比較,,ElasticSearch的并發(fā)能力確實(shí)要比Solr,究其原因,,就是因?yàn)镾olr底層還是用的Servlet容器,,而ElasticSearch底層用的是Netty。

  有人問(wèn):?jiǎn)慰磳?shí)現(xiàn)原理,,顯然AIO要比NIO高級(jí),,為什么Netty底層用NIO? Netty也曾經(jīng)做過(guò)一些AIO的嘗試性版本,但是性能效果不理想,。AIO理念很好,,但是有賴于底層操作系統(tǒng)的支持,操作系統(tǒng)目前的實(shí)現(xiàn)并沒(méi)聽(tīng)上去那么有吸引力,,是一匹剛孕育出來(lái)的黑馬,。其實(shí)AIO的性能上不去,也很好感性的理解,。NIO相當(dāng)于餐做好了自己去取,,AIO相當(dāng)于送餐上門(mén)。要吃飯的人是百萬(wàn),,千萬(wàn)級(jí)的,,送餐員也就幾百人。所以一般要吃到飯,,是自己去取快呢,,還是等著送的更快?目前的外賣(mài)流程不是很完善,,所以時(shí)間上沒(méi)想的那么靠譜,,但是有優(yōu)化空間,這就是AIO,。

  關(guān)于NIO的內(nèi)部實(shí)現(xiàn),,大家可以參考我寫(xiě)的IO和socket編程。里面沒(méi)有提到操作系統(tǒng)方面對(duì)于多路復(fù)用技術(shù)的三種常用機(jī)制:select,poll和epoll,。三個(gè)的作用都是指示內(nèi)核等待多個(gè)事件中的任何一個(gè)發(fā)生的時(shí)候或一定時(shí)間滯后被喚醒,。區(qū)別是select函數(shù)文件描述符的數(shù)量有限制,poll函數(shù)沒(méi)限制,,epoll函數(shù)用一個(gè)描述符來(lái)管理多個(gè)描述符,。

  關(guān)于文件描述符,也就是句柄,,想起一件事:好幾年前用Solr做高并發(fā)壓測(cè)的時(shí)候,,我用了一臺(tái)內(nèi)存所剩很小的服務(wù)器做測(cè)試,出現(xiàn)了NIO超出句柄數(shù)錯(cuò)誤,。而查看了系統(tǒng)的最大句柄數(shù)設(shè)置,,設(shè)置的很大,不可能用完,。換了一臺(tái)好點(diǎn)的服務(wù)器就沒(méi)了這個(gè)問(wèn)題,。那是因?yàn)閮?nèi)存不夠的時(shí)候,每次都要打開(kāi)磁盤(pán)文件的數(shù)據(jù)進(jìn)行搜索,,而內(nèi)存大點(diǎn)兒都走內(nèi)存中的緩存了,。內(nèi)存數(shù)據(jù)也有句柄,但是訪問(wèn)磁盤(pán)速度慢,,資源長(zhǎng)時(shí)間不釋放,,新的請(qǐng)求又過(guò)來(lái)了,才是句柄超出的原因,。

  關(guān)于epoll,,不得不提臭名昭著的epoll bug。它會(huì)導(dǎo)致Selector空輪詢,,最終導(dǎo)致CPU 100%,。

  關(guān)于多路復(fù)用,多嘮叨兩句,。多路指的是多個(gè)網(wǎng)絡(luò)連接,,復(fù)用是復(fù)用同一個(gè)線程。目前解決各種并發(fā)問(wèn)題的最大利器就是緩存,。我用過(guò)Memecached和Redis,。Memcached采用的是多線程,非阻塞IO復(fù)用的網(wǎng)絡(luò)模型,。Redis采用的是單線程的IO復(fù)用模型,。既然單線程會(huì)嚴(yán)重影響整體吞吐量,因?yàn)镃PU計(jì)算過(guò)程中,,整個(gè)IO調(diào)用都是被阻塞的,。那么為什么實(shí)際上大家普遍表示Redis的性能要優(yōu)于Memcached?多線程模型可以發(fā)揮多核作用,但是引入了緩存一致性和鎖的問(wèn)題,,帶來(lái)了性能損耗,。單線程可以將速度優(yōu)勢(shì)發(fā)揮到最大。想用多核,,可以多開(kāi)幾個(gè)進(jìn)程的嘛,。話說(shuō)nginx也是這樣多進(jìn)程單線程的模型。Netty可以定制,,可以單線程IO復(fù)用,,多線程IO復(fù)用,,主從多線程IO復(fù)用。

Netty邏輯架構(gòu)(從底層向上介紹)

  1> Reactor通信調(diào)度層,,由一系列輔助類(lèi)組成,,包括Reactor線程N(yùn)ioEventLoop以及其父類(lèi),NioSocketChannel以及父類(lèi),,ByteBuffer及衍生Buffer,,Unsafe及內(nèi)部子類(lèi)。

  2> 職責(zé)鏈ChannelPipeLine,,它負(fù)責(zé)調(diào)度事件在職責(zé)鏈中的傳播,,支持動(dòng)態(tài)的編排職責(zé)鏈,職責(zé)鏈可以選擇性的攔截自己關(guān)心的事件,,對(duì)其它IO操作和事件忽略,。

  3> 業(yè)務(wù)邏輯編排層。

Netty實(shí)現(xiàn)上優(yōu)勢(shì)點(diǎn):

  ☆ 零拷貝,,又叫內(nèi)存零拷貝,,指CPU不需要為數(shù)據(jù)在內(nèi)存之間的拷貝消耗資源。通常指計(jì)算機(jī)在網(wǎng)絡(luò)上發(fā)送文件時(shí),,不需要將文件內(nèi)容拷貝到用戶空間而直接在內(nèi)核空間中傳輸?shù)骄W(wǎng)絡(luò)的方式,。

  Netty的ByteBuffer采用DIRECT BUFFERS,使用堆外直接內(nèi)存進(jìn)行Socket讀寫(xiě),,不需要進(jìn)行字節(jié)緩沖區(qū)的二次拷貝,。如果大家自己動(dòng)手寫(xiě)過(guò)NIO和AIO的程序,就會(huì)知道我們接觸的網(wǎng)絡(luò)傳輸數(shù)據(jù)是直接和ByteBuffer打交道的,。在JAVA的API中,,一個(gè)ByteBuffer讀完數(shù)據(jù)后要flip一下,將當(dāng)前操作位置設(shè)置為0.<Netty In Action>里詳細(xì)介紹了Netty的ByteBuf怎樣將這個(gè)緩沖區(qū)分成一段一段的,,還可以壓縮,,將讀的數(shù)據(jù)滑向一側(cè)。而堆外內(nèi)存的零拷貝,,如果有JVM基礎(chǔ)也很好理解,。Java內(nèi)存模型里提到每個(gè)線程都有自己的高速工作內(nèi)存空間,而不是直接訪問(wèn)主內(nèi)存,。想不用工作內(nèi)存,,直接主內(nèi)存可見(jiàn),就要用volatile關(guān)鍵字修飾,。所以堆內(nèi)內(nèi)存,,走JVM就存在這個(gè)拷貝開(kāi)銷(xiāo)。

  Netty提供了組合Buffer對(duì)象,,可以聚合多個(gè)ByteBuffer對(duì)象,,而不用將幾個(gè)小Buffer通過(guò)內(nèi)存拷貝合并成一個(gè)大的Buffer.

  Netty的文件傳輸采用了transferTo方法,,它可以直接將文件緩沖區(qū)的數(shù)據(jù)發(fā)送到目標(biāo)Channel,避免了傳統(tǒng)通過(guò)循環(huán)write方式導(dǎo)致的內(nèi)存拷貝問(wèn)題,。其實(shí)這個(gè)功能不是Netty特有的,,Linux的sendfile函數(shù)和Java NIO的FileChannel的transferTo方法都實(shí)現(xiàn)了零拷貝,而Netty也通過(guò)FileRegion包裝了NIO的transferTo方法,。

  ☆  內(nèi)存池,剛才提到堆外內(nèi)存可以實(shí)現(xiàn)零拷貝,,那為啥java要設(shè)置自己的工作內(nèi)存呢,?快啊。堆外直接內(nèi)存的分配和回收是一個(gè)非常 耗時(shí)的操作,,有C或者C++基礎(chǔ)的應(yīng)該都能理解,。剛才提到的ByteBuf就是采用內(nèi)存池的,用來(lái)對(duì)緩存區(qū)復(fù)用,。

  基本一個(gè)比較底層的框架都會(huì)有自己特有的內(nèi)存池技術(shù),。比如Memcached使用預(yù)分配的內(nèi)存池方式,使用slab和帶下不同的Chunk來(lái)管理內(nèi)存,。這樣避免了上面提到的內(nèi)存分配和回收的開(kāi)銷(xiāo)問(wèn)題,。

  ☆  無(wú)鎖化的串行設(shè)計(jì)。我在自己的博客中提到自己做項(xiàng)目會(huì)把業(yè)務(wù)劃分的很清楚,,盡量少的采用線程間通信,。這就是一種無(wú)鎖化的串行設(shè)計(jì)思想。共享資源的并發(fā)訪問(wèn)處理不當(dāng),,會(huì)帶來(lái)嚴(yán)重的鎖競(jìng)爭(zhēng),,最終會(huì)導(dǎo)致性能下降。

  ☆  高效的并發(fā)編程,。有些人在面試時(shí)很吃虧(老公,,當(dāng)你看到這篇文章的時(shí)候,說(shuō)的就是你),。CPU直接操作磁盤(pán)型的,。沒(méi)有內(nèi)存,很多東西臨場(chǎng)發(fā)揮一時(shí)加載不上來(lái),。說(shuō)是吃虧究其原因是總結(jié)的少,,沒(méi)建立好強(qiáng)大的索引。而好的程序員是體現(xiàn)在細(xì)節(jié)中的,,為什么一說(shuō)原理怎么看怎么覺(jué)得Memcached比Redis先進(jìn),。而Mina的實(shí)現(xiàn)原理上也沒(méi)有多少劣于Netty的地方。就是因?yàn)楹笳叩拈_(kāi)發(fā)者更為勤奮,。比如CAS操作要比加鎖性能更好,,但是開(kāi)發(fā)維護(hù)上要繁瑣很多,。

  不論電影,電視,,武俠小說(shuō)還是實(shí)際生活中,, 智商高的人最終會(huì)被情商高的人打敗。精誠(chéng)所至金石為開(kāi)是真理,。愛(ài)一個(gè)人會(huì)打開(kāi)心靈的通道,,不著一字便可溝通。我在你心底,,你就會(huì)用我的方式去思考,。技術(shù)的書(shū),技術(shù)的文章,,代碼后面都隱藏著高人,。愛(ài)一種技術(shù),多看多想,,技術(shù)能力和境界都能得到升華,。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多