[草稿]配置IIS支持10w并发

由于iis默认最多只能处理5000个并发请求,今天由于某种情况造成同时请求超过5000,从而报错 HTTP Error 503.2 - Service Unavailable

为了避免这样的错误,通过对IIS和OS的优化调整,让服务器从设置上支持10万个并发请求,示例以一台 40核-64GB-1200GB的物理机为例,具体设置如下:

适用的IIS版本:IIS 7.0, IIS 7.5, IIS 8.0, IIS 8.5
适用的OS版本:Windows Server 2008及2008 R2、Windows Server 2012

[TOC]

知识准备

工作线程数与队列长度

  • 最大工作进程数 相当于某医院开设了多少个服务窗口,它是IIS实际可以第一时间处理的请求数。

比如,工作线程数 = 100,假如10000个连接请求同时涌过来, 那么只有100个可以被处理,其余9900个进入等待队列等待,或者直接以503错误(服务器不可用)返回。

  • 队列长度 相当于某医院大厅的排队座位。除了IIS工作线程数可以第一时间进行处理外,其余的请求可以进入等待队列进行等待的数量。

比如:工作线程数 = 100,队列长度 = 5000,假如10000个连接请求同时涌过来,将有100个第一时间被处理,5000个等待,4900个以503返回。

  • 最大并发连接数 = 队列长度 + 工作线程数
#.场景1:
工作线程数 = 100
队列长度   = 5000
最大并发连接数 = 5000
那么10000个连接请求同时涌过来,将有100个第一时间被处理,4900个进入队列等待,5000个以503返回。

#.场景2:
工作线程数 = 100
队列长度   = 5000
最大并发连接数 = 10000
那么10000个连接请求同时涌过来,将有100个第一时间被处理,5000个进入队列等待,4900个以503返回。
  • 关于 最大工作进程数 的最佳实践:

  • 最大工作进程数,不要超过CPU核数;

  • 按照每个工作进程能承载30个并发的原则来确定应用程序池的最大工作进程数;
  • 每个工作进程大约会占用200M的物理内存,注意最大工作进程数与200M的乘积不要超过可用内存;
  • 队列长度,建议 = 最高并发用户 x 1.5,例如:最高2000并发,则设置队列长度3000(用户数*1.5);
  • 建议每次增加5个工作进程数的方式对最大工作进程数进行调整,调整完后对网站观察一段时间,如果依然无法满足要求,再继续增加5个工作进程数。

  • 针对不同规模的网站,推荐的设置如下:

场景 硬件配置 最大工作进程数 队列长度 最大并发连接数
小型网站(单台最高并发5h) 4核-8G 2(默认1) 1000(默认1000) 默认4294967295
中型网站(单台最高并发6k) 16核-16G 1-16,比如10 9000 默认4294967295
大型网站(单台最高并发2w) 24核-32G 20 65535 默认4294967295

网站性能指标

指标 正常 备注
首屏时间 小于3秒 3~5秒 大于5秒 反映用户打开页面速度的直观感受
可用性 大于95% 90~95% 小于90% 反映页面打开成功率,过低影响站点形象
DNS 小于0.18秒 0.18~0.3秒 大于0.3秒 DNS解析时间,用户访问页面的第一步
建立连接时间 小于0.15秒 0.15~0.3秒 大于0.3秒 浏览器和WEB服务器建立TCP/IP连接的消耗时间
重定向时间 小于0.1秒 大于0.1秒 从收到WEB服务器重定向指令,到请求WEB服务器的第一个元素之前的消耗时间
收到第一个包时间 小于0.2秒 0.2~0.4秒 大于0.4秒 从浏览器发送HTTP请求结束开始到收到WEB服务器返回的第一个数据包的消耗时间
总下载时间 小于10秒 10~20秒 大于20秒 页面所有内容下载时间,反映的是页面的总体消耗,不同类型站点标准不同。仅参考
CDN节点匹配率 大于95% 90~95% 小于90% 指用户访问URL时是否分配到相应的运营商主机,如联通用户应访问联通主机
CND节点错误率 小于5% 5~10% 大于10% 用户访问URL时各CDN节点的错误情况
主机性能对比 小于3秒 3~5秒 大于5秒 最好的CND主机与最差的CND主机首屏时间对比

请求过多可能造成的报错

  • 场景1:请求过多导致的cat报错,关键词:0x80131904、找不到网络路径
