IIS的垃圾回收对背景任务及隐形背景任务的影响

打印 上一主题 下一主题

主题 1759|帖子 1759|积分 5277

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
IIS的垃圾回收引起的影响

错误排查

现象:在.net core api里创建的BackgroundService界说rabbitmq消耗的逻辑,在一段时间运行后常常会出现消耗任务中断,在日志里找了很久的原因但是依然没有结论。
通过日志发现异常出现在消耗后的消息确认阶段,在执行确认的时间对应的channel和connection都关闭了
  1. _channel.BasicAckAsync(eventArgs.DeliveryTag, false);
复制代码
报错信息如下,体现rabbitmq连接中断的原因是:由应用程序主动发起关闭的。
  1. RabbitMQ.Client.Exceptions.AlreadyClosedException: Already closed: The AMQP operation was interrupted: AMQP close-reason, initiated by Application, code=200, text='Goodbye', classId=0, methodId=0
  2.    at RabbitMQ.Client.Impl.SessionBase.ThrowAlreadyClosedException()
  3.    at RabbitMQ.Client.Impl.SessionBase.TransmitAsync[T](T& cmd, CancellationToken cancellationToken)
  4.    at ALC.Server.Infrastructur.RabbitMq.RabbitMQClient.<>c__DisplayClass15_0`1.<<ConsumeMqMessage>b__0>d.MoveNext()
复制代码
这个报错一般是因为channel的作用域有问题,但是一般发生在启动时,很容易发现。我们这是消耗很多消息后才出现的,显然不属于这种情况,继续排查。后续发现w3wp.exe的报错,查看事件查看器windows日志-系统发现有一连的信息如下:
  1. 为应用程序池“net9”提供服务并且进程 ID 为“45552”的工作进程因不活动而被关闭。应用程序池超时配置被设置为 20 分钟。需要时将启动一个新工作进程。
复制代码
上述的“net9”是我配置的程序池名称
  1. 弹出应用程序: Visual Studio 实时调试器: [45552] w3wp.exe 中发生了未经处理的 win32 异常。 对此异常的实时调试失败,错误为: 进程 ID 无效。
  2. 有关详细信息,请参见文档索引中的“实时调试, 错误”。
复制代码
通过对上述报错发现,应该和资源池的回收机制有关,因为资源池默认的回收时间就是20分钟。于是继续百度找到如下问题对应背景任务会被回收事件打断。受资源池回收的影响,即使不利用backgroundservice,rabbitmq的消耗历程也会被打断:
.net core背景任务办理iis自动回收导致任务被终止的问题
BackgroundService引起的影响

应对措施:让背景任务类或者rabbitmq的消耗类实现IDiposable或者IAsyncDisposable,因为资源池在回收的时间会执行Diposable或AsyncDisposable方法。在此方法内,发起一次对本系统的http调用(如果没问题继续调用),即可重新唤醒。
  1. /// <summary>
  2.             /// 释放托管资源,释放时触发
  3.             /// </summary>
  4.             public void Dispose()
  5.             {
  6.                 Common.WriteEmailLog("定时任务被释放闭", "...Dispose...");
  7.                 _timer?.Dispose();
  8.                 //iis会回收这个定时任务,这边在回收的时候触发一个请求,来再次唤醒该服务
  9.                 Thread.Sleep(5000);
  10.                 HttpHelper.HttpGet(_configuration.GetSection("AwakenUrl").Value);
  11.             }
复制代码
对于Rabbitmq消耗端的影响
  1. public async ValueTask DisposeAsync()
  2. {
  3.     //异步关闭connection及channel
  4.     await _mQClient.DisposeAsync();
  5.     _logger.LogInformation("发起唤醒请求");
  6.     //iis会回收这个rabbitmq的消费任务,这边在回收的时候触发一个请求,来再次唤醒该服务
  7.     try
  8.     {
  9.         _logger.LogInformation("进入唤醒请求");
  10.         //注意:这时HttpSimpleHelper已经不能以注入的方式去生成了,注意如果是多个实例同时部署到IIS,需要配置不同的AwakenUrl
  11.         var result = await HttpSimpleHelper.GetAsync<bool>(_configuration.GetSection("AwakenUrl").Value);
  12.         _logger.LogInformation($"唤醒请求结束:{result}");
  13.     }
  14.     catch (Exception ex)
  15.     {
  16.         _logger.LogError($"调用苏醒请求出错:{ex}");
  17.         throw;
  18.     }
  19.    
  20. }
复制代码
对应的关闭channel及Connection的方法
  1. public async ValueTask DisposeAsync()
  2. {
  3.      if (_channel != null && _channel.IsOpen)
  4.      {
  5.          await _channel.CloseAsync();
  6.      }
  7.      if (_sendConnection != null && _sendConnection.IsOpen)
  8.      {
  9.          await _sendConnection.CloseAsync();
  10.      }
  11.      _channel?.DisposeAsync();
  12.      _sendConnection?.DisposeAsync();
  13. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

不到断气不罢休

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表