问题现象:

Asp.net Mvc站点部署在IIS上后,第一个用户第一次访问站点,都会比较慢,确切的说是访问站点的Action页面(即非静态页面,因为静态页面直接由IIS处理返回给用户即完成请求,而Action页面IIS要转交给Aspnet_Wp工作进程,进而涉及相关初始化操作,这些初始化操作是比较慢的。第二次访问站点就不需要再初始化了所以就快了)。

这种第一次访问慢的问题不仅发生在网站第一次部署启动,也发生在站点重启站点程序池回收(经测试,第一次部署启动初始化所用时间会多一些,然后是站点重启,然后是站点回收)。

1.站点重启包含手动重启和修改web.config配置、修改IIS上站点配置、更新站点bin目录的dll等引起的自动重启。如果你的站点是新上线的web或者会持续修改添加功能的web,那难免会更新dll导致重启。其它编译型语言(比如java)也是如此,更新了服务端组件,都难免要重启站点。这边会分享.net环境下如何优化此问题;

2.站点程序池回收是IIS建议的,本来默认是29小时回收一次。为什么要建议回收呢,大致可以这样理解:一个每日定时回收的机制就像是在发生轻微内存泄露或者其它拖累Worker进程的因素的情况下,刷新IIS的良药,站点回收即节省了资源又提高了稳定性。然而,自动回收后第一次访问慢的问题困扰了许多人,其实只要稍微设置就可以解决,即没有困扰也拥有了回收的优点。

问题解决:

1.先在IIS上设置相应应用程序池的“高级设置”(IIS版本要在8或8以上,要知道IIS10早已出来了,如果你在用IIS很低的版本,然后在报怨IIS,我...),如下图,这样设置后,回收只会发生在凌晨04:00:00

要确定有安装IIS应用程序初始化功能,如下图

2.在IIS上设置站点的“高级设置”,把【预加载已启用】设置为true。

设置完这两步,当站点(自动)回收时,访问站点也是秒开不受任何影响,它的原理是在回收时会保持站点持续运行,这样的回收可以理解为把旧的Worker内容平滑的移到新的Worker上,然后回收掉旧的Worker。但是要注意,回收会导致站点内存信息丢失,因此如果你的设计是把session放在内存,则就要设置永不自动回收,那只要在第1步的基础上把【特定时间】清空即可。不过我个人会建议你不要设计session放内存,你更新个dll导致站点重启,内存也是清空的,你不如把session放在memcache/redis中,如果你的系统还没用上这些,那你就用cookie代替session吧,cookie更灵活适用的场景也更多。

现在回收的问题完美解决了,接下来说说站点重启。站点重启肯定是要重新加载配置重新加载dll(不想重新加载dll的,看文章最后一段),初始化是免不了,默认重启后第一个用户第一次访问站点会触发初始化,那么我们可以在站点启动/重启时,系统自动发一个站点请求,让系统自己尝尝第一次访问慢的问题。

IIS站点启动时机自动请求站点

1.启动站点时触发的时机

创建一个类,继承自IProcessHostPreloadClient接口,其Preload方法就是启动站点时触发。然后在里面自动访问站点,如下代码:

   public class ApplicationPreload : System.Web.Hosting.IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
try
{
//自动请求的url,其中http://localhost:8001 最好配置在config中,这边只是演示。
string url = "http://localhost:8001/home2/about";
using (var webClient = new WebClient())
{
webClient.DownloadStringAsync(new Uri(url));//要异步请求
}
}
catch (Exception e)
{
MvcApplication.DoLogToTxt("Preload Error:" + e.Message);
}
}
}

2. 修改IIS配置文件,让IIS能识别到刚写的ApplicationPreload类

打开IIS配置文件:%WINDIR%\System32\inetsrv\config\applicationHost.config

<applicationPools>
<add name="MyAppWorkerProcess" managedRuntimeVersion="v4.0" startMode="AlwaysRunning" /> <!-- 上面我们在IIS程序池界面中有设置过startMode项为AlwaysRunning-->
</applicationPools> <!-- ... --> <sites>
<site name="MySite" id="1">
<application path="/" serviceAutoStartEnabled="true" serviceAutoStartProvider="ApplicationPreload" />
</site>
</sites> <serviceAutoStartProviders>
<add name="ApplicationPreload" type="WebApplication1.ApplicationPreload, WebApplication1" />
</serviceAutoStartProviders>

最后一个条目的type,其中WebApplication1.ApplicationPreload是应用程序中实现IProcessHostPreloadClient接口的类的全名,WebApplication1是程序集名称。

设置完这两步也就搞定了启动站点时自动访问站点。

探讨

在上面设置之前,我测试只更新站点部分dll,第一次访问需要1~4秒,测试的站点是含有CMS源码的站点,不算小了。之前有个面试官说他们公司站点更新一个dll,第一次访问需要10~30秒,甚至更久,这样正在访问站点的用户就要等待,然后一直在报怨IIS和.Net,想要投奔java的怀抱(这里不比较两种语言,它们各自有自己的优势),我问他是不是在Global.asax里Application_Start做了太多自己的初始化,要么有些初始化在用户访问到时处理负担分担出去,要么Application_Start异步处理初始化动作,但是他说这些自己的初始化都是用户访问前必须初始化好的。这...应该是自己系统设计不够好不能怪.Net吧,如果是用了七七八八的第三方组件,比如EF初始化慢,那就换成轻量级的Dapper呗,然后好好学习一下《N种提升Asp.Net Mvc性能的方法》,不要闭门造车。

(你们更新一个站点的dll,第一次访问需要多少秒呢?)