System.Data.SqlClient.SqlException (0x80131904): 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。
未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。
(provider: Named Pipes Provider, error: 40 - 无法打开到 SQL Server 的连接) ---> System.ComponentModel.Win32Exception (0x80004005): 找不到网络路径。
  • 场景2:同类的JDBC错误,关键词:0x80131904、信号灯超时时间已到
### Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: 
Could not get JDBC Connection; nested exception is com.atomikos.jdbc.AtomikosSQLException: Failed to grow the connection pool.

Exception:System.Data.SqlClient.SqlException(0x80131904): 在从服务器接收结果时发生传输级错误。
(provider: TCP Provider, error: 0 – 信号灯超时时间已到) ===> System.ComponentModel.Win32Exception (0x80004005):信号灯超时时间已到
  • 场景3:IIS连接数暴涨,网站无法登录或查询,而 SQL Server Log 爆出大量10856错误,CPU很低,窗口查询正常
日期 源 消息
2017/11/2 19:45:53  spid108  The client was unable to reuse a sessin with SPTD 108, which had been reset for connetion pooling, The failwre ID is 29.
2017/11/2 19:45:53  spid108  错误: 18056,严重性: 20,状态: 29。

SQL Server报18056错误的分析过程

假设IIS的连接池设置100M,IIS连接数正常100个,那么每个session分配的连接池为1MB。由于数据库网络数据包默认4096字节(即4KB),假如每个session要返回4KB数据,则会话保持4/4=1秒。若偶尔几个需要返回2MB数据,该会话将会保持2*1024/4=512秒,正常情况可以慢慢消化,不会有太大问题。

若连接池100M,IIS连接数达到500个,则每个session分配的连接池为0.2MB,若每个session仅返回4KB数据,则会话保持4/4=1秒,但如果客户端不断的请求,超过最大连接数则会出现排队等待,直到有空闲的连接,这个等待时间受connection timeout(默认15s)限制,如果每个请求都能快速得到响应,即便有排队,也会慢慢消化。

若连接池100M,IIS连接数达到500个,则每个session分配的连接池为0.2MB,若有50个请求都要返回10MB(共500MB)数据,当数据库返回给IIS时发现连接池(100MB)没有足够的内存空间分配给这50个session。由于连接池不会随客户端请求的增加而自动增加,IIS就会释放掉无法处理的session。当数据库收到IIS请求并准备返回数据给相应session时却发现该spid已不存在,但是数据库的TCP连接不会因为spid不存在而立即抛弃这些数据,就会报18056错误,同时网卡流量也会增加。

  • 场景4:在事件查看器中,看到大量 MSSQLSERVER 错误:
级别 日期和时间 来源 时间ID 任务类别
错误 2017/11/2 19:45:51 MSSQLSERVER 18056 服务器

客户端无法重新使用 SPID 为 226 的会话,该会话已被重置用于连接池。失败 ID 为 29。此错误可能是由于先前的操作失败引起的。请查看错误日志,了解紧位于次错误消息之前的失败操作。
  • 场景5:收到iis连接数过多及http 503的告警,执行 netstat -ano > d:\netstat.log 并将该日志放到linux上分析,得到请求最多的ip、大量CLOSE_WAIT状态的连接
[root@localhost]# cat netstat.log | grep ":80" | wc -l
6371

[root@localhost]# cat netstat.log | grep ":80" | awk '{print $3}' | awk -F ':' '{print $1}' | sort|uniq -c |sort -nr |head -5
   1987 81.70.194.152
   1509 81.70.192.175
   1387 81.70.205.211
    755 81.70.198.136
    396 10.20.101.161

[root@localhost]# cat netstat.log | grep ":80" | awk '{print $4}' | sort|uniq -c |sort -nr |head -5
   4656 CLOSE_WAIT
   1061 ESTABLISHED
    393 TIME_WAIT
    202 LAST_ACK
     45 SYN_RECEIVED

优化配置实战

应用程序池的设置

