IIS 应用程序池每过一段时间,就异常关闭并提示:w3wp.exe [7668] 中发生了未经处理的 win32 异常。
〇、前言
在博主某次更新代码版本后,一直会隔一段时间就会出现如下提示,而且一天好几次。

出现报错的同时,应用程序池也时常自动关闭,影响了业务的正常运作,期间改了一些配置后仍然无效。
部分配置如下图:

一、原因分析
关于“Visual Studio 实时调试器”的报错,一般情况下是代码中的问题,影响到了程序的正常运行。
那么就需要进一步查找是哪个应用程序出的问题,这时需要通过“事件查看器”来查找系统日志。
打开方式:服务器管理器-->工具-->事件查看器。

筛选错误日志:

其中,同意报错的事件 ID 是相同的,点击对应的错误记录,查看具体报错内容。

这就对应上了,还是应用程序池“Timing.Interface.Operation”中的代码出了问题。
然后就是通过事件 ID 去查看最早的一条报错日志的时间,然后去查这个时间点更新了哪些内容,排查代码中的异常。
二、会导致应用程序池异常停止的情况
2.1 多线程操作耗时操作,造成拥堵逐渐加剧,内存占用到达临界值,最终导致系统崩溃
例如,一个耗时操作的接口,需要客户端调用,来更新数据。当业务繁忙时,会有很多调用请求进入,这样就会造成拥堵。
此时,可以通过锁机制,在上一个操作未完成时,不开始下一个操作,保证同一时间点仅有一个线程在更新数据。
采用两个方法:public static void Enter(object obj, ref bool lockTaken);、public static void Exit(object obj);
示例代码,仅供参考:
[ApiController]
[Route("api/[controller]/[action]")]
public class AsyncInvDetailController : ControllerBase
{
public static object obj = new object();
private static bool acquiredLock = false;
[HttpGet]
public void ActralOperation()
{
try
{
if (!acquiredLock)
{
try
{
Monitor.Enter(obj, ref acquiredLock);
Thread.Sleep(20000); // 模拟耗时操作
}
catch (Exception ex)
{
// 。。。。
}
finally
{
Monitor.Exit(obj);
acquiredLock = false;
}
}
}
catch (Exception ex)
{
// 。。。。
}
}
}
2.2 应用程序池标识不合适
应用程序池在新建时,标识默认为 ApplicationPoolIdentity,级别也是最低的,这样可能限制了程序的运行,此时就需要确认程序的功能,是否跟所选择的标识级别对应。
如下详细介绍了四种标识的差异,供参考。
在 IIS(Internet Information Services)中,应用程序池标识决定了运行应用程序池的用户账户。不同的标识类型赋予了应用程序池不同的权限和安全级别。
| 标识类型 | 权限等级 | 适用场景 | 安全性 | 管理复杂度 |
| LocalSystem | 最高 | 需要全面控制本地系统的应用 | 较低 | 简单 |
| LocalService | 低 | 不需要网络访问的普通应用 | 较高 | 简单 |
| NetworkService | 中等 | 需要访问网络资源的应用 | 中等 | 简单 |
| ApplicationPoolIdentity | 自定义 | 多租户环境或标准 Web 应用 | 高 | 中等 |
以下是四种标识的简介:
- LocalSystem
特点:拥有对本地计算机的完全控制权,可以访问几乎所有系统资源。
应用场景:
- 系统管理工具:例如某些系统管理工具或服务,可能需要读取和修改系统配置文件、安装驱动程序或执行其他高级系统任务。这些操作通常需要高权限,因此 LocalSystem 是合适的选择。
- 硬件控制:一些应用程序可能需要直接与硬件设备交互(如监控硬件状态、控制外围设备等)。这类应用通常需要较高的系统权限来完成其功能。
- 遗留应用:例如一些老旧的应用程序,可能没有考虑到权限隔离的问题,依赖于高权限账户才能正常运行。由于设计上的限制,这些应用可能无法使用较低权限的账户。
- 开发调试:例如开发者可能希望绕过复杂的权限设置,以便专注于功能开发和调试,而不必担心权限问题。在开发环境中临时使用 LocalSystem 可以简化权限管理和快速测试。
- LocalService
特点:提供有限的本地权限,适合大多数不需要网络访问的应用程序。
应用场景:
- 普通 Web 应用:例如一个简单的静态网站或不需要访问外部资源的动态网站。这类应用不需要高权限,使用 LocalService 可以提高安全性。
- 内部服务:一些只在本地运行的服务,例如日志记录服务或监控服务。这些服务通常只需要读写本地文件,不需要网络访问权限。
- 轻量级后台任务:定时任务或批处理作业,用于生成报告或清理临时文件。这类任务通常只需要基本的文件系统访问权限,不需要额外的网络权限。
- NetworkService
特点:可以访问网络资源,并通过计算机的凭据进行身份验证,适合需要网络访问的应用程序。
应用场景:
- 企业内部应用:企业内部的 Web 应用,需要访问数据库服务器或其他网络资源。这类应用通常需要访问网络资源,但不需要极高的权限,NetworkService 提供了合适的权限级别。
- 分布式应用:多个服务器之间的协同工作,如微服务架构中的各个服务。这类应用需要跨服务器通信,NetworkService 可以满足这种需求。
- 数据同步服务:用于定期同步数据的应用程序,可能需要从远程服务器获取数据。这类服务通常需要访问网络资源,但不需要完全的系统控制权限。
- ApplicationPoolIdentity
特点:专门为每个应用程序池创建的虚拟账户,具有最低必要的权限,默认情况下仅限于访问应用程序池所需的资源。
应用场景:
- 标准 Web 应用:一个典型的 ASP.NET 或 PHP Web 应用,需要访问本地文件系统和数据库。这类应用通常不需要高权限,使用 ApplicationPoolIdentity 可以最小化攻击面并提高安全性。
- 多租户环境:在一个共享主机环境中,多个不同客户的 Web 应用托管在同一台服务器上。每个应用程序池使用独立的 ApplicationPoolIdentity 账户,可以有效隔离各个应用,防止跨站点脚本攻击(XSS)或其他安全漏洞。
- 资源受限应用:一些资源密集型应用,如视频转码服务或大数据处理服务。通过为每个应用分配独立的 ApplicationPoolIdentity,可以更好地控制资源使用和权限分配。
- 自动化部署:CI/CD 流水线中的自动化部署步骤,涉及代码拉取、构建和发布。每个阶段的任务可以使用独立的 ApplicationPoolIdentity 来确保权限隔离和安全性。
选用和是的标志类型,应按照如下原则:
最小权限原则:始终遵循最小权限原则,只为应用程序分配所需的最低权限。
评估替代方案:在决定使用更高权限的账户之前,评估是否有其他较低权限的账户可以满足需求。
定期审查:定期检查应用程序池的标识设置,确保它们仍然符合当前的安全策略和业务需求。
使用托管服务账户:对于需要跨多个服务器的应用程序,考虑使用托管服务账户(如 gMSA),以便简化管理和提高安全性。
安全加固:即使选择了较高权限的账户,也应采取额外的安全措施,如启用应用程序池隔离、限制文件系统访问等。
2.3 应用程序池配置问题
检查应用程序池的‘高级设置’。
参考:https://www.cnblogs.com/sky6699/p/15406384.html#top
例如以下几项常用的修改项:

