如果可能,您不應該將要提供的文件的全部內容存儲在內存中。相反,獲取數據的InputStream,並將數據分段複製到Servlet OutputStream。例如:
ServletOutputStream out = response.getOutputStream();
InputStream in = [ code to get source input stream ];
String mimeType = [ code to get mimetype of data to be served ];
byte[] bytes = new byte[FILEBUFFERSIZE];
int bytesRead;
response.setContentType(mimeType);
while ((bytesRead = in.read(bytes)) != -1) {
out.write(bytes, 0, bytesRead);
}
// do the following in a finally block:
in.close();
out.close();
我同意toby,你應該改爲「將它們指向S3 url」。
至於OOM異常,你確定它與提供圖像數據有關嗎?假設您的JVM有256MB的「額外」內存用於提供圖像數據。在Google的幫助下,「256MB/200KB」= 1310.對於2GB「額外」內存(這些日子裏非常合理的數量),可以支持超過10,000個併發客戶端。即便如此,1300個併發客戶端也是相當大的一部分。這是你經歷的負荷類型嗎?如果沒有,您可能需要在別處尋找OOM異常的原因。
編輯 - 關於:
在這種情況下,使用圖像可以包含敏感數據...
當我通過S3文檔幾個星期前看,我注意到,你可以生成可以連接到S3 URL的超時密鑰。所以,你不必在S3上向公衆開放這些文件。我對技術的理解是:
- 初始HTML頁面有下載鏈接到你的web應用下載鏈接
- 你的web應用程序生成包括到期的一個關鍵的S3 URL上
- 用戶點擊,可以說, 5分鐘。
- 使用步驟3中的URL發送HTTP重定向到客戶端。
- 用戶從S3下載文件。即使下載時間超過5分鐘,這也可以工作 - 一旦下載開始,它可以繼續完成。
嗯,由於沒有設置內容長度,所以servlet容器必須進行緩衝,因爲在流式傳輸任何數據之前需要設置內容長度頭。所以不知道你節省了多少內存? – 2012-02-01 15:54:36
彼得,如果你不能直接指向用戶的雲服務URL,並且你想設置內容長度頭,並且你不知道大小,並且你不能查詢雲服務的大小,那麼我猜你的最好的辦法是首先流到服務器上的臨時文件。當然,在將第一個字節發送到客戶端之前,在服務器上保存副本可能會導致用戶認爲請求失敗,具體取決於雲 - >服務器傳輸需要多長時間。 – 2012-02-13 03:55:37