iT邦幫忙

6

可撐長時間運作的動態網頁技術?

已經有邦友在抱怨沒什麼新鮮事好聊了,以前這種『上網倦怠症』會由女王定期的話題來化解,不過不知道女王是否也受到『上網倦怠症』的荼毒而呈半退休狀態 ...汗因此野人獻曝貢獻一個可以閒嗑牙的話題。
敝人剛好最近在處理一個問題,把經過分享一下,也許看不下去最近問題太簡單的資深邦友們,會有什麼建議或心得也說不定。

事情是醬子的。最近一個案子是做系統監控的 Web AP,架構是 LAMP,前台使用 EXT-JS 拉畫面及 AJAX。系統需求不是太複雜,完成了。它跟一般瀏覽網站的不一樣之處,在於因為是監控,所以網頁在登入、進到監控頁面之後就不再換頁,持續跑AJAX做監控資料的更新顯示 .... 直到天荒地老。

問題來了。大家都知道瀏覽器一般的使用情境是開啟頁面,看幾秒幾分之後,就會點連結跳走,很少會留在一個固定頁面數天、數週甚至數個月都不切換的。所以瀏覽器的設計理念,在單一頁面中就是持續一直要記憶體來使用,幾乎不 care 釋不釋放記憶體的問題,因為反正換頁後整塊記憶體就會 drop 掉,一了百了,所以幹嘛那麼麻煩去 take care 每一次 allocate 的記憶體到底釋放沒。也因此,如果單純停在某個頁面而持續做 DOM 的改變、持續做 AJAX 的存取,那麼記憶體就會像最近的失業率一樣,如火箭般地衝向月球。

所以原本必須持續數個月監控的 Web 系統,在幾個小時之後,瀏覽器就會死給你看。如果還搭配 Socket.IO 做 comet,則死傷更慘烈。五大瀏覽器,無一倖免,全都會在幾個小時內把 Windows 記憶體塞爆,並停止運作。其中 IE 測試的版本 IE8 最慘,只要 <img> 換圖就升,Temporary Internet Files 檔案過多也掛,IE9 也不遑多讓,有更別出心裁的 mem leak ...

什麼!監控系統只能監控數小時?!這什麼鳥東西?!但我們 RD 又不能跟老闆、客戶說:「啊就因為瀏覽器會 memory leak,所以系統只有三小時限定。要不然我們免費附贈一個三小時後重載網頁的功能好了。」這麼說的話一定會被直接釘在牆壁當標本。事情也不是推給 IE, Firefox,Chrome 就算了。問題是瀏覽器的記憶體,Javascript 再怎麼厲害也沒有權限幫它做 Garbage Collection 啊!但老闆、客戶可不管什麼權不權限的。他們只有期限,沒有權限。限期解決,否則究責。

看倌們!請問您會從什麼方面來解這問題?改用不同的 comet 技術?使用外掛元件做 GC?額外寫支程式躲在背景監控瀏覽器?還是乾脆開發個 Windows AP 來取代 Web?說說您的看法。


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
ted99tw
iT邦高手 1 級 ‧ 2012-08-31 12:15:23

少林寺方丈出手,果然有一套.......鼓掌灑花先!!灑花灑花

wiseguy大可要有頭有尾,十天半月後要結論一下,讓眾囉囉謄寫一翻!!
謝謝謝謝

wiseguy iT邦超人 1 級 ‧ 2012-08-31 21:38:18 檢舉

那當然。小弟是有些解決的方案,不過老實說都不是最完美的解。後續會做個總結,分享給大家參考參考。謝謝

ted99tw iT邦高手 1 級 ‧ 2012-08-31 21:42:33 檢舉

wiseguy提到:
後續會做個總結

讚讚讚

0
kolom
iT邦好手 1 級 ‧ 2012-08-31 12:44:02

因為我都看不太懂,所以我的方法很簡單,就是叫 工程師 幫我限期解決,管你用什麼方法..開心
如果我是工程師,則用一個定時裝置 每幾分鐘 按一次F5 重載網頁,
不知道能不能解決.疑惑

