服务器硬盘中有 50GB 数据,全是图片
因为系统要求,所以使用 Response.TransmitFile 和 Response.WriteFile 来输出文件
这些图片的总的并发量 在 1.6 万左右
该怎么优化呢?求解啊
代码贴出来
Web.Config
<?xml version="1.0" encoding="UTF-8"?> <configuration> <configSections> <section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter" /> </configSections> <RewriterConfig> <Rules> <RewriterRule> <LookFor>^(?!/proxyCache)/(.*)$</LookFor> <SendTo> <![CDATA[~/proxyStatic.ashx/$1]]> </SendTo> </RewriterRule> </Rules> </RewriterConfig> <appSettings> <!--#反向代理设置 start--> <!--设置站点--> <add key="proxyDomain" value="http://i-1.xx.com/" /> <!--缓存文件夹--> <add key="proxyCacheFolder" value="/proxyCache" /> <!--设置不再判断缓存文件是否超时,直接从缓存读取--> <add key="proxyCacheDirectAccess" value="false" /> <!--#反向代理设置 end--> </appSettings> <system.webServer> <modules runAllManagedModulesForAllRequests="true"> <add type="URLRewriter.ModuleRewriter, URLRewriter" name="ModuleRewriter" /> </modules> <staticContent> <clientCache cacheControlMode="UseExpires" httpExpires="Thu, 31 Dec 2037 23:55:55 GMT" /> </staticContent> </system.webServer> <system.web> <customErrors mode="Off" /> <compilation debug="true" /> </system.web> </configuration>
proxyStatic.ashx
<%@ WebHandler Language="C#" Class="proxyStatic" %> using System; using System.Web; using System.Net; using System.IO; using System.Collections.Generic; using System.Configuration; public class proxyStatic : IHttpHandler { HttpResponse Response; HttpRequest Request; HttpApplicationState Application; HttpServerUtility Server; HttpContext Context; static string proxyCacheFolder = ConfigurationManager.AppSettings["proxyCacheFolder"]; static string proxyDomain = ConfigurationManager.AppSettings["proxyDomain"]; bool proxyCacheDirectAccess = ConfigurationManager.AppSettings["proxyCacheDirectAccess"] == "true"; string host = string.Empty; public void ProcessRequest(HttpContext context) { Context = context; Response = context.Response; Request = context.Request; Application = context.Application; Server = context.Server; EchoCache(); string path = context.Request.RawUrl; EchoData(path); } void EchoCache() { string date = Request.Headers.Get("If-Modified-Since"); if (date != null) { Response.StatusCode = 304; Response.StatusDescription = "from cache"; return; } DateTime expDate = new DateTime(2037, 12, 31, 23, 55, 55); Response.Cache.SetCacheability(HttpCacheability.Public); Response.Cache.SetExpires(expDate); Response.Cache.SetMaxAge(expDate - DateTime.Now); Response.Cache.SetLastModified(new DateTime(2000, 1, 1)); } static string GetMd5Str(byte[] data) { System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); string t2 = BitConverter.ToString(md5.ComputeHash(data), 4, 8); t2 = t2.Replace("-", ""); return t2; } static string[,] ContentTypes = { {".jpg","image/jpeg"}, {".png","image/png"}, {".gif","image/gif"}, {".bmp","application/x-bmp"}, {".jpeg","image/jpeg"} }; string GetContentType(string ext) { ext = ext.ToLower(); for (int i = 0; i < ContentTypes.Length; i++) { if (ContentTypes[i, 0] == ext) { return ContentTypes[i, 1]; } } return string.Empty; } void EchoData(string path) { string absCachePath = Server.MapPath(proxyCacheFolder + path); string ext = Path.GetExtension(absCachePath); Response.ContentType = GetContentType(ext); if (File.Exists(absCachePath)) { Response.WriteFile(absCachePath, true); //Response.TransmitFile(absCachePath); } else { //更新Cache File string ApplicationKey = "CacheList"; List<string> List = null; if (Application[ApplicationKey] == null) { Application.Lock(); Application[ApplicationKey] = List = new List<string>(1000); Application.UnLock(); } else { List = (List<string>)Application[ApplicationKey]; } //判断是否已有另一个进程正在更新Cache File if (List.Contains(path)) { WebClient wc = new WebClient(); byte[] buffer = wc.DownloadData(proxyDomain + path); wc.Dispose(); Response.BinaryWrite(buffer); } else { string folder = Path.GetDirectoryName(absCachePath); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } WebClient wc = new WebClient(); List.Add(path); wc.DownloadFile(proxyDomain + path, absCachePath); wc.Dispose(); List.Remove(path); Response.WriteFile(absCachePath, true); //Response.TransmitFile(absCachePath); } } } public bool IsReusable { get { return false; } } }
用缓存把读过的图片加载到内存中,Response.WriteFile 的时候直接从缓存中读取数据。
不行,基本没效果
@foxidea: 我的意思是说,你把图片读到内存缓存起来,以 byte[] 形式保存在缓存中。Response.Write(byte[])就行了,就不用 Response.WriteFile 再从磁盘去读。
@Launcher:
Response.WriteFile(absCachePath, true); 这句应该和你说的效果 是一样的,
蛋疼的事情是,并不是这个原因导致的,
后面我们找到原因是服务器提供商给我的带宽 不够
我们 买的是 1G 的 他给我吗的是 百兆的,蛋疼啊
@Launcher: 我再问下 ,Response.WriteFile("File",true)
这句话,是缓存到内存中,那它什么时候会 释放内存呢?
@foxidea: 我查了下此API,WriteFile 会缓存文件,如果你不设置 Cache Expires 等属性,它应该是用默认的缓存策略来管理已缓存的文件,一般来说是在一段时间没有访问后就释放。
如果是因为带宽问题,那么你的服务器应该比较空闲,因为它大部分时间在等待IO操作,而不会占用过多的CPU时间。