把圖片塞進資料庫?別鬧了吧!

在某個專案裏,客戶提了個有趣的要求:

「因為伺服器是架在AWS的HA架構中,是多部server的架構,所以我們的專案在上傳的時候,要上傳到多部伺服器…」

嗯?當下我就有了個疑問:

「多伺服器難道沒有檔案同步的機制嗎?在有同步機制的伺服器群中,其實只要將網頁程式碼上傳到其中一部server,就會自動同步到其它備用伺服器了吧?」

客戶的IT部門代表居然斬釘截鐵地回答我「沒有」!並補充了一句「那些同步機制要另外架才有」!

當下我聽了之後的想法是:看起來你是負責server的,這些同步機制不是你應該要去設定的嗎?於是我忍不住多問了一句:

「如果後台上傳了一張圖片到目前服務的server,在沒有自動同步機制的情形下,其它server要如何取得這張圖片?」

那位IT回答:「可以把圖片存進資料庫裏…」

啥?這會不會太有趣了?圖片塞進資料庫並不是做不到,但客戶既然會把單一的網站拆成一組HTTP與DB分離、HTTP有負載平衡、DB有主備分流的伺服器群裏,目的不就是要降低單一伺服器的負擔?結果現在又要把圖片塞進資料庫?沒考慮效能的問題嗎?

我們先來分析一下圖片塞進資料庫的處理方式:

  1. 網頁上傳圖片檔案
  2. server端收到檔案後,以fread等方法讀取檔案內容
  3. 以字串的方式將圖片檔案內容寫入資料庫

當使用者以瀏覽器開啟圖片時,server端的處理程序則是這樣:

  1. server收到http request
  2. 查詢資料庫取得圖片檔案內容
  3. 賦予mime header,將圖片檔案內容字串轉回圖片格式,輸出給瀏覽器

以上的程序中,就把瀏覽器開啟圖片這段程序拿出來討論:以一張200k大小的圖片來說,http server在收到request的時候,要向db server作資料查詢,db server要透過網路將query結果傳送給http server,http server再將這張圖片透過網路傳送給瀏覽器。

像這樣單一張圖片,200k的流量看似還好,但如果一個網頁裏有5張這樣的圖片呢?如果同時有4千個使用者存取伺服器呢?

200k * 5張圖片 * 4000使用者 = 4G bytes =32G bits

以一張1G bps的網卡來說,32G的傳輸就要超過30秒,試問,誰能忍受開一個網頁要30秒?

再者,這一個網頁,要幾部負載平衡伺服器來服務這些網頁?又要多少部DB server來提供讀取?就只為了5張圖片?

實務上,還真的遇過很多案例像這樣捨本逐末的…明明只要裝個如Unison的cluster工具就搞定了,甚至寫個shell script來定期rsync一下,也不算太爛的處理,卻要迴避這些伺服器設定,選擇一個極低效能的解決方案?

針對這個問題,應該要把伺服器上的資料夾,設定好自動同步,當檔案上傳後,就可以自動複製到備用伺服器;如果預期會有極大流量,則應該導入CDN,將圖片、css、js等靜態檔案的存取流量轉向CDN伺服器,就能有效降低伺服器的負擔。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *