文件下载中遇到的二个现象,不知如何解释

    发个牢骚先:搞什么,新手就不能一天写两篇以上的新手区文章!新手歧视嘛。

    这篇文章是用来提问题的,所以你可能从中什么也学不到,如果浪费了你的时间,很抱歉。

    二个问题

1、为什么会url直接下载>>HTTPS时下载的速度>>HTTP时下载的速度

2、400M不到的文件,下载过程中inetinfo的虚拟内存居然达到了近2G,那时客户端才下了3M不到

    先描述下场景。这个页面负责文件下载,下载的文件在局域网的另一台机器上(download server),ASPX页面在web server上。在web上做了https,可以通过https或者http访问这个页面;局域网的速度10MB/s;下载的文件大小:363,895KB。

   web服务器配置


    最初的代码是把download server上的文件一股脑的读入内存,然后在传输到客户端。

 

监视了下整个下载过程

(1)任务管理器


(2)性能


 

我对上图的理解是,第一阶段,把远端的文件全部读入web服务器上的asp.net进程占用的内存中(文件363,895KB),在这期间CPU始终保持100%,CPU使用率之所以这么高,是由于局域网的10M速度造成(速度下降到1M时,CPU在60%上下)。

第二阶段,ASP.net的内存迅速上升(远高于文件实际大小),此时IIS进程也不甘人后,可用内存则迅速降低。在IIS的使用内存达到恒定后,客户端弹出保存对话框

第三阶段, 文件传输到客户端。cpu使用率下降,可用内存升高。

可以看出这段代码存在许多问题,尤其是在下载大文件时,ASP.net超出60%物理内存后会被回收,可用内存不够用,CPU 长时间100%。

附张局域网速度1M时的:

 

为了解决这些问题,试了一些方法,但都不成功。或许某人说的对,用纯.net的方案是无解的。一个的非纯.net解决方案是ISAPI Filters+HttpHandler,限于本人水平有限,写不来那个ISAPI Filters。

前话表述完了,开始说说自己遇到的几个问题

1、url直接下载>>HTTPS时下载的速度>>HTTP时下载的速度(Why)

看到别人为了解决耗内存,用了句Response.Flush()

用了下,帮助不大

 

(1)用HTTPS访问该页面时

客户端下载速度

 

性能


(2)用HTTP访问该页面时

客户端下载速度

 

性能

 


同样的代码在Https、Http访问时有不同的表现,这让我很诧异。1、下载速度差的离谱,即使是较快的https,也只有带宽的1/10;http更别提了,下了没几M,自己就停止传输了。CPU和速度还是有很大的关系,https时的持续100%,http时的5%不到。唯一的亮点是可用内存好多啊。

这里,我的问题就是为什么会url直接下载>>HTTPS时下载的速度>>HTTP时下载的速度

2、400M不到的文件,下载过程中inetinfo的虚拟内存居然达到了近2G,那时客户端才下了3M不到(Why)

换了个想法(从结果看很不成熟的想法)。开了个线程去取数据到内存里放着,主线程把这些数据传給客户端。

代码如下

ExpandedBlockStart.gif
using System;

namespace ComDownload
{
    
/// <summary>
    
/// ╕├└α▒ú┤µ┴╦byte╩²╫Θ╝░╞Σ╩²╫Θ╡─╘¬╦╪╕÷╩²
    
/// </summary>
    public class ComBytes
    {
        
private byte[] bytes;
        
private int size;
        
        
/// <summary>
        
/// ╣╣╘∞║»╩²
        
/// </summary>
        public ComBytes(byte[] pBytes,int pSize)
        {
            Bytes 
= pBytes;
            Size 
= pSize;
        }


        
/// <summary>
        
/// byte╩²╫Θ
        
/// </summary>
        public byte[] Bytes
        {
            
get
            {
                
return bytes;
            }
            
set
            {
                bytes 
= value;
            }
        }


        
/// <summary>
        
/// ╩²╫Θ╡─╘¬╦╪╕÷╩²
        
/// </summary>
        public int Size
        {
            
get
            {
                
return size;
            }
            
set
            {
                size 
= value;
            }
        }
    }
}
ExpandedBlockStart.gif
using System;