wiseguy iT邦超人 1 級 ‧ 2012-08-31 21:36:34 檢舉

reload 是沒用的,記憶體繼續膨脹。而且監控系統畫面給它 reload 客戶會以為遭駭了。電影裡的 mission impossible 都是這麼演的。XD

0
總裁
iT邦好手 1 級 ‧ 2012-08-31 13:21:50

wiseguy提到:
Windows AP

+1
因為我沒寫過網頁程式...毆飛

0
bizpro
iT邦大師 1 級 ‧ 2012-08-31 14:44:01

您這是Memory Leak的問題吧? 是Event的Handler失聯了而無法被釋放嗎? 我看我的監控系統運作時, firefox的GC有在運作啊.

您的更新頻率是? 我可以試試看是否我的監控系統也會有這問題.

看更多先前的回應...收起先前的回應...
wiseguy iT邦超人 1 級 ‧ 2012-08-31 21:49:08 檢舉

很難說是Memory Leak的問題。因為通常說Memory Leak是指《有遺漏未回收的記憶體》,但我上面有說明,因為瀏覽器天生就不是用來擺長時間的,所以也很有可能是《programmer 故意不回收》,只等該 process 終結後就一了百了。所以在這樣的情況下,瀏覽器開發者是不會把它當做 bug 修正的。

您已經提到一個關鍵點:Event 的 Handler 如果是匿名函式,就很可能會 memory leak。我實驗的結果是:如果用完了不設為 null,那也會一直佔用著。如果匿名函式裡又曾建立新物件而沒設為 null 釋放,那 Handler 設為 null 也是無效的。這是 IE8 的結果。

comet 是以 long pulling 在運作,不見得有固定頻率。不過假如一直有資料在異動的話,是 0.5 秒 polling 一次。

bizpro iT邦大師 1 級 ‧ 2012-09-01 10:31:26 檢舉

當記憶體不斷耗用, 但並非程式所控, 不正是memory leak嗎? 可能是某些handler或物件被誤以為是回收再用, 但實際上是一直建新的, 由於設計誤解, 導致memory leak.

也許是EXT-JS的問題?
google: EXT-JS memory leak

wiseguy iT邦超人 1 級 ‧ 2012-09-01 17:50:54 檢舉

一般人寫 javascript 根本不會理會什麼記憶體釋放問題,甚至可能根本不知道 js 有 gc 這回事。programmer 並非故意不回收,只是在生命週期短暫的網頁上,不管是瀏覽器設計者或 js 設計者,都理所當然的認為記憶體耗用問題不是重點,拼命用就對了,因為沒多久網頁就會被關掉。

所以 EXT-JS、Socket.IO 這類知名的 Javascript Framework 都有嚴重的 memory leak 問題,檢視其程式碼,沒錯,就是拼命 new 物件,從不會去考慮什麼回收問題。開發者沒思考也不打算思考網頁要跑一天、一週、一個月這種 case 吧。

bizpro iT邦大師 1 級 ‧ 2012-09-02 07:19:09 檢舉

wiseguy提到:
一般人寫 javascript 根本不會理會什麼記憶體釋放問題,甚至可能根本不知道 js 有 gc 這回事。

是這樣喔, 難道都沒學過C? Java?之類的語言? 我之前寫JEE系統, 即使JEE對物件的生命週期設計十分嚴謹, 每一個物件用完之後, 也不管是否會自動被回收, 都會null掉, 呼叫, 迴圈, 或遞迴時, 都反覆檢查物件的生命週期, 生怕一個不注意, 系統就呆死了. 看來, EXT-JS不是穩定的產品?

wiseguy iT邦超人 1 級 ‧ 2012-09-02 12:39:17 檢舉