那么,在上面设置之后 ,如果更新站点dll后第一次访问需要1~4秒的情况下,系统自动帮你做了第一次访问,很可能正在访问的用户就不怎么察觉得出来站点有重启过。如果是高并发访问的大型网站,那就应该有负载均衡(IIS可以用NLB做负载均衡,或考虑CDN或DNS解析时就做负载均衡),应该有分布式等。

最后 ,如果你的站点是因为更新dll而导致站点重启,而且对此问题深恶痛绝,那么可以用.net的动态加载dll来解决,不是用AppDomain动态加载和卸载dll(这个太麻烦),而是用Assembly.LoadFile加载dll。比如Controller所在的dll是MvcA.dll,它引用了LibA.dll,当这两个dll都有修改时,如何让站点加载到这两个最新版本的dll。这个可以解决的,如果实际应用中需要此需求的人多(请回复评论),我会再整理分享出来。

IIS+Asp.Net Mvc必须知道的事(解决启动/重启/自动回收站点后第一次访问慢问题)的更多相关文章

  1. asp.net MVC webservice 报次错解决方法

    asp.net  MVC  webservice  报次错解决方法: 解决方法: 在 RouteConfig.cs public static void RegisterRoutes(RouteCol ...

  2. Nginx+IIS+asp.net mvc 实现负载均衡示例

    一.Nginx官网 http://nginx.org/ 二.下载并安装Nginx 下载地址:http://nginx.org/en/download.html 启动Nginx,启动成功的话可以在任务管 ...

  3. 用ASP.NET MVC仿站糗事百科

    废话就不多说,直接来操作,有些细节问题就不一一解说了(没有几天几夜都说不完),主意是想让大家看完知道大概这个框架是怎么搭建的就可以了 一. 新建一个解决方案,搭建三层架构,分别为: DAL层  .DL ...

  4. ASP.NET MVC搭建项目后台UI框架—11、自动加载下拉框查询

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 需求:在查询记录的时候,输入第一个字,就自动把以这个字开头的相关记录查找出来,输入2个字就过滤以这两个子开头的记录,依次类推. 突然要用到这 ...

  5. nojs iis asp.net mvc

    http://blogs.msdn.com/b/scott_hanselman/archive/2011/11/29/window-iis-node-js.aspx http://www.hansel ...

  6. IIS部署asp.net MVC 出现错误 403.14-Forbidden解决办法

    可能性一: <system.webServer>   <validationvalidateIntegratedModeConfiguration="false" ...

  7. IIS ASP.NET MVC 上传文件到NAS目录

    项目要求,网站用户上传的文件,存储到服务器挂接的NAS磁盘里,死活也写不进去,一直提示 System.IO.IOException: 指定的服务器无法运行请求的操作 阿里的客服也问过了, 一群只知道发 ...

  8. iis7 下配置 ASP.NET MVC 项目遇到的问题 (WIN7 64位 旗舰版 第一次配置站点)

    转自 https://www.cnblogs.com/Leo_wl/p/3866625.html,再次感谢 指定的目录或文件在 Web 服务器上不存在. URL 拼写错误. 某个自定义筛选器或模块(如 ...

  9. ASP.Net MVC——DotNetZip简单使用,解决文件压缩问题。

    准备工作: 在vs工具栏中找到NuGet 下载DotNetZip 现在就可以使用DotNetZip强大的类库了,在这里我给出一些简单的使用. public ActionResult Export() ...

随机推荐

  1. Socket通信时服务端无响应,客户端超时设置

    背景:在写一个客户端的socket程序,服务端没有返回消息,客户端一直在等待. 目标:我需要设置一个时间,如果超过这个时间客户端自动断开连接.最好是在服务端实现,客户端对我来说不可控.

  2. [LOJ] 分块九题 3

    https://loj.ac/problem/6279 区间修改,区间查询前驱. TLE无数,我觉得这代码最精髓的就是block=1000. 谜一样的1000. 两个启示: 块内可以维护数据结构,比如 ...

  3. Python自动化测试框架——概述

    #使用import import unittest #测试用例TestCase ''' 一个测试用例时一个完整的测试流程,包括了环境准备SetUp,测试执行Run,测试环境还原TearDown 一个测 ...

  4. BZOJ2726【SDOI2012】任务安排(斜率优化Dp+二分查找)

    由题目条件显然可以得到状态 f[i][j] 表示以 i 为结尾且 i 后作为断点,共做了 j 次分组的最小代价. 因此转移变得很显然:f[i][j]=min{f[k][j-1]+(s×j+sumT[i ...

  5. [转]Selenium-Webdriver系列Python版教程(1)————快速开始

    elenium的历史,selenium2与WebDriver的关系本文就不讲了,想了解的同学们百度一下就可以Ok.     本系列教程是以Selenium-WebDriver的Python版本,首先从 ...

  6. 一个抓取智联招聘数据并存入表格的python爬虫

    talk is cheap...show you the code..... import requests import lxml,time,os from bs4 import Beautiful ...

  7. Leetcode 315.计算右侧小于当前元素的个数

    计算右侧小于当前元素的个数 给定一个整数数组 nums,按要求返回一个新数组 counts.数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元 ...

  8. codeforces #299 div 2

    (总算是5题都做完了- -) 暂时做了4题,先放一下有时间做最后一题(当然如果我真的能做出的话...)(看了大神的代码总算是理解了E题,做完发现也没那么难,果然想出一个思路的过程对于我这种弱渣来说还是 ...

  9. [luoguP2129] L国的战斗续之多路出击(模拟 || 矩阵)

    传送门 1.模拟 easy #include <cstdio> #define N 500001 int n, m; int X[N], Y[N], x[N], y[N], a = 1, ...

  10. windows下的asp.net core开发及docker下的发布

    参照下面,搭建好开发环境.Docker及配置好Docker加速器 http://www.cnblogs.com/windchen/p/6257846.html 参照下面,将windows共享目录挂载到 ...