詳解MongoDB實現(xiàn)存儲物理文件和SQUID加速
之前在閱讀MongoDB GFS文檔時,學(xué)習(xí)了它如何存儲物理文件(包括大文件)的方式。為了加深印象,專門寫了一個上傳文件存儲到Mongodb的示例。當(dāng)然后因為是存儲到文檔數(shù)據(jù)庫中,所以就不能用普通方式來訪問這些物理文件了,這里又專門寫了一個aspx頁面專門讀取這些文件(比如圖片或MP3等),所以下載示例之后會看到兩個頁面,一個是uploadfile.aspx(上傳),一個是getfile.aspx(從mongodb中把文件以流的方式讀出來)。當(dāng)然考慮到訪問速度,這里還引入了SQUID來進(jìn)行文件加速(當(dāng)前SQUID默認(rèn)只緩存靜態(tài)文件,所以這里要對ASPX頁面的輸出進(jìn)行一下設(shè)置,這些都會在本文中進(jìn)行介紹)
首先介紹一下開發(fā)環(huán)境,我使用的是VS2008+SP1 ,mongodb客戶端軟件用的是samus-mongodb(最新版本即可)
添加對下面名空間的引用
- using MongoDB;
- using MongoDB.GridFS;
下面是上傳文件的主要代碼:
uploadfile.aspx.cs
- HttpPostedFile myFile = FileUpload.PostedFile;
- int nFileLen = myFile.ContentLength;
- byte[] myData = new Byte[nFileLen];
- myFile.InputStream.Read(myData, 0, nFileLen);
- GridFile fs = new GridFile(DB, filesystem);
- Random random = new Random(unchecked((int)DateTime.Now.Ticks));
- string newfilename = string.Format("{0}{1}{2}", random.Next(1000, 99999),
- random.Next(1000, 99999), System.IO.Path.GetExtension(myFile.FileName));
- GridFileStream gfs = fs.Create(newfilename);
- gfs.Write(myData, 0, nFileLen);
- gfs.Close();
這里只是給上傳文件起個隨機(jī)名稱,這樣如果一切正常,就可以在數(shù)據(jù)庫中找到該文件了,如下圖:
下面看一下如何訪問上傳的物理文件getfile.aspx.cs(通過傳遞filename參數(shù),mongodb中相應(yīng)字段結(jié)構(gòu),如上圖):
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!string.IsNullOrEmpty(Request.QueryString["filename"]))
- {
- string filename = Request.QueryString["filename"];
- Init();
- String filesystem = "gfstream";
- GridFile fs = new GridFile(DB, filesystem);
- GridFileStream gfs = fs.OpenRead(filename);
- Byte[] buffer = new Byte[gfs.Length];
- HttpContext.Current.Response.AddHeader("Expires", DateTime.Now.AddDays(20).ToString("r"));
- HttpContext.Current.Response.AddHeader("Cache-Control", "public");
- // 需要讀的數(shù)據(jù)長度
- long dataToRead = gfs.Length;
- int length;
- while (dataToRead > 0)
- {
- // 檢查客戶端是否還處于連接狀態(tài)
- if (HttpContext.Current.Response.IsClientConnected)
- {
- length = gfs.Read(buffer, 0, 10000);
- HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
- HttpContext.Current.Response.Flush();
- buffer = new Byte[10000];
- dataToRead = dataToRead - length;
- }
- else
- {
- // 如果不再連接則跳出死循環(huán)
- dataToRead = -1;
- }
- }
- gfs.Dispose();
- HttpContext.Current.Response.End();
- }
- }
下面就是以列表的方式從mongodb中檢索文件列表的最終的運行效果:
盡管MONGODB的并發(fā)性能很不錯,但每次都去mongodb取的話也是有性能損耗的,特別是對于不經(jīng)常變化的物理文件,所以這里使用了SQUID來進(jìn)行文件緩存。當(dāng)前SQUID默認(rèn)只支持靜態(tài)文件,對于本示例中的ASPX頁面輸出的流信息來緩存還要進(jìn)行一下設(shè)置。
首先,如果在squid.conf文件中有如下行,需要用#進(jìn)行注釋(它會禁止緩存所有帶?的鏈接地址):
- hierarchy_stoplist cgi-bin ? \.php \.html
- acl QUERY urlpath_regex cgi-bin \? \.php \.html
- cache deny QUERY
這樣,再修改一下相應(yīng)的.aspx,并在Header中添加如下信息,即:
- HttpContext.Current.Response.AddHeader("Expires", DateTime.Now.AddDays(20).ToString("r"));
- HttpContext.Current.Response.AddHeader("Cache-Control", "public");
這樣SQUID就會忠實在根據(jù)該頭信息來CACHED相應(yīng)文件了。
當(dāng)然也可以用如下方式來讓指定那些文件aspx文件才會被SQUID CACHED:
- acl CACHABLE_PAGES urlpath_regex \getfile.aspx
- #允許cache上面的aspx頁面
- no_cache allow CACHABLE_PAGES
而下面一個acl匹配所有的動態(tài)頁面并禁止緩存所有aspx頁面
- #acl NONE_CACHABLE_PAGES urlpath_regex \? \.aspx
- #禁止cache其它的aspx頁面
- #no_cache deny NONE_CACHABLE_PAGES
下面幾行設(shè)置頁面cache的時長,第一行cache一天,第二行cache兩分鐘
- refresh_pattern ^http://10.0.4.114:1100/mongodbsample/getfile.aspx 1440 0% 1440 ignore-reload
- refresh_pattern ^http://10.0.4.114:1100/mongodbsample/getfile.aspx 2 0% 2 ignore-reload
如要SQUID配置正確的話,只要訪問SQUID所請求代理的站點(本文中為http://10.0.4.85:8989/mongodbspame/uploadfile.aspx),這里它就會到http://10.0.4.114:1100/mongodbspame/uploadfile.aspx去獲取頁面信息,同時對該頁面中的鏈接getfile.aspx文件均會進(jìn)行緩存,如下圖:
好了,今天的內(nèi)容就先到這里了,示例源碼及SQUID配置文件下載鏈接:/Files/daizhj/mongodbsample.rar
原文標(biāo)題:使用Mongodb存儲上傳物理文件并進(jìn)行SQUID加速(基于aspx頁面)
鏈接:http://www.cnblogs.com/daizhj/archive/2010/08/19/1803454.html
【編輯推薦】