队列长度:HTTP.sys 将针对应用程序池排队的最大请求数。如果队列已满,新请求将收到 503“服务不可用”的响应。默认队列长度设置是1000,范围在10-65535 之间。
如果针对 64 位操作系统上的应用程序池将该属性设为 True,则为应用程序池提供服务的工作进程将处于 WOW64 (Windows on Windows64)模式。WOW64 模式下的进程是仅加载 32 位应用程序的 32 位进程。

应用程序池回收(Application Pool Recycling)是指自动重启或重新加载应用程序池的过程。这个过程涉及终止当前运行的应用程序池进程,并启动一个新的进程来接管请求。应用程序池回收的主要目的是提高应用程序的稳定性和性能,通过定期重启应用程序池来释放资源和清理内存。
特定时间:可以配置多个时间点,来定时回收。
虚拟内存限制(KB):工作进程可以使用的最大虚拟内存量(以 KB 为单位),超过此内存量,将导致应用程序池回收。如果值为 0,则表示没有限制。
专用内存限制(KB):工作进程可以使用的最大专用内存量(以 KB 为单位),超出此内存量,将导致应用程序池回收。如果值为 0,则表示没有限制。

标识,上一节已经详解过了,略过。
启动时间限制(秒):为工作进程指定的、启动并进行初始化的时间段(以秒为单位)。如果工作进程初始化时间超过启动时间限制,将被终止。
2.4 其他原因
- 文件夹权限问题
编辑文件夹的权限:

- 版本兼容性问题
当操作系统、.NET Framework 版本更新后,如果应用程序没有相应的调整,可能会遇到兼容性问题,从而导致异常。
- 第三方组件或模块的问题
使用了有问题的第三方 DLL、控件或其他库,这些组件可能会引入 bug 或者与 IIS 环境不兼容,导致应用程序池崩溃。
- 硬件故障
当以上问题都排查过后,最后还有可能黑丝硬件问题,例如硬盘故障、内存故障等等。
本文来自博客园,作者:橙子家,欢迎微信扫码关注博主【橙子家czzj】,有任何疑问欢迎沟通,共同成长!

浙公网安备 33010602011771号