namespace ComDownload
{
    
/// <summary>
    
/// ╢╙┴╨╜╙┐┌
    
/// </summary>
    public interface IQueue
    {
        
/// <summary>
        
/// ┼╨╢╧╢╙┴╨╩╟╖±╥╤┬·
        
/// </summary>
        bool IsFull();

        
/// <summary>
        
/// ┼╨╢╧╢╙┴╨╩╟╖±╬¬┐╒
        
/// </summary>
        bool IsEmpty();

        
/// <summary>
        
/// ╟σ┐╒╢╙┴╨
        
/// </summary>
        void Clear();

        
/// <summary>
        
/// ╚δ╢╙
        
/// </summary>
        void In(object item);

        
/// <summary>
        
/// │÷╢╙
        
/// </summary>
        object Out();
    }

    
/// <summary>
    
/// ╤¡╗╖╦│╨≥╢╙┴╨
    
/// </summary>
    public class CycQueue : IQueue
    {  
        
//╤¡╗╖╦│╨≥╢╙┴╨╡─╚▌┴┐
        private int maxsize;
        
//┤µ┤ó╦│╨≥╢╙┴╨╓╨╡─╓╡
        private object[] data;
        
//╢╙═╖
        private int front;
        
//╢╙╬▓
        private int rear;


        
/// <summary>
        
/// ╣╣╘∞╞≈
        
/// </summary>
        public CycQueue(int size)
        { 
            data
=new object[size];
            Maxsize 
= size;
            front 
= rear = 0;
        }

        
/// <summary>
        
/// ╚▌┴┐╩⌠╨╘
        
/// </summary>
        public int Maxsize
        {
            
get 
            {
                
return maxsize;
            }
            
set
            {
                maxsize 
= value;
            }
        }

        
/// <summary>
        
/// ╟σ┐╒
        
/// </summary>
        public void Clear()
        {
            front 
= rear = -1;
        }

        
/// <summary>
        
/// ┼╨╢╧╢╙┴╨╩╟╖±╬¬┐╒
        
/// </summary>
        public bool IsEmpty()
        {
           
return front == rear;
        }


        
/// <summary>
        
/// ┼╨╢╧╢╙┴╨╩╟╖±╥╤┬·
        
/// </summary>
        public bool IsFull()
        {
            
return (rear + 1% Maxsize == front;
        }


        
/// <summary>
        
/// ╚δ╢╙
        
/// </summary>
        public void In(object item)
        {
            
//╥¬╘┌IsFull()┼╨╢╧╓«╟░╝╙╦°ú¼╢α╧▀│╠╡─│í║╧ú¼┐╔─▄╘┌┼╨╢╧IsFull()=false║≤ú¼
            
//╓┤╨╨╞Σ╦√╧▀│╠╡─In▓┘╫≈ú¼╒Γ╤∙╘∞│╔╒Γ╕÷╧▀│╠IsFull()=trueú¼
            
//╢°▓╗╩╟╓«╟░╡─false┴╦
            lock(this)
            {
                
if (IsFull())
                {
                    
//╢╙┴╨┬·ú¼╩▓├┤╥▓▓╗╫÷
                    return;
                }
                data[rear] 
= item;
                rear 
= (rear + 1% Maxsize;
            }
        }


        
/// <summary>
        
/// //│÷╢╙
        
/// </summary>
        public object Out()
        { 
            
object temp = null;
            
//╥¬╘┌IsEmpty()┼╨╢╧╓«╟░╝╙╦°ú¼╢α╧▀│╠╡─│í║╧ú¼┐╔─▄╘┌┼╨╢╧IsEmpty()=false║≤ú¼
            
//╓┤╨╨╞Σ╦√╧▀│╠╡─Out▓┘╫≈ú¼╒Γ╤∙╘∞│╔╒Γ╕÷╧▀│╠IsEmpty()=trueú¼
            
//╢°▓╗╩╟╓«╟░╡─false┴╦
            lock(this)
            {
                
if (IsEmpty())
                {
                    
return null;
                }
                temp 
= data[front];
                front 
= (front + 1% Maxsize;
            }
            
return temp;
        }
     }
}
ContractedBlock.gif ExpandedBlockStart.gif 队列成员
using System;

namespace ComDownload
{
    
/// <summary>
    
/// 该类保存了byte数组及其数组的元素个数
    
/// </summary>
    public class ComBytes
    {
        
private byte[] bytes;
        
private int size;
        
        
/// <summary>
        
/// 构造函数
        
/// </summary>
        public ComBytes(byte[] pBytes,int pSize)
        {
            Bytes 
= pBytes;
            Size 
= pSize;
        }


        
/// <summary>
        
/// byte数组
        
/// </summary>
        public byte[] Bytes
        {
            
get
            {
                
return bytes;
            }
            
set
            {
                bytes 
= value;
            }
        }


        
/// <summary>
        
/// 数组的元素个数
        
/// </summary>
        public int Size
        {
            
get
            {
                
return size;
            }
            
set
            {
                size 
= value;
            }
        }
    }
}

ComDownload.download process = null;
ContractedBlock.gif ExpandedBlockStart.gif 循环队列
using System;

namespace ComDownload
ExpandedBlockStart.gifContractedBlock.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
    
/// 队列接口
    
/// </summary>

    public interface IQueue
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 判断队列是否已满
        
/// </summary>

        bool IsFull();

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 判断队列是否为空
        
/// </summary>

        bool IsEmpty();

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 清空队列
        
/// </summary>

        void Clear();

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 入队
        
/// </summary>

        void In(object item);

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 出队
        
/// </summary>

        object Out();
    }


ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
    
/// 循环顺序队列
    
/// </summary>

