紫風(fēng)亂寫(xiě)

          除了他眼前的屏幕,這個(gè)人什么也沒(méi)看見(jiàn)。
          被周?chē)碾娔X簇?fù)碇恢浪鶆?chuàng)造的現(xiàn)實(shí),但又意識(shí)到那是虛幻。
          他已經(jīng)超越了技術(shù)。也超越了機(jī)器。
          posts - 62, comments - 93, trackbacks - 0, articles - 0
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          病中吟之內(nèi)存溢出

          Posted on 2015-06-08 19:13 Justfly Shi 閱讀(3976) 評(píng)論(4)  編輯  收藏 所屬分類(lèi): 隨便寫(xiě)寫(xiě)

          感冒了,在家里休息,打開(kāi)電腦隨便看看,想起前兩天有人問(wèn)的一個(gè)事情:“內(nèi)存溢出怎么分析和處理?”方案有很多了,基本上的思路就是獲取系統(tǒng)狀態(tài),內(nèi)存變化方向,內(nèi)存對(duì)象等之類(lèi)的,profile,debug,jmx,dump等等。

          我更想說(shuō)的是,為什么會(huì)內(nèi)存溢出呢?

          在我看來(lái),干活有兩種方式:

          • 沒(méi)想清楚了,貿(mào)貿(mào)然開(kāi)干,然后各處救火各種解決問(wèn)題
          • 想清楚了再開(kāi)干,無(wú)驚無(wú)險(xiǎn),安然做完

          一般來(lái)說(shuō),我都是后者,所以真的很少碰到各種莫名其妙的問(wèn)題,比如自己實(shí)現(xiàn)排序算法、在內(nèi)存中處理有100000個(gè)值的列表、不用第三個(gè)變量來(lái)交換兩個(gè)變量的值等等。

          怎么避免內(nèi)存溢出

          吐槽完畢,來(lái)說(shuō)說(shuō)對(duì)于內(nèi)存溢出這種事情是要怎么避免,我所謂的“想清楚了再開(kāi)干”到底是怎么想清楚的。

          首先內(nèi)存溢出的本質(zhì)是什么?“內(nèi)存使用超出了預(yù)期”。 
          那么要怎么避免呢?“預(yù)期內(nèi)存怎么使用,將其控制在內(nèi)存使用范圍呢”。

          如何預(yù)期內(nèi)存的使用

          Java程序中,內(nèi)存是被怎么占用的?被數(shù)據(jù)和對(duì)象占用的,數(shù)據(jù)和對(duì)象怎么來(lái)的?

          • 應(yīng)用的輸入和輸出
          • 第三方系統(tǒng)的輸入和輸出
          • 應(yīng)用本身產(chǎn)生的數(shù)據(jù)

          如何控制內(nèi)存的使用

          應(yīng)用輸入和輸出怎么控制

          • 控制允許輸入的線程數(shù),比如允許同時(shí)多少個(gè)線程提供服務(wù)
          • 控制輸入的請(qǐng)求對(duì)象的大小和內(nèi)容,比如輸入時(shí)的所允許的緩沖區(qū)大小
          • 輸出的線程數(shù)是和輸入的線程對(duì)應(yīng)的,如果是主動(dòng)輸出的,那么就控制一下
          • 輸出的服務(wù)對(duì)象的大小和內(nèi)容,比如你是文件服務(wù)器,那么設(shè)置一個(gè)輸出緩存,每10K就Flush一下。

          第三方系統(tǒng)的輸入和輸出怎么控制

          思路和應(yīng)用輸入和輸出怎么控制所說(shuō)的是一樣的,控制線程數(shù),使用緩存控制。

          應(yīng)用本身產(chǎn)生的數(shù)據(jù)怎么控制

          思路也是一樣的,線程數(shù),緩存,再加上生存時(shí)間,對(duì)象池等等。

          還有?

          使用上述技巧和思路你就能控制好你應(yīng)用中的內(nèi)存了,但是所有的設(shè)計(jì)都是在風(fēng)險(xiǎn)和滿(mǎn)足需求之間的平衡,如果再退一步,那么你需要考慮一下Java虛擬機(jī)中內(nèi)存各個(gè)區(qū)的使用了。你需要區(qū)分好哪些是常駐對(duì)象,哪些是臨時(shí)對(duì)象,新生代,舊生代,怎么安排你的虛擬機(jī)中各個(gè)內(nèi)存區(qū)的大小。希望你不需要用到,如果需要的話,可以看看《深入理解Java虛擬機(jī)》這本書(shū)。

          來(lái)個(gè)例子

          有這么一個(gè)應(yīng)用,它獲取客戶(hù)端的請(qǐng)求,驗(yàn)證請(qǐng)求的合法性,然后對(duì)于合法的請(qǐng)求,從第三方系統(tǒng)獲取文件內(nèi)容,并把文件內(nèi)容寫(xiě)回給客戶(hù)端。 
          下面是一大片的空白,再滾動(dòng)下去之前看我的設(shè)計(jì)之前,讀者可以就這個(gè)需求想想你會(huì)怎么處理。 







































          |

          應(yīng)用本身的的輸入和輸出的控制

          • 同時(shí)服務(wù)數(shù)設(shè)置為可配置的屬性,來(lái)控制并行的服務(wù)數(shù)
          • 請(qǐng)求只允許Get請(qǐng)求,請(qǐng)求內(nèi)容只有Header和URL,設(shè)置一個(gè)輸入Buffer
          • 輸出,設(shè)置輸出緩存區(qū)的大小,可配置的,默認(rèn)情況下,每20K Flush一下。

          第三方系統(tǒng)的輸入和輸出

          第三方系統(tǒng)有兩個(gè),一個(gè)是合法性驗(yàn)證的,一個(gè)是文件內(nèi)容的。 
          合法性驗(yàn)證的請(qǐng)求和輸出的內(nèi)容都比較小。但是考慮到其服務(wù)器的性能,把合法性驗(yàn)證的交互過(guò)程放到一個(gè)線程池中控制。這樣能避免合法性驗(yàn)證服務(wù)不過(guò)來(lái)的情況。

          文件內(nèi)容第三方系統(tǒng)的輸入和輸出的控制

          • 和合法性驗(yàn)證一樣,文件內(nèi)容第三方系統(tǒng)的輸入和輸出能力有限,將其訪問(wèn)用線程池控制起來(lái)。
          • 文件內(nèi)容第三方系統(tǒng)的請(qǐng)求訪問(wèn)對(duì)象較小,不予控制
          • 整個(gè)系統(tǒng)的最重點(diǎn)來(lái)了!文件內(nèi)容第三方系統(tǒng)的返回文件大小不可控制。所以使用緩存機(jī)制,每次讀入20K(可配置),然后寫(xiě)給系統(tǒng)的客戶(hù)端,然后再讀20K,然后再寫(xiě),讓文件內(nèi)容從這個(gè)系統(tǒng)中像水一樣流過(guò)去。流不動(dòng)了(第三方系統(tǒng)連接或者客戶(hù)端連接失?。┚妥尡敬畏?wù)失敗。這個(gè)流過(guò)去就是重點(diǎn)了,不管這個(gè)文件多大,每次請(qǐng)求只占用20K。

          應(yīng)用本身產(chǎn)生的數(shù)據(jù)

          最原始的需求中還有一個(gè)把文件內(nèi)容緩存在本地,然后可以多次寫(xiě)給客戶(hù)端的這么一個(gè)想法,減少網(wǎng)絡(luò)等待。這個(gè)想法被我否決了,原因如下:

          • 首先可以通過(guò)HTTP 304狀態(tài)碼來(lái)減少同一客戶(hù)端對(duì)同樣內(nèi)容的多次讀取。
          • 如果不對(duì)這個(gè)文件內(nèi)容進(jìn)行管理,將導(dǎo)致硬盤(pán)空間溢出。如果對(duì)其管理,會(huì)添加很多的開(kāi)發(fā)、運(yùn)維和設(shè)計(jì)的工作,得不償失。

          總結(jié)

          想清楚了再開(kāi)干就是這個(gè)意思,花點(diǎn)時(shí)間系統(tǒng)的想想,想清楚了,前面多寫(xiě)點(diǎn)代碼,多寫(xiě)點(diǎn)單元測(cè)試,后面少點(diǎn)麻煩,不用救火,也不用加班。 
          吃飯去了。

          再多啰嗦一句,《JUnit收費(fèi)課程》的第二節(jié)的材料已經(jīng)準(zhǔn)備好了,昨晚?yè)?dān)心自己的塞著鼻子,大家聽(tīng)著難受,沒(méi)有錄。今天好多了,晚上錄一下,明天上午編輯審核,明天下午或者晚上大家應(yīng)該就能看到了。


          評(píng)論

          # re: 病中吟之內(nèi)存溢出  回復(fù)  更多評(píng)論   

          2015-06-16 10:50 by imxylz
          有興趣加入世界邦么?http://www.aygfsteel.com/xylz/archive/2013/11/05/406019.html

          # re: 病中吟之內(nèi)存溢出  回復(fù)  更多評(píng)論   

          2015-06-16 21:52 by Justfly Shi
          @imxylz
          謝謝,可惜我目前不在北京。

          # re: 病中吟之內(nèi)存溢出  回復(fù)  更多評(píng)論   

          2015-06-29 12:16 by 好介紹
          對(duì)內(nèi)容溢出的介紹很不錯(cuò)!

          # re: 病中吟之內(nèi)存溢出  回復(fù)  更多評(píng)論   

          2015-08-12 11:33 by 東莞服務(wù)器租用
          話說(shuō)中間留那么大一空白是啥意思?
          主站蜘蛛池模板: 旅游| 克拉玛依市| 周宁县| 赤水市| 新巴尔虎左旗| 余庆县| 时尚| 榆树市| 襄汾县| 丹东市| 新营市| 罗定市| 聊城市| 三江| 台山市| 大宁县| 翁源县| 鸡泽县| 儋州市| 行唐县| 四平市| 永顺县| 息烽县| 伊宁县| 铁力市| 仙桃市| 会宁县| 承德市| 禹城市| 光泽县| 开江县| 城固县| 安塞县| 江油市| 沈丘县| 梁山县| 运城市| 报价| 象州县| 盐亭县| 宣化县|