喔!我想 bizpro 應該是沒有寫過 Javascript 等動態網頁程式。這麼說沒有任何批判貶抑的意思,只是說明如果您有寫過,應該就明白我上面的說法。
通常 Javascript 程式生命期是很短的,就跟 DOS/Windows 裡的 .bat 批次檔一樣,很快地跑過去就整個結束了,短到不會有人關心 bat 檔裡面有沒有指令會造成 memory leak 的問題。但是假如真的有問題,那麼就會在它跑很久很久的時候,問題就會放大、就會影響到穩定性了。
C/Java 都是通用型程式語言,跟網頁用的 Javascript 是截然不同的兩個世界。只能說 Javascript 有它天生的限制,而我們想克服的,就是在這限制下,儘量符合客戶的需求。

wiseguy iT邦超人 1 級 ‧ 2012-09-02 12:47:44 檢舉

EXT-JS 是很知名的 Javascript Framework,但是它也一樣有問題,就證明了我所說的,沒有人會關心 Javascript 跑很久很久的 case。因為瀏覽器天生就不是用來跑很久很久的網頁。所以您說《EXT-JS不是穩定的產品》,就像是說《法拉利沒辦法溯溪》一樣。因為 EXT-JS 不關注穩定,它關注的是快速開發。穩定會在大部份短暫的執行時間內被忽略不計。
講白話一點就是,EXT-JS 的設計者認為還沒到讓它當掉的時間,user 早就已經關掉網頁了,所以譬如《它跑三天就會當掉》這種問題,設計者是一點都不關心的。

bizpro iT邦大師 1 級 ‧ 2012-09-03 16:06:26 檢舉

是不是寫過Javascript不是重點, 而我已不寫程式了, 程式的語法都差不多, 就像我沒氣力去學PHP了, 但是我還是修正了某一個開源監控系統的某些PHP的關鍵錯誤. 也許Vaadin 7.0的到來會讓我有動機再去寫系統. 不過, 謝謝您的指教.

程式的法則是一樣的: 不因善小而不為. 所謂的善, 是任何可以使系統穩定的程式, 有可能一個小善像是堵住荷蘭堤防的小洞, 卻堵住了未來的大災難. 很難相信不去處理memory leak的根本問題, 任何的workaround都像貼膏藥一樣.

bizpro iT邦大師 1 級 ‧ 2012-09-03 16:08:09 檢舉

wiseguy提到:
講白話一點就是,EXT-JS 的設計者認為還沒到讓它當掉的時間,user 早就已經關掉網頁了,所以譬如《它跑三天就會當掉》這種問題,設計者是一點都不關心的。

如果EXT-JS是如此的弱的話, 為何您還要用?

wiseguy iT邦超人 1 級 ‧ 2012-09-10 11:39:40 檢舉

因為 EXT-JS 百利而只有這一壞 (mem leak 會導致長時間運作下 crash)。
而且在 99.9% 的 case 中,這一壞是幾乎沒機會發生的。
我會貼出這個問題,就是因為中了這 0.1% 的發生機率,所以才有研究的價值囉~

0
海綿寶寶
iT邦大神 1 級 ‧ 2012-08-31 15:17:55

改成傳統寫法
定時更新網頁

謎之音:畫面不時「閃」一下,程式才像在正常執行
逃跑

不是股票即時行情
應該沒有人會一直盯著螢幕看吧
汗

看更多先前的回應...收起先前的回應...
總裁 iT邦好手 1 級 ‧ 2012-08-31 15:59:33 檢舉

我以前寫的監控程式都沒畫面的,出事再哇哇叫就好了...

ted99tw iT邦高手 1 級 ‧ 2012-08-31 16:19:36 檢舉

cdfu提到:
出事再哇哇叫就好了...

我都是等臭蟲鑽出來,程式掛掉後幾天才被告知滴.....失神

我以前根本沒寫監控程式
都是採用「人工智慧主動式偵測回報系統」

運作原理很簡單
每當系統掛掉
最早發現的人會通知最急的那個人
然後再來向我回報
哈哈哈哈哈哈