打开应用程序池,找到Web站点对应的应用程序池,右键“高级设置”

  • [01] (常规)-.NET CLR版本:确认为v4.0
  • [02] (常规)-队列长度:默认值1000,将原来的队列长度改为 65535
  • [03] (常规)-启动32位应用程序:默认值False,改为True, 否则安装一些32位的组件或php都会出错
  • [04] (常规)-托管管道模式:默认Integrated,改为Integrated或Classsic
  • [05] (进程模型)-闲置超时(分钟):默认20分钟,改为120分钟

    注:也有建议设置为0,即不让应用程序池因为没有请求而回收

  • [06] (进程模型)-最大工作进程数:默认1,改为xx(太大则造成内存紧张及其他副作用)
  • [07] (快速故障防护)-已启用:默认True,改为False
  • [08] (回收)-固定时间间隔(分钟):默认1740分钟,改为0,表示不回收。

    注:即禁用应用程序池定期自动回收,解决第一次打开PEP速度慢的问题。

  • [09] (回收)-禁用重叠回收:默认False,改为True

    注:禁用之后,可有效避免Windows Server 2008 R2应用程序池回收假死的问题

  • [待定] (快速故障防护)-最大故障数:默认5,改为65535

网站设置的设置

打开网站,找到对应的网站,右键“管理网站”,选择“高级设置”

  • [10] (限制)-最大并发连接数:默认4294967295,改为100000

.Net Framework的相关设置

  • [11] 调整IIS 7的appConcurrentRequestLimit设置,由原来的默认5000改为100000,以下在cmd中执行:
cd /d c:\windows\system32\inetsrv\
appcmd.exe set config /section:serverRuntime /appConcurrentRequestLimit:100000

type c:\windows\system32\inetsrv\config\applicationHost.config | findstr appConcurrentRequestLimit
  • [12] 调整machine.config中的requestQueueLimit设置,以下在cmd中执行:
notepad %systemroot%\Microsoft.Net\Framework64\v4.0.30319\CONFIG\machine.config

打开 machine.config 后,在 <system.web> 中找到如下所示的 processModel 元素:

找到  <processModel autoConfig="true" />
改为  <processModel enable="true" requestQueueLimit="100000" />
  • [13] 调整ASP.NET线程配置,以下在cmd中执行:
notepad %systemroot%\Microsoft.Net\Framework64\v4.0.30319\CONFIG\machine.config

打开 machine.config 后,在 <processModel> 中添加如下设置:

<processModel enable="true" maxWorkerThreads="100" maxIoThreads="100" minWorkerThreads="50" minIoThreads="50" />

注册表的相关设置

  • [14] 调整IIS 7支持的TCP最大并发数,由原来的默认5000改为100000,以下在cmd中执行:
reg add HKLM\System\CurrentControlSet\Services\HTTP\Parameters /v MaxConnections /t REG_DWORD /d 100000

reg query HKLM\System\CurrentControlSet\Services\HTTP\Parameters /v MaxConnections
for /f "tokens=3 delims= " %i in ('reg query HKLM\System\CurrentControlSet\Services\HTTP\Parameters /v MaxConnections') do set /a %i
  • [15] 解决Bad Request - Request Too Long问题,以下在cmd中执行:
reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters /v MaxFieldLength /t REG_DWORD /d 32768
reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters /v MaxRequestBytes /t REG_DWORD /d 32768

应用设置

  • [16] 在web.config中添加如下几行,设置 Cache-Controlpublic
<configuration>
 <system.webServer>
  <staticContent>
   <clientCache cacheControlCustom="public" />
  </staticContent>
 </system.webServer>
</configuration>
  • [17] 代码上,Connection连接对象一定要及时 conn.Close() 关闭
  • [18] IIS站点,要在web.config里合理设置数据库最大连接池 Max Pool Size(默认100,建议xxx)
<connectionStrings> 
<add name="xxx" connectionstring="data source=192.168.4.120;pooling=true;max pool size=xxx;min pool size=5;packet size=4096;initial catalog=xxx;user id=xxx;password=xxx;connection timeout=180;" providername="system.data.sqlclient"/>
</connectionStrings>
  • [19] 若是JAVA业务,要在连接字符串中配置 minPoolSize 及 maxPoolSize
<bean>
<property name="user" value="xxx"/>
<property name="password" value="xxx"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="100"/>
<property name="borrowConnectionTimeout" value="60"/>
<property name="maxLifetime" value="1200"/>
</bean>

重启站点服务

  • [20] 运行 iisreset 重启iis使设置生效
net stop http & net start http & iisreset

完成上述设置,就可以支持10万个并发请求。

Copyright © www.sqlfans.cn 2023 All Right Reserved更新时间: 2023-05-15 09:11:23

results matching ""

    No results matching ""