    public class CycQueue : IQueue
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{  
        
//循环顺序队列的容量
        private int maxsize;
        
//存储顺序队列中的值
        private object[] data;
        
//队头
        private int front;
        
//队尾
        private int rear;


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 构造器
        
/// </summary>

        public CycQueue(int size)
ExpandedSubBlockStart.gifContractedSubBlock.gif        

            data
=new object[size];
            Maxsize 
= size;
            front 
= rear = 0;
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 容量属性
        
/// </summary>

        public int Maxsize
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get 
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return maxsize;
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                maxsize 
= value;
            }

        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 清空
        
/// </summary>

        public void Clear()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            front 
= rear = -1;
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 判断队列是否为空
        
/// </summary>

        public bool IsEmpty()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
           
return front == rear;
        }



ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 判断队列是否已满
        
/// </summary>

        public bool IsFull()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return (rear + 1% Maxsize == front;
        }



ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 入队
        
/// </summary>

        public void In(object item)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            
lock(this)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if (IsFull())
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    
//队列满,什么也不做
                    return;
                }

                data[rear] 
= item;
                rear 
= (rear + 1% Maxsize;
            }

        }



ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// //出队
        
/// </summary>

        public object Out()
ExpandedSubBlockStart.gifContractedSubBlock.gif        

            
object temp = null;

            
lock(this)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if (IsEmpty())
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    
return null;
                }

                temp 
= data[front];
                front 
= (front + 1% Maxsize;
            }

            
return temp;
        }

     }

}

            try             {


                process = new ComDownload.download(10240,"http://192.168.1.165:800/TestDownload/a.zip");                 process.Start();
ContractedBlock.gif ExpandedBlockStart.gif 下载类
using System;
using System.Threading;
using System.Net;
using System.IO;

namespace ComDownload
ExpandedBlockStart.gifContractedBlock.gif
{
    
public class download
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 下载完成
        
/// </summary>

        private bool mblnCompleted;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 文件的读操作完成
        
/// </summary>

        private bool mblnReadCompleted;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 每次传递的数组长度
        
/// </summary>

        private int mintpostlength;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 循环队列的容量
        
/// </summary>

        private const int mintMaxQueueSize = 1000;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 等待时间
        
/// </summary>

        private const int mintSleep = 5000;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 队列
        
/// </summary>

        private CycQueue queue = null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 文件URL
        
/// </summary>

        private string mstrUrl = null;
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 读文件的线程
        
/// </summary>

        private Thread getbytesThread = null;
        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 构造函数
        
/// </summary>
        
/// <param name="PostBytesLength">
        
/// 每次下载字节数长度
        
/// </param>
        
/// <param name="FileUrl">
        
/// 文件URL
        
/// </param>

        public download(int PostBytesLength,string FileUrl)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            mblnCompleted 
= false;
            mblnReadCompleted 
= false;
            mintpostlength 
= PostBytesLength;
            mstrUrl 
= FileUrl;
            queue 
= new CycQueue(mintMaxQueueSize);
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 清理
        
/// </summary>

        public void Close()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if(getbytesThread!=null)
                getbytesThread.Abort();
        }

        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 判断下载是否完成
        
/// </summary>

        public bool IsCompleted()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return mblnCompleted;
        }



ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 开始下载
        