wiseguy iT邦超人 1 級 ‧ 2012-08-31 21:52:06 檢舉

本來實際上線應該是沒人會一直盯著螢幕看才對。只可惜驗收的時候會 ...落寞

0
fillano
iT邦超人 1 級 ‧ 2012-08-31 15:46:08

https://developers.google.com/chrome-developer-tools/docs/heap-profiling

Chrome的開發者工具,可以找出已經從dom tree被detach但是還無法釋放的元素,然後參考這些資訊看要怎麼修改程式。

wiseguy iT邦超人 1 級 ‧ 2012-08-31 21:58:08 檢舉

感謝 fillano 大大的資訊,的確用這個找到不少遺漏的地方。不過如果是 EXT-JS 本身的問題,還真困擾改了之後,下一版也許還要來一次 ... 搖頭

fillano iT邦超人 1 級 ‧ 2012-09-01 08:09:37 檢舉

extjs喔...這就傷腦筋XD

0
Ken(Bigcandy)
iT邦大師 1 級 ‧ 2012-08-31 20:51:39

我也支持AP+1

超討厭到處都在用瀏覽器!!

除了免安裝軟體(爛藉口,外面一對可攜軟體不是嗎?)
或是所謂跨平台...

奇怪ㄟ,不就畫面顯示而已,其中一台電腦來監控,另外一台抓資料呈現到WEB上
這樣不是很簡單嗎?
不過,我不會寫程式,以上都只是隨口縮縮.....

看更多先前的回應...收起先前的回應...
ted99tw iT邦高手 1 級 ‧ 2012-08-31 21:38:37 檢舉

iT邦幫忙MVPbigcandy提到:
我也支持AP+1

現在老闆喜歡用移動裝置來“監控”公司一切,若用AP,那得要波到:iOS,Android,Windows Phone,Symbian,BlackBerry....族多不及備載~~Orz

wiseguy iT邦超人 1 級 ‧ 2012-08-31 21:55:09 檢舉

泰大說得沒錯。用 AP 就是有這種困擾,要寫好多套。
但 Web 又得看瀏覽器吃飯,真是《有一好、沒兩好》... 嘆氣

ted99tw iT邦高手 1 級 ‧ 2012-09-01 09:34:20 檢舉

wiseguy提到:
但 Web 又得看瀏覽器吃飯,真是《有一好、沒兩好》...

所幸Web還有W3C業界標準,瀏覽器間的差異(如:Firefox vs IE)遠小於手持裝置間的源溝(如:iOS-Objective C/Android-Java)。

而且瀏覽器還有JavaScript天王與全球各地怪咖加持,生猛程度完全不輸AP。

或許糖叔擔心的是瀏覽器方便之餘的資安隱憂?

資安我比較不單心,憑證、https、VPN,應該都可以吧,不過意外總是難免,就掠過

我想,瀏覽器端只抓Web Server來自監控Server的資料,是否可行?
差別在於非即時資料,不要定時刷新、不要太美觀的版型設計、不要flash、不要圖片,要什麼資料,就選擇+確認之後才會抓到Web Server並呈現給瀏覽者。

ted99tw iT邦高手 1 級 ‧ 2012-09-01 15:45:17 檢舉

wiseguy提到:
所以網頁在登入、進到監控頁面之後就不再換頁,持續跑AJAX做監控資料的更新顯示 .... 直到天荒地老。

要什麼資料,就選擇+確認之後才會.....

如果是這樣靜態作法,應不會有記憶體飆高之苦,問題是“表面不換頁,背景跑AJAX”,乍看之下頁面只有幾個數字或圖表在變,實則記憶體一直allocate卻釋放不掉,結果不是瀏覽器慢到爆,不然就是系統直接死給你看....

另一方面,需長時間使用的AP,不論是Windows或手持式裝置,GC(Garbage Collection)可說是programmer基本功,該null的null,該D的D,GC才能充分回收記憶體,AP跑再久都不怕。

