首页 新闻 会员 周边 捐助

Response.TransmitFile 和 Response.WriteFile 频繁,导致服务器很慢很慢

0
悬赏园豆:10 [已关闭问题] 关闭于 2013-01-09 16:29

服务器硬盘中有 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;
        }
    }

}
fun5的主页 fun5 | 初学一级 | 园豆:4
提问于:2013-01-09 14:59
< >
分享
所有回答(1)
0

用缓存把读过的图片加载到内存中,Response.WriteFile 的时候直接从缓存中读取数据。

Launcher | 园豆:45050 (高人七级) | 2013-01-09 15:01

不行,基本没效果

支持(0) 反对(0) fun5 | 园豆:4 (初学一级) | 2013-01-09 17:33

@foxidea: 我的意思是说,你把图片读到内存缓存起来,以 byte[] 形式保存在缓存中。Response.Write(byte[])就行了,就不用 Response.WriteFile 再从磁盘去读。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-01-09 17:55

@Launcher: 

Response.WriteFile(absCachePath, true);  这句应该和你说的效果 是一样的,

蛋疼的事情是,并不是这个原因导致的,
后面我们找到原因是服务器提供商给我的带宽 不够
我们 买的是 1G 的 他给我吗的是 百兆的,蛋疼啊
支持(0) 反对(0) fun5 | 园豆:4 (初学一级) | 2013-01-10 13:03

@Launcher: 我再问下 ,Response.WriteFile("File",true)  

这句话,是缓存到内存中,那它什么时候会 释放内存呢?

支持(0) 反对(0) fun5 | 园豆:4 (初学一级) | 2013-01-10 14:39

@foxidea: 我查了下此API,WriteFile 会缓存文件,如果你不设置 Cache Expires 等属性,它应该是用默认的缓存策略来管理已缓存的文件,一般来说是在一段时间没有访问后就释放。

如果是因为带宽问题,那么你的服务器应该比较空闲,因为它大部分时间在等待IO操作,而不会占用过多的CPU时间。

支持(0) 反对(0) Launcher | 园豆:45050 (高人七级) | 2013-01-10 16:19
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册