ASP. NET 페이지 최적화, 불 러 오 는 속도 향상
                                            
 34985 단어  asp.net
                    
namespace ASPNETCode.HttpModules
{
    public class CommonModule : IHttpModule
    {
        public void Init(HttpApplication application)
        {
            application.BeginRequest += Application_BeginRequest;
        }
        private void Application_BeginRequest(object sender, EventArgs e)
        {
            var context = HttpContext.Current;
            var request = context.Request;
            var url = request.RawUrl;
            var response = context.Response;
            var path = GetPath(url);
            var file = new FileInfo(path);
            if (DateTime.Now.Subtract(file.LastWriteTime).TotalDays < 7)
            {
                response.TransmitFile(path);
                response.End();
                return;
            }
            try
            {
                var stream = file.OpenWrite();
                response.Filter = new CommonFilter(response.Filter, stream);
            }
            catch (Exception)
            {
                //Log.Insert("");
            }
        }
        public void Dispose()
        {
        }
        private static string GetPath(string url)
        {
            var hash = Hash(url);
            string fold = HttpContext.Current.Server.MapPath("~/Temp/");
            return string.Concat(fold, hash);
        }
        private static string Hash(string url)
        {
            url = url.ToUpperInvariant();
            var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            var bs = md5.ComputeHash(Encoding.ASCII.GetBytes(url));
            var s = new StringBuilder();
            foreach (var b in bs)
            {
                s.Append(b.ToString("x2").ToLower());
            }
            return s.ToString();
        }
    }
}  2. 페이지 GZIP 압축 페이지 GZIP 압축 은 거의 모든 편 에서 고성능 WEB 프로그램 을 설명 하 는 몇 가지 방법 중 하나 이다. GZIP 압축 을 사용 하면 서버 가 보 내 는 바이트 수 를 낮 출 수 있 고 고객 에 게 웹 페이지 의 속도 가 빠 르 고 대역 폭 에 대한 사용 상황 도 줄 일 수 있 기 때문이다.물론 클 라 이언 트 의 브 라 우 저가 지원 하 는 지 여부 도 존재 한다.따라서 우리 가 해 야 할 일 은 클 라 이언 트 가 GZIP 을 지원 하면 GZIP 압축 된 내용 을 보 내 고 지원 하지 않 으 면 정적 파일 의 내용 을 직접 보 내 는 것 입 니 다.다행히 현대 브 라 우 저 IE 6.7.8.0, 파이 어 폭 스 등 은 GZIP 을 지원 한다.이 기능 을 실현 하기 위해 서 는 위의 application 을 고 쳐 써 야 합 니 다.BeginRequest 이벤트:
private void Application_BeginRequest(object sender, EventArgs e)
{
    var context = HttpContext.Current;
    var request = context.Request;
    var url = request.RawUrl;
    var response = context.Response;
    var path = GetPath(url);
    var file = new FileInfo(path);
    //       
    ResponseCompressionType compressionType = this.GetCompressionMode(request);
    if (compressionType != ResponseCompressionType.None)
    {
        response.AppendHeader("Content-Encoding", compressionType.ToString().ToLower());
        if (compressionType == ResponseCompressionType.GZip)
        {
            response.Filter = new GZipStream(response.Filter, CompressionMode.Compress);
        }
        else
        {
            response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress);
        }
    }
    if (DateTime.Now.Subtract(file.LastWriteTime).TotalMinutes < 5)
    {
        response.TransmitFile(path);
        response.End();
        return;
    }
    try
    {
        var stream = file.OpenWrite();
        response.Filter = new CommonFilter(response.Filter, stream);
    }
    catch (Exception)
    {
        //Log.Insert("");
    }
}
private ResponseCompressionType GetCompressionMode(HttpRequest request)
{
    string acceptEncoding = request.Headers["Accept-Encoding"];
    if (string.IsNullOrEmpty(acceptEncoding))
        return ResponseCompressionType.None;
    acceptEncoding = acceptEncoding.ToUpperInvariant();
    if (acceptEncoding.Contains("GZIP"))
        return ResponseCompressionType.GZip;
    else if (acceptEncoding.Contains("DEFLATE"))
        return ResponseCompressionType.Deflate;
    else
        return ResponseCompressionType.None;
}
private enum ResponseCompressionType
{
    None,
    GZip,
    Deflate
}  3. OutputCache 프로 그래 밍 방식 으로 페이지 캐 시 를 출력 합 니 다. ASP. 내 장 된 OutputCache 캐 시 는 내용 을 세 곳 에 캐 시 할 수 있 습 니 다. 웹 서버, 프 록 시 서버 와 브 라 우 저 입 니 다.사용자 가 OutputCache 로 설 정 된 페이지 에 접근 할 때 ASP. NET 은 MSIL 이후 에 결 과 를 output cache 캐 시 에 기록 한 다음 브 라 우 저 에 보 냅 니 다. 사용자 가 같은 경로 의 페이지 에 접근 할 때 ASP. NET 은. aspx 컴 파일 및 MSIL 을 실행 하 는 과정 을 거치 지 않 고 Cache 의 내용 을 직접 보 냅 니 다. 따라서 프로그램 자체 의 효율 이 향상 되 지 않 았 지만,하지만 페이지 불 러 오 는 속 도 는 향상 되 었 다.이 기능 을 실현 하기 위해 서, 우 리 는 위의 응용 프로그램 을 계속 고 쳐 씁 니 다BeginRequest 이벤트, TransmitFile 이후 이 경로 의 페이지 를 OutputCache 프로 그래 밍 방식 으로 캐 시 합 니 다.
private void Application_BeginRequest(object sender, EventArgs e)
{
    if (DateTime.Now.Subtract(file.LastWriteTime).TotalMinutes < 5)
    {
        response.TransmitFile(path);
        //    OutputCache    ,       
        response.Cache.SetExpires(DateTime.Now.AddMinutes(5));
        response.Cache.SetCacheability(HttpCacheability.Public);
        response.End();
        return;
    }
}  4. CommonFilter 류 필터 ViewState, 필터 Naming Container, 공백 문자열, 그리고 디스크 를 생 성 하 는 캐 시 파일 을 실현 합 니 다. response. Filter 의 Stream 대상 을 CommonFilter 류 에 전달 합 니 다. 우선, 우 리 는 먼저 Stream 의 Write 방법 으로 디스크 의 캐 시 파일 을 생 성 합 니 다. 코드 는 다음 과 같 습 니 다. 이 코드 에서 구조 함수, Write 방법 만 초기 화 합 니 다.Close 방식 은 유용 합 니 다. 그 중에서 FileStream 필드 는 정적 파일 을 만 드 는 작업 대상 입 니 다.
namespace ASPNETCode.HttpModules
{
    public class CommonFilter : Stream
    {
        private readonly Stream _responseStream;
        private readonly FileStream _cacheStream;
        public override bool CanRead
        {
            get
            {
                return false;
            }
        }
        public override bool CanSeek
        {
            get
            {
                return false;
            }
        }
        public override bool CanWrite
        {
            get
            {
                return _responseStream.CanWrite;
            }
        }
        public override long Length
        {
            get
            {
                throw new NotSupportedException();
            }
        }
        public override long Position
        {
            get
            {
                throw new NotSupportedException();
            }
            set
            {
                throw new NotSupportedException();
            }
        }
        public CommonFilter(Stream responseStream, FileStream stream)
        {
            _responseStream = responseStream;
            _cacheStream = stream;
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException();
        }
        public override void SetLength(long length)
        {
            throw new NotSupportedException();
        }
        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }
        public override void Flush()
        {
            _responseStream.Flush();
            _cacheStream.Flush();
        }
        public override void Write(byte[] buffer, int offset, int count)
        {
            _cacheStream.Write(buffer, offset, count);
            _responseStream.Write(buffer, offset, count);
        }
        public override void Close()
        {
            _responseStream.Close();
            _cacheStream.Close();
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _responseStream.Dispose();
                _cacheStream.Dispose();
            }
        }
    }
}  그리고 우 리 는 정규 를 이용 하여 ViewState 를 완전히 삭제 합 니 다.
//   ViewState
private string ViewStateFilter(string strHTML)
{
    string matchString1 = "type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\"";
    string matchString2 = "type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\"";
    string matchString3 = "type=\"hidden\" name=\"__EVENTTARGET\" id=\"__EVENTTARGET\"";
    string matchString4 = "type=\"hidden\" name=\"__EVENTARGUMENT\" id=\"__EVENTARGUMENT\"";
    string positiveLookahead1 = "(?=.*(" + Regex.Escape(matchString1) + "))";
    string positiveLookahead2 = "(?=.*(" + Regex.Escape(matchString2) + "))";
    string positiveLookahead3 = "(?=.*(" + Regex.Escape(matchString3) + "))";
    string positiveLookahead4 = "(?=.*(" + Regex.Escape(matchString4) + "))";
    RegexOptions opt = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.Compiled;
    Regex[] arrRe = new Regex[] {
        new Regex("\\s*<div>" + positiveLookahead1 + "(.*?)</div>\\s*", opt),
        new Regex("\\s*<div>" + positiveLookahead2 + "(.*?)</div>\\s*", opt),
        new Regex("\\s*<div>" + positiveLookahead3 + "(.*?)</div>\\s*", opt),
        new Regex("\\s*<div>" + positiveLookahead3 + "(.*?)</div>\\s*", opt),
        new Regex("\\s*<div>" + positiveLookahead4 + "(.*?)</div>\\s*", opt)
    };
    foreach (Regex re in arrRe)
    {
        strHTML = re.Replace(strHTML, "");
    }
    return strHTML;
}  다음은 페이지 공백 을 삭제 하 는 방법 입 니 다.
//     
private Regex tabsRe = new Regex("\\t", RegexOptions.Compiled | RegexOptions.Multiline);
private Regex carriageReturnRe = new Regex(">\\r\
<", RegexOptions.Compiled | RegexOptions.Multiline);
private Regex carriageReturnSafeRe = new Regex("\\r\
", RegexOptions.Compiled | RegexOptions.Multiline);
private Regex multipleSpaces = new Regex("  ", RegexOptions.Compiled | RegexOptions.Multiline);
private Regex spaceBetweenTags = new Regex(">\\s<", RegexOptions.Compiled | RegexOptions.Multiline);
private string WhitespaceFilter(string html)
{
    html = tabsRe.Replace(html, string.Empty);
    html = carriageReturnRe.Replace(html, "><");
    html = carriageReturnSafeRe.Replace(html, " ");
    while (multipleSpaces.IsMatch(html))
        html = multipleSpaces.Replace(html, " ");
    html = spaceBetweenTags.Replace(html, "><");
    html = html.Replace("//<![CDATA[", "");
    html = html.Replace("//]]>", "");
    return html;
}  다음은 ASP. NET 컨트롤 의 쓰레기 UniqueID 이름 을 삭제 하 는 방법 입 니 다.
//   NamingContainer
private string NamingContainerFilter(string html)
{
    RegexOptions opt =
        RegexOptions.IgnoreCase |
        RegexOptions.Singleline |
        RegexOptions.CultureInvariant |
        RegexOptions.Compiled;
    Regex re = new Regex("( name=\")(?=.*(" + Regex.Escape("$") + "))([^\"]+?)(\")", opt);
    html = re.Replace(html, new MatchEvaluator(delegate(Match m)
    {
        int lastDollarSignIndex = m.Value.LastIndexOf('$');
        if (lastDollarSignIndex >= 0)
        {
            return m.Groups[1].Value + m.Value.Substring(lastDollarSignIndex + 1);
        }
        else
        {
            return m.Value;
        }
    }));
    return html;
}  마지막 으로, 우 리 는 상기 여과 방법 을 CommonFilter 류 의 Write 방법 에 통합 시 켰 다.
public override void Write(byte[] buffer, int offset, int count)
{
    //   buffer    
    byte[] data = new byte[count];
    Buffer.BlockCopy(buffer, offset, data, 0, count);
    string html = System.Text.Encoding.UTF8.GetString(buffer);
    //         
    html = NamingContainerFilter(html);
    html = ViewStateFilter(html);
    html = WhitespaceFilter(html);
    byte[] outdata = System.Text.Encoding.UTF8.GetBytes(html);
    //     
    _cacheStream.Write(outdata, 0, outdata.GetLength(0));
    _responseStream.Write(outdata, 0, outdata.GetLength(0));
}  5. 캐 시 파 괴 는 상기 프로그램의 실현 을 거 쳐 웹 페이지 는 클 라 이언 트 에 고속 캐 시 되 었 습 니 다. 만약 에 사용자 가 사이트 가 캐 시 된 페이지 를 방문 하면 페이지 는 0 요청 속도 로 페이지 를 불 러 옵 니 다.그러나 배경 에 일부 데 이 터 를 업데이트 하면 프론트 사용 자 는 최신 데 이 터 를 제때에 볼 수 없 기 때문에 이러한 상황 을 바 꾸 려 면 캐 시 를 파괴 해 야 합 니 다.위의 프로그램 에 따 르 면 캐 시 를 파괴 하려 면 2 단계 만 해 야 합 니 다. 서버 에 있 는 임시 파일 을 업데이트 하고 OutputCache 가 지나 간 페이지 를 삭제 합 니 다.서버 에 있 는 파일 을 업데이트 하려 면 이 파일 만 삭제 하면 됩 니 다. 사용자 가 이 페이지 를 처음 방문 할 때 자동 으로 생 성 됩 니 다. 물론 프로그램 으로 먼저 삭제 한 후에 생 성 할 수도 있 습 니 다.
//     
foreach ( var file in Directory.GetFiles( HttpRuntime.AppDomainAppPath + "Temp" ) ) {
    File.Delete( file );
}  OutputCache 와 연 결 된 캐 시 항목 을 삭제 하려 면 코드 는 다음 과 같 습 니 다. 우 리 는 이 방법의 매개 변수 만 확보 해 야 합 니 다. 페이지 의 절대 경로 가 정확 하고 경 로 는 사용 할 수 없습니다.. / 이러한 상대 경 로 를 말 합 니 다.
//     
HttpResponse.RemoveOutputCacheItem( "/Default.aspx" );  최적화 가 끝나 지 않 았 습 니 다. 전 투 는 계속 되 고 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
작업 중 문제 해결 - (win 2003 asp. net) Session 과 페이지 전송 방법 으로 해결 방안 을 정상적으로 사용 할 수 없습니다.또한 F 는 처음에 우리 의 BP & IT 프로젝트 팀 이 Forms 폼 검증 을 사용 했다 고 판단 할 수 있 습 니 다. 페이지 를 뛰 어 넘 는 것 은http://hr.bingjun.cc/MyTask/MyTas...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.