马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
IIS的垃圾回收引起的影响
错误排查
现象:在.net core api里创建的BackgroundService界说rabbitmq消耗的逻辑,在一段时间运行后常常会出现消耗任务中断,在日志里找了很久的原因但是依然没有结论。
通过日志发现异常出现在消耗后的消息确认阶段,在执行确认的时间对应的channel和connection都关闭了- _channel.BasicAckAsync(eventArgs.DeliveryTag, false);
复制代码 报错信息如下,体现rabbitmq连接中断的原因是:由应用程序主动发起关闭的。- 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
- at RabbitMQ.Client.Impl.SessionBase.ThrowAlreadyClosedException()
- at RabbitMQ.Client.Impl.SessionBase.TransmitAsync[T](T& cmd, CancellationToken cancellationToken)
- at ALC.Server.Infrastructur.RabbitMq.RabbitMQClient.<>c__DisplayClass15_0`1.<<ConsumeMqMessage>b__0>d.MoveNext()
复制代码 这个报错一般是因为channel的作用域有问题,但是一般发生在启动时,很容易发现。我们这是消耗很多消息后才出现的,显然不属于这种情况,继续排查。后续发现w3wp.exe的报错,查看事件查看器,windows日志-系统发现有一连的信息如下:- 为应用程序池“net9”提供服务并且进程 ID 为“45552”的工作进程因不活动而被关闭。应用程序池超时配置被设置为 20 分钟。需要时将启动一个新工作进程。
复制代码 上述的“net9”是我配置的程序池名称- 弹出应用程序: Visual Studio 实时调试器: [45552] w3wp.exe 中发生了未经处理的 win32 异常。 对此异常的实时调试失败,错误为: 进程 ID 无效。
- 有关详细信息,请参见文档索引中的“实时调试, 错误”。
复制代码 通过对上述报错发现,应该和资源池的回收机制有关,因为资源池默认的回收时间就是20分钟。于是继续百度找到如下问题对应背景任务会被回收事件打断。受资源池回收的影响,即使不利用backgroundservice,rabbitmq的消耗历程也会被打断:
.net core背景任务办理iis自动回收导致任务被终止的问题
BackgroundService引起的影响
应对措施:让背景任务类或者rabbitmq的消耗类实现IDiposable或者IAsyncDisposable,因为资源池在回收的时间会执行Diposable或AsyncDisposable方法。在此方法内,发起一次对本系统的http调用(如果没问题继续调用),即可重新唤醒。- /// <summary>
- /// 释放托管资源,释放时触发
- /// </summary>
- public void Dispose()
- {
- Common.WriteEmailLog("定时任务被释放闭", "...Dispose...");
- _timer?.Dispose();
- //iis会回收这个定时任务,这边在回收的时候触发一个请求,来再次唤醒该服务
- Thread.Sleep(5000);
- HttpHelper.HttpGet(_configuration.GetSection("AwakenUrl").Value);
- }
复制代码 对于Rabbitmq消耗端的影响
- public async ValueTask DisposeAsync()
- {
- //异步关闭connection及channel
- await _mQClient.DisposeAsync();
- _logger.LogInformation("发起唤醒请求");
- //iis会回收这个rabbitmq的消费任务,这边在回收的时候触发一个请求,来再次唤醒该服务
- try
- {
- _logger.LogInformation("进入唤醒请求");
- //注意:这时HttpSimpleHelper已经不能以注入的方式去生成了,注意如果是多个实例同时部署到IIS,需要配置不同的AwakenUrl
- var result = await HttpSimpleHelper.GetAsync<bool>(_configuration.GetSection("AwakenUrl").Value);
- _logger.LogInformation($"唤醒请求结束:{result}");
- }
- catch (Exception ex)
- {
- _logger.LogError($"调用苏醒请求出错:{ex}");
- throw;
- }
-
- }
复制代码 对应的关闭channel及Connection的方法- public async ValueTask DisposeAsync()
- {
- if (_channel != null && _channel.IsOpen)
- {
- await _channel.CloseAsync();
- }
- if (_sendConnection != null && _sendConnection.IsOpen)
- {
- await _sendConnection.CloseAsync();
- }
- _channel?.DisposeAsync();
- _sendConnection?.DisposeAsync();
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
|