瀏覽器不是沒GC,但不知怎地,威力就沒那麼強,難道是天生DNA使然?

wiseguy iT邦超人 1 級 ‧ 2012-09-01 17:59:03 檢舉

bigcandy 大大說的一連串《不要 ...》我都試過了。但遺憾的是《抓資料》這個動作 (polling) 就會讓記憶體升高,只不過越單純的網頁,升高速度越慢而已。

但回到現實面,老闆、客戶不可能會接受不要太美觀的版型設計、不要flash、不要圖片 ... 這種頁面,因為這是要賣的產品,超炫的畫面是影響售價的重要因素。嘆氣

0
ted99tw
iT邦高手 1 級 ‧ 2012-09-01 09:40:30

瀏覽器的吃記憶體問題的確讓人頭大....

我開一個Firefox所造成的系統lag,絕不亞於開一個VM....Orz

wiseguy iT邦超人 1 級 ‧ 2012-09-01 18:03:25 檢舉

我主要使用的瀏覽器是 Firefox,但越改版越囧 ...
雖然記憶體耗用減低了,不過當掉率也提高了 ...
什麼都不幹,光開著都會當掉,這點就比 IE 爛到掉渣 ...

0
何必問
iT邦好手 1 級 ‧ 2012-09-01 23:40:53

所知
windows 有出empty.exe工具
http://www.microsoft.com/en-us/download/details.aspx?id=17657
XP / 7 / vista/ 2003 可用
主要是清除使用記憶體

見解若力猶未逮之處
請見諒末見怪

0
Ken(Bigcandy)
iT邦大師 1 級 ‧ 2012-09-02 03:38:47

Code Man~(Coder)帥哥們........

自己寫一套瀏覽器呢!?逃跑逃跑

wiseguy iT邦超人 1 級 ‧ 2012-09-02 12:25:41 檢舉

哈哈 ... bigcandy 大大,您別拿我們 RD 窮開心了 汗
我們被允許的解決時間只有一週不到,要自己寫一套瀏覽器的話,可能跳槽到 Mozilla 基金會比較快 ...XD
而且它的問題跟 AP 是一樣的:必須要部署到各種平台上。所以 bigcandy 大大這個解決方案,小弟只能先謝過,等到要離職前,就會呈報給長官們參考了。哈哈

唉,這部份我只能說,不但力有未逮,個人沒興趣碰,也常常覺得寫程式真的好難

敬佩你們能玩弄Code......哈哈

ted99tw iT邦高手 1 級 ‧ 2012-09-02 13:05:33 檢舉

bigcandy提到:
敬佩你們能玩弄Code......

其實大家更敬佩糖叔出入A﹣Z女,還能全身而退.....不要扁我,我自K先...毆飛

0
recca0120
iT邦新手 5 級 ‧ 2016-02-25 19:25:39

小弟之前有過類似的經驗,
也是用extjs2.x版!
也確實是因為memory leak的問題讓人很頭痛
要寫的功能不是監視器而是KTV

當時的解決方案是利用
JAVA+SWT+XULRUNNER來架構browser
(xurlrunner可以透過設定檔來開啟javascript的jit功能,及一些校調設定)

然後必須得很注意javascript的circular references

頁面更新的會更新的原件再執行一次
document.getElementById('#xxx').innerHTML = ""
(這個動作對extjs的釋放記憶體有一定的效用)

javascript的function的寫法變成

&lt;pre class="c" name="code">
function test() {
    var a = "a";

    try {
        return a;
    } catch (e) {

    } finally {
       a = null;
       delete a;
    }
}

利用finally來進行一次強制釋放記憶體

做了這些事情去監看記憶體的使用量
就不會一直節節上升
執行狀況大約一周沒問題(是不是能到一年以上就不得而知了)

再補充狀況,當時的機器環境之惡劣
系統為
cpu: 1.5g (哪牌的忘記了,上網查的實際時脈大約800mhz)
ram: 2g
hd: 2g
os: xpe embedded

我要留言

立即登入留言