/// </summary>

        public void Start()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            getbytesThread 
= new Thread(new ThreadStart(ReadBytes));
            getbytesThread.Start();
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 读取远程文件
        
/// </summary>

        private void ReadBytes()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            Stream readStream 
= null;
            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                HttpWebRequest request 
= (HttpWebRequest)WebRequest.Create(mstrUrl);
                HttpWebResponse response 
= (HttpWebResponse)request.GetResponse();
                readStream 
= response.GetResponseStream();
            
                
byte[] bytes = new byte[mintpostlength];
                
int intBytesRead = 0;
                ComBytes comBytes 
= null;
                
while ((intBytesRead = readStream.Read(bytes,0,mintpostlength)) > 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    
while(queue.IsFull())
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
{
                        Thread.Sleep(mintSleep);
                    }

                    comBytes 
= new ComBytes(bytes,intBytesRead);
                    queue.In(comBytes);
                }

                mblnReadCompleted 
= true;
            }

            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if(readStream!=null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    readStream.Close();
                }

            }

        }


        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 传输字节流
        
/// </summary>
        
/// <returns>ComBytes字节流</returns>

        public ComBytes GetBytes()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if(mblnReadCompleted && queue.IsEmpty())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                mblnCompleted 
= true;
                
return null;
            }



            
if(queue.IsEmpty())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Thread.Sleep(mintSleep);
                
return null;
            }


            
return (ComBytes)queue.Out();
        }


    }

}

                                 Response.ClearHeaders();


                Response.AppendHeader("Content-Disposition","attachment; filename=a.zip");                 Response.ContentType="application/octet-stream";
ContractedBlock.gif ExpandedBlockStart.gif 页面下载代码
ComDownload.download process = null;
            
try
ExpandedBlockStart.gifContractedBlock.gif            
{
                process 
= new ComDownload.download(10240,"http://localhost:800/TestDownload/a.zip");
                process.Start();
                
                Response.ClearHeaders();
                Response.AppendHeader(
"Content-Disposition","attachment; filename=a.zip");
                Response.ContentType
="application/octet-stream";
                ComBytes bytes 
= null;
                
while(!process.IsCompleted())
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    bytes 
= process.GetBytes();
                    
if(bytes == null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                    
{
                        
continue;
                    }

                    Response.OutputStream.Write(bytes.Bytes,
0,bytes.Size);
                    Response.Flush();
                }

            }

            
catch
ExpandedBlockStart.gifContractedBlock.gif            
{
            }

            
finally
ExpandedBlockStart.gifContractedBlock.gif            
{
                
if(process!=null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    process.Close();
                }

            }
                ComBytes bytes = null;                 while(!process.IsCompleted())                 {                     bytes = process.GetBytes();                     if(bytes == null)                     {                         continue;                     }                     Response.OutputStream.Write(bytes.Bytes,0,bytes.Size);                     Response.Flush();                 }             }             catch             {             }             finally             {                 if(process!=null)                 {                     process.Close();                 }             }
ComDownload.download process = null;
            
try
            {
                process 
= new ComDownload.download(10240,"http://localhost:800/TestDownload/a.zip");
                process.Start();
                
                Response.ClearHeaders();
                Response.AppendHeader(
"Content-Disposition","attachment; filename=a.zip");
                Response.ContentType
="application/octet-stream";
                ComBytes bytes 
= null;
                
while(!process.IsCompleted())
                {
                    bytes 
= process.GetBytes();
                    
if(bytes == null)
                    {
                        
continue;
                    }
                    Response.OutputStream.Write(bytes.Bytes,
0,bytes.Size);
                    Response.Flush();
                }
            }
            
catch
            {
            }
            
finally
            {
                
if(process!=null)
                {
                    process.Close();
                }
            }

 

这里依旧有url直接下载>>HTTPS时下载的速度>>HTTP时下载的速度的问题

(1)先看HTTPS

下载速度


任务管理器


(2)再看HTTP的



文件也才400M不到,为什么inetinfo的虚拟内存就占用了近2G?


参考:

Optimizing the Downloading of Large Files in ASP.NET 

转载于:https://www.cnblogs.com/wordmy/archive/2009/04/08/1431817.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值