放翁(文初)的一畝三分地

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            210 隨筆 :: 1 文章 :: 320 評(píng)論 :: 0 Trackbacks

          #

              下周一應(yīng)該是我今年最后一次參加內(nèi)部培訓(xùn)了,所要講的內(nèi)容也是我這大半年來都在專注的技術(shù):Open API&SIP。由于文章要在程序員1月刊發(fā)表,因此文章暫時(shí)不能放在Blog上,不過下周一的培訓(xùn)PPT還是可以分享一下的。有興趣的集團(tuán)的同學(xué)也可以來阿里軟件聽。同時(shí)也很高興的看到在csdn的blog在年底沖過了10w,希望明年有更多的分享能夠貢獻(xiàn)出來^_^



          Uploaded on authorSTREAM by cenwenchu
          posted @ 2008-12-10 10:23 岑文初 閱讀(3970) | 評(píng)論 (1)編輯 收藏

              今天,有一個(gè)使用我優(yōu)化的Memcached cache Client給我發(fā)了郵件問到一個(gè)參數(shù)的作用,覺得還是比較重要的一個(gè)參數(shù),因此也說一下,同時(shí)也在這里說一下,當(dāng)前優(yōu)化過的客戶端已經(jīng)作了幾次小的升級(jí),修復(fù)了一些邊界數(shù)據(jù)的問題,大家如果在使用的話,最好能夠升級(jí)。(http://code.google.com/p/memcache-client-forjava/

             郵件如下:

             你好:
          <socketpool name="pool0" failover="true" initConn="5" minConn="5"
            maxConn="250" maintSleep="5000" nagle="false" socketTO="3000"
            aliveCheck="true" >
            <servers>10.0.0.16:11111</servers>
            <weights>10</weights>
           </socketpool>
          能解釋下maintSleep這個(gè)意思么?我看有的資料說吧它設(shè)置為0性能更好,能給些建議么?謝謝!!我們現(xiàn)在的PV大約每天500萬(wàn)。

           

              這個(gè)參數(shù)是對(duì)此連接池維護(hù)線程的檢查間隔時(shí)間的配置,如果配置小于等于0,則將不會(huì)有后臺(tái)線程維護(hù)此連接池,參數(shù)單位為毫秒,下面解釋一下維護(hù)連接池的含義,其實(shí)就和其他的資源池一樣,資源池的目的就是為了解決資源的申請(qǐng)和釋放的開銷增加系統(tǒng)壓力的問題,將資源通過池的方式回收重用,有利于系統(tǒng)性能的提高。memcached cache client 其實(shí)是通過socket來和服務(wù)端進(jìn)行通信,建立socket連接也是比較消耗時(shí)間的工作,因此配置了池的初始連接數(shù)(initConn),最小連接數(shù)(minConn),最大連接數(shù)(maxConn)。這三者關(guān)系如下圖,維護(hù)他們之間狀態(tài)轉(zhuǎn)移的就是后臺(tái)線程。

           

              后臺(tái)進(jìn)程維護(hù)資源池的作用就是將有限資源回收,例如數(shù)據(jù)庫(kù)連接,如果一臺(tái)oracle只有500個(gè)連接數(shù)可以支持,那么如果一個(gè)應(yīng)用都占用了50個(gè)閑置,那對(duì)于其他需要資源的應(yīng)用來說無疑是一種浪費(fèi)。但如果配置了資源管理,但由于應(yīng)用屬于忙時(shí)和閑時(shí)交替比較頻繁的情況,那么如果時(shí)間配置的不是很合適,就會(huì)達(dá)不到原來資源池的作用,資源反復(fù)回收和申請(qǐng)。所以對(duì)于這個(gè)參數(shù)的配置,個(gè)人覺得一定要配,配置的值需要注意,初始化和最小的值可以是自己預(yù)估平時(shí)平均并發(fā)處理的均值,最大的連接數(shù)當(dāng)然依賴于資源的總數(shù),而維護(hù)時(shí)間間隔則最好是能夠根據(jù)閑時(shí)和忙時(shí)的情況來考慮配置,這樣既不會(huì)浪費(fèi)資源,同時(shí)也不會(huì)使資源池時(shí)效。

              順帶說一句,如果對(duì)于數(shù)據(jù)丟失要求不是很苛刻,然后網(wǎng)絡(luò)情況也不錯(cuò)的時(shí)候,可以將aliveCheck設(shè)置為false,因?yàn)槿绻莟rue,在每一次發(fā)送任何數(shù)據(jù)操作之前都會(huì)去做心跳檢查,這個(gè)未來也會(huì)考慮去優(yōu)化。

          posted @ 2008-11-21 15:28 岑文初 閱讀(1947) | 評(píng)論 (0)編輯 收藏

              一句話:“不要為做別人已經(jīng)作過的事情而沾沾自喜,要做就做別人沒有做或者做不到的”。原話可能不是這句了,但是意思差不多,這是上次架構(gòu)委員會(huì)開會(huì)的時(shí)候,阿里集團(tuán)新來的首席架構(gòu)師王堅(jiān)和我們說的一句話。原因就是集團(tuán)內(nèi)或者公司內(nèi)部資源重復(fù)去做一些工作,包括我在內(nèi)很多程序員就整天津津樂道的去重復(fù)做一些工作,對(duì)于別人的成果(國(guó)外開源除外),總是有些排斥,特別是一些關(guān)鍵性技術(shù),但其實(shí)真正的架構(gòu)師應(yīng)該關(guān)注如何能夠找到合適的方法正確高效的解決問題,如何積累技術(shù),而不是重復(fù)建設(shè),這點(diǎn)很多人都很清楚,但是真的遇到一些情況的時(shí)候,就忘記了這些準(zhǔn)則。

              一個(gè)人,我們阿軟的首席架構(gòu)師趙進(jìn)。說到對(duì)人能力的佩服,我想對(duì)于趙進(jìn)作為首席架構(gòu)師的能力,我自己真的是很實(shí)實(shí)在在的佩服。遠(yuǎn)了不說,就說最近的關(guān)于阿里軟件自己的基礎(chǔ)組件Cache,當(dāng)前除了SIP以外,其他兩個(gè)自主產(chǎn)品的cache都采用的我維護(hù)的cache組件,這次做外貿(mào)重構(gòu),其他的架構(gòu)師作了一個(gè)新的Cache,趙進(jìn)知道后覺得這個(gè)關(guān)系到未來的整體基礎(chǔ)架構(gòu)統(tǒng)一性的問題,因此反復(fù)找我們幾個(gè)人談了很久,當(dāng)然我也很理解架構(gòu)師為了項(xiàng)目需求不愿意切換或者改變現(xiàn)有成型代碼,但是如果作為一種長(zhǎng)遠(yuǎn)的負(fù)責(zé)的規(guī)劃,的卻是需要統(tǒng)一起來。期間的困難可想而知,趙進(jìn)最后找了我們的老大來拍板,結(jié)果我老大的一句話把趙進(jìn)打入冷庫(kù),連我們老大都因?yàn)閾?dān)心項(xiàng)目影響的風(fēng)險(xiǎn)而不是很贊成,我可以看出當(dāng)時(shí)趙進(jìn)的失落,但是在他棄而不舍的精神下,我真的算是感動(dòng)了,大家一起在作了分析和討論,最后總算確定了一個(gè)不算最滿意,但也算是達(dá)到目的的一個(gè)解決方案。

              那么回顧一下我對(duì)趙進(jìn)的感受,那么就能夠體現(xiàn)出如果要成為一個(gè)架構(gòu)師,或者是一個(gè)首席架構(gòu)師應(yīng)該具有的能力,首先就是微笑,其次就是傾聽,再則就是引導(dǎo),最后就是堅(jiān)持。微笑可以化解敵意,傾聽可以找出問題,引導(dǎo)可以商討解決方案,堅(jiān)持可以達(dá)到目標(biāo)。當(dāng)然雙贏之類的就不說了。其實(shí)說到能力,在我看來技術(shù)方面的能力是可以培養(yǎng)的,要成為技術(shù)上的能人,需要專注,堅(jiān)持和勤奮,但是要成為一個(gè)架構(gòu)師那么最重要的還是胸懷和眼界,能夠容納別人才會(huì)讓別人接受你,這些說起來都很容易,但是做起來卻是很難,因?yàn)檫@和個(gè)性也有關(guān)系,改變自己的個(gè)性需要勇氣和時(shí)間。

              我現(xiàn)在MSN的名字叫做海納百川,時(shí)時(shí)告訴自己有容乃大,整天為了一些細(xì)枝末節(jié)的重復(fù)勞動(dòng)而沾沾自喜,只會(huì)變成井底之蛙,要做就要做別人沒有做或者做不到的,多了解一些,多學(xué)習(xí)一些,站在不到巨人的肩膀上也站到石頭上,看得更高才會(huì)走得更遠(yuǎn)。

              一年過去之際,勉勵(lì)自己改變自己。

              有架構(gòu)師的能力,卻沒有寬廣的胸懷,那么永遠(yuǎn)只會(huì)停留在一個(gè)代碼編寫者階段。

              有寬廣的胸懷,卻只有程序員的能力,那么只要努力就會(huì)成為架構(gòu)師甚至首席架構(gòu)師。
              (打個(gè)廣告^_^,年底關(guān)于Open API的文章由于要發(fā)表在雜志上,因此無法在這里貼了,不過到了一月份應(yīng)該就可以貼了,這篇關(guān)于Open API的文章是自己沉淀自己大半年工作的一份總結(jié),也希望能夠分享給大家)

          posted @ 2008-11-20 08:46 岑文初 閱讀(2516) | 評(píng)論 (9)編輯 收藏

              昨天集團(tuán)架構(gòu)委員會(huì)(虛擬組織)作了第二次交流,各個(gè)子公司都說了當(dāng)前的一些進(jìn)度,問題和想法,我也大致講了一下阿里軟件的服務(wù)集成平臺(tái)的一些進(jìn)展和自己的一些思考,這里先貼一下PPT的圖片,后面想整理以下關(guān)于當(dāng)前Open API的一些想法以及對(duì)Open API Framework的一些思路。

           

          幻燈片1

           

          幻燈片2

           

          幻燈片3

           

          幻燈片4

           

          幻燈片5

           

          幻燈片6

           

          幻燈片7

           

          幻燈片8

           

          幻燈片9

           

          幻燈片10

           

          幻燈片11
          posted @ 2008-10-31 09:53 岑文初 閱讀(1974) | 評(píng)論 (4)編輯 收藏

                 SIP5.0以后服務(wù)的請(qǐng)求量爆發(fā)性增長(zhǎng),因此也暴露了原來沒有暴露出來的問題。由于過去一般一個(gè)新版本發(fā)布周期在一個(gè)月左右,因此如果是小的內(nèi)存泄露,在一個(gè)月之內(nèi)重新發(fā)布以后也就看不出任何問題。

          因此這陣子除了優(yōu)化Memcache客戶端和SIP框架邏輯以外其他依賴部分以外,對(duì)于內(nèi)存泄露的壓力測(cè)試也開始實(shí)實(shí)在在的做起來。經(jīng)過這次問題的定位和解決以后,大致覺得對(duì)于一個(gè)大用戶量應(yīng)用要放心的話,那么需要做這么幾步。

          1.       GC輸出的環(huán)境下,大壓力下做多天的測(cè)試。(可以在 JAVA_OPTS增加-verbose:gc -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError

          2.       檢查GC輸出日志來判斷是否有內(nèi)存泄露。(這部分后面有詳細(xì)的實(shí)例說明)

          3.       如果出現(xiàn)內(nèi)存泄露問題,則使用jprofiler等工具來排查內(nèi)存泄露點(diǎn)(之所以不一開始使用,因?yàn)?/span>jprofiler等工具對(duì)于壓力測(cè)試有影響,使得大壓力無法上去,也使問題不那么容易暴露)

          4.       解決問題,并在重復(fù)2步驟。

          這里對(duì)SIPjdk1.5jdk1.6下做壓力測(cè)試的GC 日志來做一個(gè)實(shí)際的分析對(duì)比,通過對(duì)比來大致描述一下如何根據(jù)輸出情況能夠了解應(yīng)用是否存在內(nèi)存泄露問題。(這里的內(nèi)存泄露問題就是在以前blog寫過的jdkconcurrent包內(nèi)LinkedBlockingQueuepoll方法存在比較嚴(yán)重的內(nèi)存泄露,調(diào)用頻率越高,內(nèi)存泄露的越厲害)

          兩次壓力測(cè)試都差不多都是兩天,測(cè)試方案如下:

          開始50個(gè)并發(fā),每個(gè)并發(fā)每次請(qǐng)求完畢后休息0.1秒,10分鐘后增長(zhǎng)50個(gè)并發(fā),按此規(guī)律增長(zhǎng)到500并發(fā)。

          舊版本SIP是在JDK1.5環(huán)境下完成的壓力測(cè)試,

          新版本SIPJDK版本是1.6

          壓力機(jī)和以前一樣,是10.2.226.40DELL19508CPU8G內(nèi)存。

          壓力機(jī)模擬發(fā)出對(duì)一個(gè)需要簽名的API不斷的調(diào)用請(qǐng)求。

          看看兩個(gè)Log的具體內(nèi)容(內(nèi)容很多截取部分做分析)

          先說一下日志輸出的結(jié)構(gòu):(1.61.5略微有一些不同,只是1.6對(duì)于時(shí)間統(tǒng)計(jì)更加細(xì)致)

          [GC [<collector>: <starting occupancy1> -> <ending occupancy1>, <pause time1> secs] <starting occupancy3> -> <ending occupancy3>, <pause time3> secs]

          <collector>GC收集器的名稱

          <starting occupancy1> 新生代在GC前占用的內(nèi)存

          <ending occupancy1> 新生代在GC后占用的內(nèi)存

          <pause time1> 新生代局部收集時(shí)jvm暫停處理的時(shí)間

          <starting occupancy3> JVM Heap GC前占用的內(nèi)存

          <ending occupancy3> JVM Heap GC后占用的內(nèi)存

          <pause time3> GC過程中jvm暫停處理的總時(shí)間

          Jdk1.5 log

          啟動(dòng)時(shí)GC輸出:

          [GC [DefNew: 209792K->4417K(235968K), 0.0201630 secs] 246722K->41347K(498112K), 0.0204050 secs]

          [GC [DefNew: 214209K->4381K(235968K), 0.0139200 secs] 251139K->41312K(498112K), 0.0141190 secs]

          一句輸出:

          新生代回收前209792K,回收后4417K,回收數(shù)量205375KHeap總量回收前246722K回收后41347K,回收總量205375K。這就表示100%的收回,沒有任何新生代的對(duì)象被提升到中生代或者永久區(qū)(名字說的不一定準(zhǔn)確,只是表達(dá)意思)。

          第二句輸出:

          按照分析也就只是有1K內(nèi)容被提升到中生代。

          運(yùn)行一段時(shí)間后:

          [GC [DefNew: 210686K->979K(235968K), 0.0257140 secs] 278070K->68379K(498244K), 0.0261820 secs]

          [GC [DefNew: 210771K->1129K(235968K), 0.0275160 secs] 278171K->68544K(498244K), 0.0280050 secs]

          第一句輸出:

                   新生代回收前210686K,回收后979K,回收數(shù)量209707KHeap總量回收前278070K回收后68379K,回收總量209691K。這就表示有16k沒有被回收。

          第二句輸出:

                   新生代回收前210771K,回收后1129K,回收數(shù)量209642KHeap總量回收前278171K回收后68544K,回收總量209627K。這就表示有15k沒有被回收。

          比較一下啟動(dòng)時(shí)與現(xiàn)在的新生代占用內(nèi)存情況和Heap使用情況發(fā)現(xiàn)Heap的使用增長(zhǎng)很明顯,新生代沒有增長(zhǎng),而Heap使用總量增長(zhǎng)了27M,這就表明可能存在內(nèi)存泄露,雖然每一次泄露的字節(jié)數(shù)很少,但是頻率很高,大部分泄露的對(duì)象都被升級(jí)到了中生代或者持久代。

          又一段時(shí)間后:

          [GC [DefNew: 211554K->1913K(235968K), 0.0461130 secs] 350102K->140481K(648160K), 0.0469790 secs]

          [GC [DefNew: 211707K->2327K(235968K), 0.0546170 secs] 350275K->140921K(648160K), 0.0555070 secs]

          第一句輸出:

                   新生代回收前211554K,回收后1913K,回收數(shù)量209641KHeap總量回收前350102K回收后140481K,回收總量209621K。這就表示有20k沒有被回收。

                   分析到這里就可以看出每一次泄露的內(nèi)存只有10K,但是在大壓力長(zhǎng)時(shí)間的測(cè)試下,內(nèi)存泄露還是很明顯的,此時(shí)Heap已經(jīng)增長(zhǎng)到了140M,較啟動(dòng)時(shí)已經(jīng)增長(zhǎng)了100M。同時(shí)GC占用的時(shí)間越來越長(zhǎng)。

          后續(xù)的現(xiàn)象:

                   后續(xù)觀察日志會(huì)發(fā)現(xiàn),Full GC的頻率越來越高,收集所花費(fèi)時(shí)間也是越來越長(zhǎng)。(Full GC定期會(huì)執(zhí)行,同時(shí)局部回收不能滿足分配需求的情況下也會(huì)執(zhí)行)。

          [Full GC [Tenured: 786431K->786431K(786432K), 3.4882390 secs] 1022399K->1022399K(1022400K), [Perm : 36711K->36711K(98304K)], 3.4887920 secs]

          java.lang.OutOfMemoryError: Java heap space

          Dumping heap to java_pid7720.hprof ...

                   出現(xiàn)這個(gè)語(yǔ)句表示內(nèi)存真的被消耗完了。

          Jdk1.6 log

           

          啟動(dòng)時(shí)GC的輸出:

          [GC [PSYoungGen: 221697K->31960K(229376K)] 225788K->36051K(491520K), 0.0521830 secs] [Times: user=0.26 sys=0.05, real=0.05 secs]

          [GC [PSYoungGen: 228568K->32752K(229376K)] 232659K->37036K(491520K), 0.0408620 secs] [Times: user=0.21 sys=0.02, real=0.04 secs]

          第一句輸出:

                   新生代回收前221697K,回收后31960K,回收數(shù)量189737KHeap總量回收前225788K回收后36051K,回收總量189737K100%被回收。

          運(yùn)行一段時(shí)間后輸出:

          [GC [PSYoungGen: 258944K->2536K(259328K)] 853863K->598135K(997888K), 0.0471620 secs] [Times: user=0.15 sys=0.00, real=0.05 secs]

          [GC [PSYoungGen: 259048K->2624K(259328K)] 854647K->598907K(997888K), 0.0462980 secs] [Times: user=0.16 sys=0.02, real=0.04 secs]

          第一句輸出:

                   新生代回收前258944K,回收后2536K,回收數(shù)量256408KHeap總量回收前853863K回收后598135K,回收總量255728K680K沒有被回收,但這并不意味著就會(huì)產(chǎn)生內(nèi)存泄露。同時(shí)可以看出GC回收時(shí)間并沒有增加。

          在運(yùn)行一段時(shí)間后輸出:

          [GC [PSYoungGen: 258904K->2488K(259264K)] 969663K->713923K(1045696K), 0.0485140 secs] [Times: user=0.16 sys=0.01, real=0.04 secs]

          [GC [PSYoungGen: 258872K->2448K(259328K)] 970307K->714563K(1045760K), 0.0473770 secs] [Times: user=0.16 sys=0.01, real=0.05 secs]

          第一句輸出:

                   新生代回收前258904K,回收后2488K,回收數(shù)量256416KHeap總量回收前969663K回收后713923K,回收總量255740K676K沒有被回收,同時(shí)總的Heap也有所增加。

                   此時(shí)看起來好像和1.5的狀況一樣。但是查看了一下Full GC的執(zhí)行還是400-500GC執(zhí)行一次,因此繼續(xù)觀察。

          運(yùn)行一天多以后輸出:

          [GC [PSYoungGen: 257016K->3304K(257984K)] 1019358K->766310K(1044416K), 0.0567120 secs] [Times: user=0.18 sys=0.01, real=0.06 secs]

          [GC [PSYoungGen: 257128K->2920K(258112K)] 1020134K->766622K(1044544K), 0.0549570 secs] [Times: user=0.19 sys=0.00, real=0.05 secs]

          可以發(fā)現(xiàn)Heap增長(zhǎng)趨緩。

          運(yùn)行兩天以后輸出:

          [GC [PSYoungGen: 256936K->3584K(257792K)] 859561K->606969K(1044224K), 0.0565910 secs] [Times: user=0.18 sys=0.01, real=0.06 secs]

          [GC [PSYoungGen: 256960K->3368K(257728K)] 860345K->607445K(1044160K), 0.0553780 secs] [Times: user=0.18 sys=0.01, real=0.06 secs]

          發(fā)現(xiàn)Heap反而減少了,此時(shí)可以對(duì)內(nèi)存泄露問題作初步排除了。(其實(shí)在jdk1.6環(huán)境下用jprofiler來觀察,對(duì)于concurrent那個(gè)內(nèi)存泄露點(diǎn)的跟蹤發(fā)現(xiàn),內(nèi)存的確還是會(huì)不斷增長(zhǎng)的,不過在一段時(shí)間后還是有回收,因此也就可以部分解釋前面出現(xiàn)的情況)

          總結(jié):

                   對(duì)于GC輸出的觀察需要分兩個(gè)維度來看。一個(gè)是縱向比較,也就是一次回收對(duì)于內(nèi)存變化的觀察。一個(gè)是橫向比較,對(duì)于長(zhǎng)時(shí)間內(nèi)存分配占用情況的比較,這部分比較需要較長(zhǎng)時(shí)間的觀察,不能僅僅憑短時(shí)間的幾個(gè)抽樣比較,因?yàn)閷?duì)于抽樣來說,Full GC前后的區(qū)別,運(yùn)行時(shí)長(zhǎng)的區(qū)別,資源瞬時(shí)占用的區(qū)別都會(huì)影響判斷。同時(shí)要結(jié)合Full GC發(fā)生的時(shí)間周期,每一次GC收集所耗費(fèi)的時(shí)間作為輔助判斷標(biāo)準(zhǔn)。

                   順便說一下,Heap YoungGen,OldGen,PermGen的設(shè)置也是需要注意的,并不是越大越好,越大執(zhí)行收集的時(shí)間越久,但是可能執(zhí)行Full GC的頻率會(huì)比較低,因此需要權(quán)衡。這些仔細(xì)的去了解一下GC的基礎(chǔ)設(shè)計(jì)思想會(huì)更有幫助,不過一般用默認(rèn)的也不錯(cuò)。還有就是可以配置一些特殊的GC,并行,同步等等,充分利用多CPU的資源。

                   對(duì)于GC的優(yōu)化可以通過現(xiàn)在很多圖形工具來做,也可以類似于我這樣采用最原始的分析方式,好處就是任何時(shí)間任何地點(diǎn)只要知道原理就可以分析無需借助外部工具。原始的總是最好的^_^

          posted @ 2008-10-22 16:36 岑文初 閱讀(4849) | 評(píng)論 (5)編輯 收藏

                   從去年到今年,開放這個(gè)詞也在互聯(lián)網(wǎng)上炒得火熱,自己一年多的工作也讓自己對(duì)開放這個(gè)詞有了自己的一些理解和認(rèn)識(shí)。

          開放的平臺(tái)

                   去年到今年自己的工作也隨著公司的戰(zhàn)略改變不斷的發(fā)生著變化。最早公司定位致力于為中小企業(yè)提供商務(wù)管理軟件,讓中小企業(yè)能夠通過使用在線軟件輕松搞定電子商務(wù)貿(mào)易管理。隨后公司又致力于提供開放的在線軟件運(yùn)營(yíng)平臺(tái),為眾多ISV和中小企業(yè)建立一個(gè)軟件交易平臺(tái),中小企業(yè)可以隨需定制管理軟件。到今年年初,提出了服務(wù)集成平臺(tái),ISV的應(yīng)用開發(fā)不再是封閉的開發(fā)模式,可以基于ISP提供的服務(wù)定制出更加豐富的應(yīng)用。其實(shí)這種轉(zhuǎn)變也是對(duì)平臺(tái)的開放的思想不斷成熟的一個(gè)過程。

                   獨(dú)自實(shí)現(xiàn)在線管理軟件和傳統(tǒng)軟件其實(shí)沒有太大的差別,唯一的差別就是把應(yīng)用由客戶的機(jī)器拉到了軟件提供商的服務(wù)器上,對(duì)于維護(hù),更新和商業(yè)模式可能有部分的變化,但是根本上來說軟件的封閉性還是和傳統(tǒng)軟件一樣。互聯(lián)網(wǎng)軟件的最大特點(diǎn)就是個(gè)性化需求強(qiáng)烈以及需求變更周期短,要適應(yīng)行業(yè)客戶的需求,僅僅靠一個(gè)公司的幾桿槍幾號(hào)人的創(chuàng)意遠(yuǎn)遠(yuǎn)不夠。Web2.0的熱潮其實(shí)能夠給開發(fā)人員最大的啟示就是參與才是力量的源泉,其實(shí)軟件開發(fā)也是一樣,如果能夠集合互聯(lián)網(wǎng)上眾多ISV的思想和創(chuàng)意,那么滿足用戶需求并不是一件難事,同時(shí)及時(shí)響應(yīng)用戶需求也不再是火燒屁股的事情。同時(shí),看看互聯(lián)網(wǎng)應(yīng)用開發(fā)的今天,國(guó)外Open API前幾年就已經(jīng)興起,Amazon,Google,Yahoo,FaceBook,MySpace等等,將自己的數(shù)據(jù),存儲(chǔ),計(jì)算通過API的方式提供給第三方,讓第三方開發(fā)者能夠通過使用這些服務(wù)有機(jī)會(huì)實(shí)踐自己的創(chuàng)新和創(chuàng)意,互聯(lián)網(wǎng)應(yīng)用的開發(fā)也有了新的開放式開發(fā)模式。服務(wù)集成平臺(tái)其實(shí)就是為ISV提供了創(chuàng)建應(yīng)用的一個(gè)資源平臺(tái),ISV可以通過服務(wù)集成平臺(tái)獲取到各個(gè)ISP(例如淘寶)API,在其基礎(chǔ)上開發(fā)出在線應(yīng)用,然后直接掛接到應(yīng)用運(yùn)營(yíng)平臺(tái)為終端用戶提供應(yīng)用服務(wù)。這很類似于傳統(tǒng)行業(yè)的產(chǎn)業(yè)鏈,服務(wù)集成平臺(tái)就好比原料交易市場(chǎng),應(yīng)用運(yùn)營(yíng)平臺(tái)就好比商品交易市場(chǎng)。回過頭來看,阿里系的各個(gè)子公司,其實(shí)都是在以這種思路做事,從加入公司到現(xiàn)在,給我印象最深刻的一句話就是:“凡事不要先想著如何賺到別人的錢,讓別人先賺到錢,別人自然很樂意的和你分享”,這種雙贏的思想在開放中能夠得到最好的實(shí)踐。

          開放的框架

                   一個(gè)公司技術(shù)是需要積累的,如果純粹讓每一個(gè)開發(fā)人員根據(jù)自己的能力去合作開發(fā)企業(yè)的產(chǎn)品和平臺(tái),對(duì)于企業(yè),對(duì)于產(chǎn)品都是不利的。Java吸引人就在于它的開源世界,每一個(gè)開發(fā)人員可以去獲得自己想要的,或者去貢獻(xiàn)給他人自己創(chuàng)造的。現(xiàn)在很多公司應(yīng)聘的過程就是一個(gè)開源知識(shí)問答,其實(shí)是否用過能說明什么問題呢,關(guān)鍵是沒用過如何去學(xué)習(xí)和了解并且快速上手,如果能力再?gòu)?qiáng)一點(diǎn),那就知道如何定制和擴(kuò)展,我想這樣的才可以叫做企業(yè)需要的人才。

                   從公司成立那時(shí)起,內(nèi)部就有一個(gè)應(yīng)用開發(fā)框架,作用就是為了快速開發(fā)應(yīng)用,盡最大可能降低開發(fā)者對(duì)于開發(fā)技術(shù)的學(xué)習(xí),集中精力致力于業(yè)務(wù)開發(fā)。(當(dāng)然看到這里估計(jì)98%的開發(fā)人員都會(huì)皺起眉頭)。我也為此貢獻(xiàn)了自己2個(gè)Q的工作時(shí)間,當(dāng)時(shí)我主要負(fù)責(zé)后臺(tái)重構(gòu),需要建立起一個(gè)服務(wù)框架,開始參考了OSGI(因?yàn)樗哪K化和動(dòng)態(tài)載入機(jī)制),發(fā)現(xiàn)并不是很合適,然后接觸了SCA框架(可擴(kuò)展,模塊化,SOA的支持),最后決定在開源項(xiàng)目Tuscany0.91版本的基礎(chǔ)上再次開發(fā)和封裝,實(shí)現(xiàn)了內(nèi)部的ASF(應(yīng)用服務(wù)框架)ASF作為我們開發(fā)框架的后臺(tái)基礎(chǔ)框架被廣泛使用在了我們的多條產(chǎn)品線以及基礎(chǔ)平臺(tái)上,但是ASF的質(zhì)疑就一直沒有停過,性能,學(xué)習(xí)成本,調(diào)試?yán)щy度等等。雖然自己竭力去寫了厚厚的一套文檔,一組單元測(cè)試工具,一系列的問題查找工具,作了多次的壓力測(cè)試,學(xué)習(xí)普及,但是還是得不到一些架構(gòu)師的支持。

                   其實(shí),自己在后面也做過一些思考,其實(shí)對(duì)于ASF來說,它的可擴(kuò)展性沒有什么好懷疑,他不像其他開源項(xiàng)目,我可以封裝Hessian組件,REST組件等等,隨需載入,開發(fā)者只需要配置一下標(biāo)簽,即可使用,因此這樣的框架下,不會(huì)隨著技術(shù)的發(fā)展和自己的封閉而腐爛。但是,有一點(diǎn)就導(dǎo)致推廣產(chǎn)生了那么多問題,那就是參與。我記憶很深的就是我們的首席架構(gòu)師在今年招開會(huì)議評(píng)估ASF的問題時(shí)地郵件中說的:“ASF不是岑文初一個(gè)人的ASF,也不是平臺(tái)一部的ASF,而是大家的ASF”。其實(shí)那時(shí)候我已經(jīng)不再專職負(fù)責(zé)ASF,當(dāng)今年因?yàn)橐粋€(gè)項(xiàng)目進(jìn)度由于開發(fā)受到影響時(shí)再次提出ASF的質(zhì)疑地時(shí)候,我自己真的覺得比較沮喪,很多架構(gòu)師和開發(fā)者從來就沒有看過文檔,沒有用過調(diào)試工具,沒有看過Q&A,一出問題就覺得無所適從,要找人解決框架問題,我曾經(jīng)說是否Spring用的時(shí)候出現(xiàn)問題,第一想法就是去找Spring的開發(fā)者,還是先會(huì)看看文檔,調(diào)試一下。我想這應(yīng)該是兩方面的原因,但如果能夠讓每個(gè)人都參與進(jìn)來,那么就不會(huì)是今天一人獨(dú)擋的局面。

                   因此未來自己的工作中,不論是內(nèi)部的基礎(chǔ)組件還是基礎(chǔ)平臺(tái)都會(huì)多邀請(qǐng)一些參與者,畢竟自己的肩膀有限,螞蟻就算在大力也需要有伙伴的支持。

          開放的心態(tài)

                   這點(diǎn)其實(shí)是做人的基本要素,有一個(gè)寬闊的胸懷才會(huì)有更多的機(jī)會(huì),才會(huì)成長(zhǎng)的更快。但是自己這點(diǎn)的卻做得很不夠。開發(fā)人員都有一個(gè)相同的特點(diǎn)就是熱衷于技術(shù)鉆研,今天搞一個(gè)東西比你快一點(diǎn),明天做一個(gè)東西比他功能多一點(diǎn),總是在技術(shù)方面去尋找滿足。其實(shí)老大一直和我們也在說,現(xiàn)在公司內(nèi)部的架構(gòu)師并不是一個(gè)“全專”,也不一定是一個(gè)寫代碼高手,但是在某一個(gè)領(lǐng)域會(huì)有深入的研究,同時(shí)接觸其他領(lǐng)域也能夠勝任。沒有什么技術(shù)人員是絕對(duì)的高手,其實(shí)隨著工作重心的不斷變化,所接觸的領(lǐng)域也會(huì)不斷發(fā)生變化,因此不可能有所謂的“全才”。

                   有時(shí)候自己也會(huì)用技術(shù)的眼光去看待人或者事,其實(shí)這樣只會(huì)讓自己看不到自己的不足,也忽略了別人的優(yōu)點(diǎn),更重要的就是失去了一次進(jìn)步的機(jī)會(huì)。其實(shí)經(jīng)常給自己換換思路會(huì)對(duì)自己有很大的幫助,就好比最近忙于寫了一陣子代碼,那么就給自己一個(gè)機(jī)會(huì)去看看一些關(guān)于搜索領(lǐng)域的知識(shí)。開發(fā)了一個(gè)階段的服務(wù)集成平臺(tái),去了解一下所有的國(guó)外網(wǎng)站Open API的風(fēng)格,結(jié)構(gòu),流程。用慣了Java后,去學(xué)習(xí)學(xué)習(xí)Php,Ruby等等。這樣換換腦子對(duì)自己來說會(huì)有新的收獲。

                   開放的心態(tài)理解容易,但是要讓他不僅僅寫在MSNtitle中,而寫在心里卻需要不斷地督促和付出。不過知道自己有問題好過覺得自己沒有問題。

                   寫了那么些,其實(shí)思路比較亂,我想從隨筆里面也看得出來,但是還是想記錄一下自己的一些思考,起碼以后回過頭來可以看到自己成長(zhǎng)的過程。

          posted @ 2008-10-07 13:24 岑文初 閱讀(1720) | 評(píng)論 (5)編輯 收藏

              昨天貼了這個(gè)帖子以后,有同學(xué)說我是不是寫錯(cuò)了,Memcached Cache應(yīng)該是分布式的Cache,怎么變成集中式了。

              這里把我另外一部分的內(nèi)容貼出來。

              Memcached是一種集中式Cache,支持分布式橫向擴(kuò)展。這里需要有點(diǎn)說明,很多開發(fā)者覺得Memcached是一種分布式Cache,但是其實(shí)Memcached服務(wù)端本身是單實(shí)例的,只是在客戶端實(shí)現(xiàn)過程中可以根據(jù)存儲(chǔ)的主鍵作分區(qū)存儲(chǔ),而這個(gè)區(qū)就是Memcached服務(wù)端的一個(gè)或者多個(gè)實(shí)例,如果將客戶端也囊括到Memcached中,那么可以部分概念上說是集中式的。其實(shí)回顧一下集中式的構(gòu)架,無非兩種情況:1.節(jié)點(diǎn)均衡的網(wǎng)狀(JBoss Tree Cache),利用JGroup的多播通信機(jī)制來同步數(shù)據(jù)。2.Master-Slaves模式(分布式文件系統(tǒng)),由Master來管理Slave,如何選擇Slave,如何遷移數(shù)據(jù),都是由Master來完成,但是Master本身也存在單點(diǎn)問題。

          總結(jié)幾個(gè)它的特點(diǎn)來理解一下它的優(yōu)點(diǎn)和限制。

                   Memory:內(nèi)存存儲(chǔ),不言而喻,速度快,對(duì)于內(nèi)存的要求高,不指出的話所緩存的內(nèi)容非持久化。對(duì)于CPU要求很低,所以常常采用將Memcached服務(wù)端和一些CPU高消耗Memory低消耗應(yīng)用部屬在一起。(作為我們AEP正好有這樣的環(huán)境,我們的接口服務(wù)器有多臺(tái),接口服務(wù)器對(duì)于CPU要求很高(由于WS-Security),但是對(duì)于Memory要求很低,因此可以用作Memcached的服務(wù)端部屬機(jī)器)

                   集中式Cache:避開了分布式Cache的傳播問題,但是需要非單點(diǎn)保證其可靠性,這個(gè)就是后面集成中所作的cluster的工作,可以將多個(gè)Memcached作為一個(gè)虛擬的cluster,同時(shí)對(duì)于cluster的讀寫和普通的memcached的讀寫性能沒有差別。

                   分布式擴(kuò)展:Memcached的很突出一個(gè)優(yōu)點(diǎn),就是采用了可分布式擴(kuò)展的模式。可以將部屬在一臺(tái)機(jī)器上的多個(gè)Memcached服務(wù)端或者部署在多個(gè)機(jī)器上的Memcached服務(wù)端組成一個(gè)虛擬的服務(wù)端,對(duì)于調(diào)用者來說完全屏蔽和透明。提高的單機(jī)器的內(nèi)存利用率,也提供了scale out的方式。

                   Socket通信:傳輸內(nèi)容的大小以及序列化的問題需要注意,雖然Memcached通常會(huì)被放置到內(nèi)網(wǎng)作為Cache,Socket傳輸速率應(yīng)該比較高(當(dāng)前支持Tcp和udp兩種模式,同時(shí)根據(jù)客戶端的不同可以選擇使用nio的同步或者異步調(diào)用方式),但是序列化成本和帶寬成本還是需要注意。這里也提一下序列化,對(duì)于對(duì)象序列化的性能往往讓大家頭痛,但是如果對(duì)于同一類的Class對(duì)象序列化傳輸,第一次序列化時(shí)間比較長(zhǎng),后續(xù)就會(huì)優(yōu)化,其實(shí)也就是說序列化最大的消耗不是對(duì)象序列化,而是類的序列化。如果穿過去的只是字符串,那么是最好的,省去了序列化的操作,因此在Memcached中保存的往往是較小的內(nèi)容。

                   特殊的內(nèi)存分配機(jī)制:首先要說明的是Memcached支持最大的存儲(chǔ)對(duì)象為1M。它的內(nèi)存分配比較特殊,但是這樣的分配方式其實(shí)也是對(duì)于性能考慮的,簡(jiǎn)單的分配機(jī)制可以更容易回收再分配,節(jié)省對(duì)于CPU的使用。這里用一個(gè)酒窖比喻來說明這種內(nèi)存分配機(jī)制,首先在Memcached起來的時(shí)候可以通過參數(shù)設(shè)置使用的總共的Memory,這個(gè)就是建造一個(gè)酒窖,然后在有酒進(jìn)入的時(shí)候,首先申請(qǐng)(通常是1M)的空間,用來建酒架,酒架根據(jù)這個(gè)酒瓶的大小分割酒架為多個(gè)小格子安放酒瓶,將同樣大小范圍內(nèi)的酒瓶都放置在一類酒架上面。例如20cm半徑的酒瓶放置在可以容納20-25cm的酒架A上,30cm半徑的酒瓶就放置在容納25-30cm的酒架B上。回收機(jī)制也很簡(jiǎn)單,首先新酒入庫(kù),看看酒架是否有可以回收的地方,如果有直接使用,如果沒有申請(qǐng)新的地方,如果申請(qǐng)不到,采用配置的過期策略。這個(gè)特點(diǎn)來看,如果要放的內(nèi)容大小十分離散,同時(shí)大小比例相差梯度很明顯,那么可能對(duì)于使用空間來說不好,可能在酒架A上就放了一瓶酒,但占用掉了一個(gè)酒架的位置。

                   Cache機(jī)制簡(jiǎn)單:有時(shí)候很多開源的項(xiàng)目做的面面俱到,但是最后也就是因?yàn)檫^于注重一些非必要性的功能而拖累了性能,這里要提到的就是Memcached的簡(jiǎn)單性。首先它沒有什么同步,消息分發(fā),兩階段提交等等,它就是一個(gè)很簡(jiǎn)單的Cache,把東西放進(jìn)去,然后可以取出來,如果發(fā)現(xiàn)所提供的Key沒有命中,那么就很直白的告訴你,你這個(gè)key沒有任何對(duì)應(yīng)的東西在緩存里,去數(shù)據(jù)庫(kù)或者其他地方取,當(dāng)你在外部數(shù)據(jù)源取到的時(shí)候,可以直接將內(nèi)容置入到Cache中,這樣下次就可以命中了。這里會(huì)提到怎么去同步這些數(shù)據(jù),兩種方式,一種就是在你修改了以后立刻更新Cache內(nèi)容,這樣就會(huì)即時(shí)生效。另一種是說容許有失效時(shí)間,到了失效時(shí)間,自然就會(huì)將內(nèi)容刪除,此時(shí)再去去的時(shí)候就會(huì)命中不了,然后再次將內(nèi)容置入Cache,用來更新內(nèi)容。后者用在一些時(shí)時(shí)性要求不高,寫入不頻繁的情況。

                   客戶端的重要性:Memcached是用C寫的一個(gè)服務(wù)端,客戶端沒有規(guī)定,反正是Socket傳輸,只要語(yǔ)言支持Socket通信,通過Command的簡(jiǎn)單協(xié)議就可以通信,但是客戶端設(shè)計(jì)的合理十分重要,同時(shí)也給使用者提供了很大的空間去擴(kuò)展和設(shè)計(jì)客戶端來滿足各種場(chǎng)景的需要,包括容錯(cuò),權(quán)重,效率,特殊的功能性需求,嵌入框架等等。

                   幾個(gè)應(yīng)用點(diǎn):小對(duì)象的緩存(用戶的token,權(quán)限信息,資源信息)。小的靜態(tài)資源緩存。Sql結(jié)果的緩存(這部分用的好,性能提高相當(dāng)大,同時(shí)由于Memcached自身提供scale out,那么對(duì)于db scale out的老大難問題無疑是一劑好藥)。ESB消息緩存。

          posted @ 2008-09-26 11:45 岑文初 閱讀(3289) | 評(píng)論 (2)編輯 收藏

               摘要:   Author:文初 Email: wenchu.cenwc@alibaba-inc.com Blog: http://blog.csdn.net/cenwenchu79/            MemCached Cache在大型網(wǎng)站被應(yīng)用得越來越廣泛,不同語(yǔ)言的客戶端也都在官方網(wǎng)站上...  閱讀全文
          posted @ 2008-09-25 16:34 岑文初 閱讀(6791) | 評(píng)論 (3)編輯 收藏

          越是忙,雜七雜八的事情越多,最近正在優(yōu)化Memcache的客戶端代碼,這時(shí)候SIP突然出現(xiàn)OOM的問題(Out of Memory),作開發(fā)最頭痛就是這種問題,壓力測(cè)試都作過,早期的幾個(gè)版本都沒有出現(xiàn)這樣的問題,因此懷疑可能是最近一次發(fā)布修改引起的。借助JProfiler在測(cè)試環(huán)境搭了一套系統(tǒng),開始做壓力測(cè)試,來分析Memory到底流到了哪里去了。

          問題一:連接池泄漏

                 看到這個(gè)問題,我想很多人都說,都什么年代了,使用開源的現(xiàn)成連接池,怎么還會(huì)有這樣的問題,又不是那些使用jdbc的年代了。那來看看現(xiàn)象吧。

          場(chǎng)景:測(cè)試部用loadRunner往死里壓,發(fā)現(xiàn)很多業(yè)務(wù)對(duì)象不斷增長(zhǎng),但是按照業(yè)務(wù)場(chǎng)景來說,這些業(yè)務(wù)對(duì)象處理以后就自動(dòng)釋放了。(在本地的開發(fā)環(huán)境驗(yàn)證了是會(huì)自動(dòng)釋放的)

          JProfiler截圖:

                 上圖中可以看到有很多業(yè)務(wù)對(duì)象已經(jīng)累積占用了不少內(nèi)存,在讓測(cè)試部同學(xué)停掉壓力測(cè)試以后,等待了一會(huì)兒,然后用JProfiler主動(dòng)發(fā)起垃圾回收,也看到了Jboss后臺(tái)有GC回收的記錄輸出以后,發(fā)現(xiàn)這些對(duì)象依然存在,也就是說這些對(duì)象成為了Memory泄漏的誘因之一。但是就如我所說的,在本地測(cè)試以及白盒測(cè)試來看,這些對(duì)象在一次請(qǐng)求以后,處理完畢一定會(huì)被釋放,沒有被其他MapReference,然后通過JProfiler看了看這些對(duì)象的Allocation Call Tree,就是我們處理請(qǐng)求的Servlet作為源頭的,但為什么Servlet沒有被清理掉呢?接著來看看后面二張圖

                 既然知道對(duì)象存在并且被Hold了,那么就去看看線程運(yùn)行的狀況,這一看發(fā)現(xiàn)有很多線程都處于Wait的狀態(tài)(其實(shí)在serverdump也可以看到),這張圖上就可以看到,我選擇了其中一個(gè)wait的線程它處于等待狀態(tài)的原因就是在ibatisThrottleincrement的時(shí)候處于等待狀態(tài),看了看ibatis的代碼,這部分代碼其實(shí)是ibatis連接池的一段代碼,在連接池被占滿以后,處于等待釋放的狀態(tài),也就是說程序把連接池耗盡了。

                 為了驗(yàn)證是否是耗盡了,讓DBA老大光輝給我看了看MySql(這部分當(dāng)天的日志數(shù)據(jù)都保存在MySql中)的連接情況,發(fā)現(xiàn)只有8個(gè)連接,看來不是真的耗盡,應(yīng)該是連接池泄露了。光輝告訴我,這八個(gè)連接都在做同一個(gè)查詢,就是統(tǒng)計(jì)某一個(gè)API的訪問記錄次數(shù)和流量。在當(dāng)前的業(yè)務(wù)流程中對(duì)于MySql主要做了兩類操作:

                 1.訪問控制計(jì)數(shù)器創(chuàng)建的統(tǒng)計(jì)查詢。

          由于要對(duì)Open API訪問控制,采用了Memcache計(jì)數(shù)器方式來實(shí)現(xiàn)。當(dāng)發(fā)現(xiàn)此類API沒有創(chuàng)建過計(jì)數(shù)器,那么就分析MySql中的數(shù)據(jù),創(chuàng)建計(jì)數(shù)器,后續(xù)的訪問記錄除了插入數(shù)據(jù)庫(kù)以外還需要累加計(jì)數(shù)器,這樣訪問控制可以高效使用集中式計(jì)數(shù)器而不需要查詢數(shù)據(jù)庫(kù)。

          2.日志批量異步寫入。

          對(duì)于Open API的記錄采用了線程池中每一個(gè)線程維護(hù)一個(gè)內(nèi)存分頁(yè),當(dāng)頁(yè)滿或者到了刷新間隔時(shí),一次性批量寫入數(shù)據(jù)庫(kù),緩解數(shù)據(jù)庫(kù)寫入壓力,這里采用了事務(wù)來批量提交。

                 對(duì)于第一種操作,由于設(shè)計(jì)中MySql就只會(huì)保留當(dāng)天的數(shù)據(jù)量,因此只有系統(tǒng)啟動(dòng)的時(shí)候做一次統(tǒng)計(jì),對(duì)于數(shù)據(jù)庫(kù)壓力和Sql執(zhí)行來說應(yīng)該沒有太大的壓力,但是由于壓力測(cè)試是從昨天下午就開始做的,里面的數(shù)據(jù)已經(jīng)有上千萬(wàn),因此這次重新啟動(dòng)開始做壓力測(cè)試,導(dǎo)致了這個(gè)創(chuàng)建計(jì)數(shù)器的Sql執(zhí)行很慢。同時(shí)日志的批量寫入采用的是事務(wù)方式來提交,對(duì)于MySql其實(shí)自己還不是很深入,但是感覺上來說,問題應(yīng)該出現(xiàn)在這里,由于查詢的緩慢在加上事務(wù)批量的提交,可能會(huì)造成事務(wù)失敗,同時(shí)沒有正確的將釋放資源的信號(hào)傳遞給ibatis,導(dǎo)致了看起來的連接資源耗盡。

                 我將數(shù)據(jù)庫(kù)中的記錄全部刪除,然后重新啟動(dòng),開始?jí)毫y(cè)試,問題不存在了,對(duì)象都及時(shí)得到回收。后續(xù)還會(huì)去跟進(jìn)這個(gè)問題,在ibatis早期版本,同樣是這個(gè)類出現(xiàn)了死鎖的問題,后來升級(jí)得到了解決,但是也看到很多國(guó)外的朋友說道2.22.3其實(shí)還是有死鎖的問題,不過我個(gè)人覺得可能還是和數(shù)據(jù)庫(kù)也有一定關(guān)系。

          疑問:

                 這個(gè)問題的背后我還有一點(diǎn)疑問,對(duì)于我們來說,如果一個(gè)普通的http請(qǐng)求,當(dāng)超時(shí)以后肯定就會(huì)自動(dòng)中斷,但是在這個(gè)場(chǎng)景中,我足足等了1個(gè)小時(shí)還是沒有釋放,也就是說客戶端其實(shí)已經(jīng)斷開了,但是JBoss好像并不會(huì)釋放這些處理請(qǐng)求的事務(wù),導(dǎo)致資源被卡。

          問題二:LinkedBlockingQueue惹禍

                 自從Jdk1.5以后concurrent包為大家提供了很多便利高效的開發(fā)新模式,我在不少地方用到了LinkedBlockingQueue,作為消費(fèi)者和生產(chǎn)者之間的數(shù)據(jù)通道,消費(fèi)者們等待在LinkedBlockingQueue門口守候生產(chǎn)者提供數(shù)據(jù),獲取數(shù)據(jù)后就開始并行處理。這里我會(huì)采用queue.poll(100,TimeUnit.MILLISECONDS)這種方式來半阻塞的獲取數(shù)據(jù)。其實(shí)在昨天已經(jīng)聽說LinkedBlockingQueue可能存在著內(nèi)存泄露的問題,看了看很多網(wǎng)上的人也都提到了這個(gè)問題,在1.5種沒有得到解決,在1.6中會(huì)去fix這個(gè)問題,但是沒有證據(jù),也不好亂加斷定。在問題一搞好以后,然后繼續(xù)查找潛在bug,這時(shí)候不經(jīng)意的發(fā)現(xiàn)有一個(gè)對(duì)象隨著時(shí)間的推移始終在增加,但是由于單個(gè)對(duì)象占的內(nèi)存不大,因此沒有很明顯的體現(xiàn)出來,但是對(duì)象實(shí)例的增加卻是很明顯的,看看下面兩張圖:

                

          這兩張圖的間隔時(shí)間2小時(shí)左右,可以發(fā)現(xiàn)這個(gè)對(duì)象的instance已經(jīng)有了很大的增長(zhǎng),同時(shí)內(nèi)存也吃了不少,看了看創(chuàng)建這個(gè)對(duì)象的Tree,發(fā)現(xiàn)就是poll這個(gè)方法,也就是我線程池中線程周期性掃描的結(jié)果。這期間沒有任何訪問,僅僅就是放著不動(dòng),就有如此大量的增長(zhǎng)。我嘗試將poll(100,TimeUnit.MILLISECONDS)換成poll()全阻塞方式,對(duì)象增長(zhǎng)依舊。因此可以看出來服務(wù)器的Memory Leak很大程度上由這部分引起,早先沒有發(fā)現(xiàn),因?yàn)槭?/span>SIP上線不久,沒有太多用戶,而這陣子用戶越來越多,加上API中的更新類請(qǐng)求比較吃內(nèi)存,就容易發(fā)現(xiàn)此類問題。

                 那么是否1.6就解決了這個(gè)問題呢,開始使用機(jī)器上1.6_01的版本,發(fā)現(xiàn)問題依舊,去sun下載了最新的1.6_07,發(fā)現(xiàn)的卻會(huì)回收,但是回收和增長(zhǎng)都存在,具體數(shù)據(jù)描述舉例如下:

          1.       1000 instance   31k

          2.       200 instance    6k (回收了一部分)

          3.       1500 instance   46k(發(fā)現(xiàn)增長(zhǎng)的比以前還多)

          4.       300 instance    9k (回收了一部分)

          5.       2000 instance   62k (發(fā)現(xiàn)增長(zhǎng)的比以前還多)

          也就是說,回收時(shí)有發(fā)生,但是總體趨勢(shì)還是在上升,這個(gè)真的還需要好好測(cè)試,有興趣的同學(xué)也可以試驗(yàn)一下我的測(cè)試方式,就僅僅只需要使用一個(gè)LinkedBlockingQueue,然后定時(shí)的去pool1.5絕對(duì)增長(zhǎng)的不小。

                 對(duì)于這個(gè)問題,我只能再去驗(yàn)證,如果發(fā)現(xiàn)真的暫時(shí)不可避免,那么只有考慮替代方案了。

          這是今天作了Memory Leak的一些分享,希望也能給其他遇到或者將會(huì)遇到問題的同學(xué)一個(gè)分享,說一句,如果有條件的話用JProfiler去分析性能絕對(duì)是不錯(cuò)的,沒有條件么就dump,gc輸出來查找問題。
             剛剛作了測(cè)試現(xiàn)在的場(chǎng)景可以用take來替換poll,原來是看中了poll的timeout方式,take完全沒有問題,看來如果要在1.5版本用,還是老老實(shí)實(shí)用take。

          posted @ 2008-09-18 22:14 岑文初 閱讀(3935) | 評(píng)論 (4)編輯 收藏

           

                 集團(tuán)內(nèi)部很多團(tuán)隊(duì)都使用Memcache來提高應(yīng)用性能,最近的一次工作匯報(bào)中提及了MemcacheHash算法需要研究來滿足一些需求,同時(shí)提高Memcache的利用效率。討論了一下最后自己總結(jié)了這么幾點(diǎn)是對(duì)Hash算法需要著重考慮的。

          問題:

          1.       存儲(chǔ)數(shù)據(jù)如何均勻分散。如何把數(shù)據(jù)盡可能的散開存儲(chǔ),這樣對(duì)于Memcache的可擴(kuò)展性才會(huì)有充分利用,試想如果算法每次都會(huì)把數(shù)據(jù)定向到某幾臺(tái)機(jī)器,那么就會(huì)導(dǎo)致集群機(jī)器之間利用率的不均衡,無法發(fā)揮出集群效應(yīng)。

          2.       增減機(jī)器減小對(duì)原有數(shù)據(jù)存取的影響。由于業(yè)務(wù)量的增長(zhǎng)勢(shì)必需要對(duì)后端的服務(wù)器有所擴(kuò)容,但是增加或者減少機(jī)器如何盡可能小的影響已有的緩存數(shù)據(jù),這點(diǎn)直接影響業(yè)務(wù)處理以及應(yīng)用的效率。

          3.       提高Memcache效率。Memcache在壓力測(cè)試下也會(huì)暴露出對(duì)于網(wǎng)絡(luò)資源的消耗問題,畢竟也是網(wǎng)絡(luò)間的Socket數(shù)據(jù)交互。

          解決的一些思路和方法:

          1.       Consistent Hashing是一種比較好的解決思路。可以參看一下:http://tech.idv2.com/2008/07/24/memcached-004/ 其中主要兩個(gè)亮點(diǎn)就是稀釋節(jié)點(diǎn)以及環(huán)狀分區(qū)段管理。稀釋節(jié)點(diǎn)就是將原來的節(jié)點(diǎn)再?gòu)?fù)制幾十倍,使得離散度更高,數(shù)據(jù)更加分散。環(huán)狀分區(qū)段管理,就能夠?qū)?shù)據(jù)分區(qū)管理,在加入和減少節(jié)點(diǎn)時(shí)對(duì)數(shù)據(jù)產(chǎn)生影響最低,最好的類比就是解放前的地下工作者單線聯(lián)系,如果被捕不會(huì)涉及到所有的地下黨同志。

          2.       集群的機(jī)器使用Memcache最好結(jié)合本地Cache,這里我們自己寫了一個(gè)本地的類似于Memcache有超時(shí)時(shí)間Cache,兩者結(jié)合一起使用緩存信息,在壓力測(cè)試下提高了20%左右的性能。這里和我們的系統(tǒng)也有關(guān)系,我們對(duì)于Memcache有比較大的依賴,雖然已經(jīng)對(duì)于每一個(gè)請(qǐng)求處理都防止重復(fù)獲取信息,將必要信息放在線程上下文中,但是在運(yùn)行期間還是會(huì)有不少的請(qǐng)求。

          存儲(chǔ)到Memcache中的數(shù)據(jù)類型:

          1. 一次寫入多次讀,很少更新。這種數(shù)據(jù)系統(tǒng)啟動(dòng)以后構(gòu)建,在非命中情況下不采用從后備數(shù)據(jù)源中獲取數(shù)據(jù)來填充Memcache。(也是提高效率,同時(shí)防止一些攻擊性的請(qǐng)求)

          2. 多次寫入多次讀取。這類數(shù)據(jù)往往是在運(yùn)行期被構(gòu)建,非命中下會(huì)從后備數(shù)據(jù)源中獲取,或者是某一種計(jì)算結(jié)果的緩存。

          對(duì)于第一類數(shù)據(jù)來說,增加機(jī)器需要重新構(gòu)建,如果采用分區(qū)分段,那么只需要構(gòu)建某一部分的數(shù)據(jù),或者是移動(dòng)數(shù)據(jù)。對(duì)于第二類數(shù)據(jù),增加機(jī)器如果采用簡(jiǎn)單的Hash算法也問題不大,最多存儲(chǔ)多份,命中率降低,但是如果采用分區(qū),也可以降低命中率下降的情況。

                 這里只是拋出問題,后續(xù)如何解決請(qǐng)各位看官各抒己見了。當(dāng)然這里自己也會(huì)考慮這方面的實(shí)現(xiàn)和設(shè)計(jì)。
          posted @ 2008-08-14 10:36 岑文初 閱讀(3439) | 評(píng)論 (1)編輯 收藏

          僅列出標(biāo)題
          共12頁(yè): First 上一頁(yè) 4 5 6 7 8 9 10 11 12 下一頁(yè) 
          主站蜘蛛池模板: 筠连县| 井冈山市| 平山县| 长乐市| 吉林市| 建昌县| 景宁| 兰考县| 岚皋县| 丰台区| 四子王旗| 长宁县| 巧家县| 叙永县| 天等县| 商河县| 珲春市| 临沭县| 上杭县| 沁水县| 阿尔山市| 昌吉市| 罗定市| 恩施市| 浙江省| 慈溪市| 巴塘县| 巴彦县| 桂平市| 宕昌县| 吴江市| 夏邑县| 麟游县| 家居| 定陶县| 湘潭市| 河池市| 弥勒县| 尖扎县| 渭源县| 文化|