作者mmis1000 (秋月戀楓)
看板PHP
標題[請益] php檔案快取問題
時間Wed Nov 27 02:17:18 2013
各位版友好
小弟最近再做一個自動伺服器狀態圖的小程式,
但發現每次都重新產生的話,cpu會吃很兇
所以就用檔案修改時間當判斷,加上快取
和用header產生304減少流量
可是卻發生了奇怪的狀況
出問題的區段
http://pastebin.com/MrT5ZdjW
完整code
http://goo.gl/b1mlg0
因為第一次產生時有時會傳輸不全導致破圖,
所以我在圖片產生完的第一次輸出,
並沒有加上更新快取紀錄的header
可是測試時卻發現,圖片還是被快取了
請問有人看得出是哪裡出錯嗎?
像是邏輯上的問題之類。
麻煩了
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.116.130.56
1F:→ danny8376:如果用Chrome測 沒關cache很正常 client端短時間cache 11/27 02:28
2F:→ danny8376:的行為是看瀏覽器高興的 你還是讓圖片一次成功比較實際 11/27 02:29
3F:→ mmis1000:並不是短時間快取,而是長時間快取,得按 ^ F5才能刷新 11/27 02:33
4F:→ mmis1000:不知道圖片不全是不是time out造成的 11/27 02:34
5F:→ danny8376:另外 要輸出檔案我會建議直接用readfile 11/27 02:34
6F:→ mmis1000:圖片只會產生一次,第二次傳的圖片跟第一次是一樣的 11/27 02:35
7F:→ danny8376:不過更要建議我會直接用x-sendfile之類的傳cache檔出去 11/27 02:35
8F:→ danny8376:可能真的是timeout問題吧 你可以試著增加timeout試試? 11/27 02:42
9F:→ mmis1000:剛用firefox開發者去看,明明不含last-modified 11/27 02:44
10F:→ mmis1000:If-Modified-Since 還是被更新了,不知道是不是bug... 11/27 02:44
11F:→ danny8376:這不是BUG Cache本來就不是沒Last-Modified就不能做 11/27 02:51
12F:→ mmis1000:那如果把時間標註為0,標為過期呢? 11/27 02:53
13F:→ danny8376:你還是確保圖片成功傳送比較實際... 11/27 02:57
14F:→ mmis1000:如果無法正確判斷header,連送304都會有問題啊... 11/27 03:01
15F:→ danny8376:反正剛剛試了下 我是沒遇過破圖啦 11/27 03:03
16F:→ danny8376:可能我伺服器太好了(X 11/27 03:03
17F:→ danny8376:我是比較建議你 可以直接PHP輸出到cache之後 11/27 03:04
18F:→ danny8376:直接用Location的方式redirect過去 11/27 03:04
19F:→ danny8376:你只要確定那張圖還能用 連要不要傳304都不用管 11/27 03:05
20F:→ danny8376:反正丟給HTTP Server自己判斷去 11/27 03:05
21F:→ danny8376:對了 不要再巧虎頭了www 11/27 03:06
22F:→ mmis1000:聽說那是firebug的bug,在chrome上測不出這種行為 11/27 03:06
23F:→ mmis1000:firebug好像會造成額外request,但卻又沒更新cache 11/27 03:07
24F:→ mmis1000:不直接重導向的理由是,要排程更新很麻煩 11/27 03:15
25F:→ mmis1000:而且會把code搞得很複雜,也不好處裡未被使用的圖 11/27 03:17
26F:→ danny8376:沒啊 對外使用php的連結 php裡再導去cache 11/27 03:17
27F:→ danny8376:這樣還是要先走過php 只是最後輸出改成location header 11/27 03:18
28F:→ mmis1000:是指header歐,我以為是mod_rewrite 11/27 03:22
29F:→ mmis1000:其實本來就只是暫時性的做法拉 11/27 03:23
30F:→ mmis1000:多人同時連線會讓更新用的socket_client出問題... 11/27 03:24
31F:→ danny8376:其實用rewrite也行www rewrite可以寫很複雜的www 11/27 03:26
32F:→ danny8376:我自己是用php放crontab去每分鐘跑一次更新資料 11/27 03:27
33F:→ danny8376:然後要顯示時才去資料庫撈回來給人看 11/27 03:27
35F:→ mmis1000:多了一次無參數request,而且無視快取狀態更新紀錄 11/27 04:05
36F:推 alog:基本上你要讓他圖片不要被快取,有個方式 11/27 06:11
37F:→ alog:你至少要輸出時的時候 Header 帶 Cache-Control 11/27 06:19
38F:→ alog:或伺服端控制圖片的 Header 11/27 06:19
39F:→ alog:至少都要有基本的 no-store no-cache private 11/27 06:19
40F:→ alog:另外就是圖片的快取設計要改變,不是 Request 進來才產生圖 11/27 06:20
41F:→ alog:而是你要用系統排程call你腳本 定時更新圖 11/27 06:21
42F:→ alog:這樣一來你的CPU占用的機會就會大幅縮小 11/27 06:21
43F:→ alog:再補充,輸出完圖,直接放在伺服端就可以了 11/27 06:23
44F:→ alog:直接讓apache or nginx 直接把圖抓出來輸出給使用者 11/27 06:23
45F:→ alog:不論是記憶消耗或CPU佔用度都會大大減低 11/27 06:24
46F:→ alog:另外就是在某種情況下,session_start 會影響到快取 11/27 06:24
47F:→ alog:因為他會提早告知browser或代理伺服器不要快取產生的網頁 11/27 06:25
48F:→ danny8376:session對cache不會有影響 除非中間夾了cache server 11/27 06:52
49F:→ danny8376:有檢查cookie差異來決定決定是否cache 11/27 06:53
50F:→ danny8376:不過這也不會影響到client端的cache行為 11/27 06:54
51F:→ danny8376:畢竟session_start唯一做的事只有再找不到SESSION ID時 11/27 06:55
52F:→ danny8376:隨機產生SESSION ID塞到Cookie裡而已 11/27 06:55
53F:推 alog:我印象走fastcgi就會,cache server是因為遵循http協定設計 11/27 06:55
54F:→ alog:你可以觀察 header 輸出,很有趣有開沒開有差 11/27 06:56
55F:→ alog:我印象php的session start原始碼會輸出 阻止cache的header 11/27 06:58
56F:→ alog:session本身機制設計,資料不該被任何東西cache到會強制要求 11/27 06:59
57F:→ alog:那些裝置或服務不能把資料給儲存跟共享 11/27 07:00
58F:→ alog:當然如果那些程式硬要不遵守快取也沒辦法 11/27 07:01
59F:→ MOONRAKER:不是有一個爛招是圖片名稱後面帶GET參數嗎 11/27 10:59
60F:→ MOONRAKER:例如這樣 x.jpg?t=38552120793 (用js隨便加一個亂數) 11/27 11:00
61F:→ danny8376:樓上沒看清楚啊www 他不是要"總是"不cache 11/27 11:35
62F:→ danny8376:而是PHP判定某種狀況下才不給cache 11/27 11:35
63F:→ MOONRAKER:OUCH~~ 11/27 11:55
64F:→ MOONRAKER:果然看了半天還是看不懂 :~( 11/27 11:56
65F:→ mmis1000:request進來才確認產生圖片的理由是 11/27 16:07
66F:→ mmis1000:因為圖片每次更新不一定都會有人看到,如果排程更新 11/27 16:08
67F:→ mmis1000:沒被使用到的圖片會很浪費資源 11/27 16:08
68F:→ mmis1000:而且也不好處裡打錯資料造成的無意義請求 11/27 16:09
69F:→ mmis1000:這個函式只是為了簡單處理參數/快取而做的 11/27 16:20
70F:→ mmis1000:加入一堆額外判斷實在有違本意 11/27 16:20
71F:推 alog:就評估你的成本吧 11/27 17:49
72F:→ alog:,我個人覺得如果要考量到伺服器的狀況 11/27 17:51
73F:→ alog:跟你的程式訴求做調整 11/27 17:52
74F:→ mmis1000:這就只是為demo而做,所以最低限度就是能正常運作 11/27 17:54
75F:→ mmis1000:不要造成額外無意義消耗 11/27 17:55
76F:推 alog:負載重一點 你的伺服器節點就產生圖這件事情佔掉頻寬跟cpu 11/27 17:55
77F:→ alog:哦,你覺得無意義就無意義吧,保重 11/27 17:57
78F:→ mmis1000:所以才有快取 本來就只能維持 請求數/消耗資源 的比例 11/27 17:58
79F:→ mmis1000:改變總請求數從來就不是我能決定的阿 11/27 17:59
80F:推 alog:伺服器有上百台嗎,我是不懂怎麼變用戶一個了 11/27 17:59
81F:→ alog:一張圖了,另外我怎麼知道你要弄demo而已,那我早就不回這篇 11/27 18:00
82F:→ mmis1000:那是demo阿,負載平衡...etc本來就不在考慮範圍 11/27 18:00
83F:→ alog:似乎你自己就有答案,你自己解吧,有問題去看http協定規則 11/27 18:01
84F:→ alog:不回了 11/27 18:01
85F:→ chrisQQ:這種需求一般都會在前端檔一台 varnish 之類的… 11/28 13:15
86F:→ danny8376:務實上確實放varnish比較簡單XDD 11/29 00:15