【问题标题】:How to stop exception alerts from going bezerk如何阻止异常警报发狂
【发布时间】:2011-05-01 22:58:51
【问题描述】:

假设您的 .NET 系统需要在出现错误时向系统管理员发送电子邮件通知。示例:

try
{
    //do something mission critical 
}
catch(Exception ex)
{
    //send ex to the system administrator
    //give the customer a user-friendly explanation
} 

这个代码块每秒被不同的用户调用数百次。

现在假设底层 API/服务/数据库出现故障。这段代码会失败很多次。可怜的管理员会在收件箱中发现几百万封电子邮件,而开发人员会接到一个粗鲁的电话,并不是说今天早上一定会发生这样的事件(咳嗽)。

很明显,这不是一个可以很好扩展的设计。

首先想到的几个解决方案都存在某种缺陷:

  • 将错误记录到数据库中,然后通过 HTTP 健康检查将高错误计数暴露给外部监控服务,例如 Pingdom。 (到目前为止我最喜欢的候选人。但是如果数据库出现故障怎么办?)
  • 有一个静态缓存来跟踪最近的异常,并且警报系统总是首先检查重复项。 (似乎不必要的复杂,其次,很多错误消息的差异非常小 - 例如,如果错误中有时间戳,则它是无用的。)
  • 在某些错误后或基于对关键依赖项的持续监控以编程方式使我们的系统脱机(风险!如果出现短暂的误报怎么办?)
  • 只是不对这些错误发出警报,而是依靠系统的不同部分来监视和报告相关性。 (不应对我们没有预料到的“意外”错误。)

这似乎是一个必须解决的问题,而我们正在以一种愚蠢的方式解决它。欢迎提出建议,即使它们涉及完全不同的异常管理策略!

【问题讨论】:

  • 你说你喜欢登录数据库的想法。我同意这是控制你想要的最佳选择。但是,您说数据库可能已关闭,这就是您有点害怕此选项的原因。我说你必须忍受这些限制。如果数据库出现故障,您可能会遇到更多问题,而不仅仅是系统的这一部分(异常处理)出现故障。不可能预见所有可能出现并处理所有的事情。否则,我们将不得不构建能够自动处理电力供应不足的系统。

标签: .net design-patterns exception-handling error-handling alerts


【解决方案1】:

想到的最简单的解决方案是为这个异常块分配一个 ID 号(如 1)并记录最后一次通知给管理员的时间。如果通知之间的间隔时间不够长(比如一个小时),请不要再次通知管理员

如果这段代码通常会产生不止一种异常,您可能还需要记录异常的类;如果同一异常的通知之间经过的时间不够大,请不要再次通知管理员

【讨论】:

  • 我同意这个解决方案:以某种方式对异常进行分类,将您自己的异常处理模块放在中间,并使用 log4net 或 EntLib 在您自己的模块下进行处理(许多开箱即用的功能)
  • 我使用带有 LRU 映射的聚合器助手;关键是异常的类,这样我就可以过滤重复的异常。每 X 多个实例(或每单位时间)我会发出“20 多个这样的”异常。
【解决方案2】:

我之前开发过用于向管理员发送电子邮件的监控应用程序,但我会不好意思地承认我遇到过你的情况。解决方案是对您的电子邮件进行速率限制。保存在某处发送的最后一封电子邮件的时间,并建立检查以查看自上一封电子邮件在发送之前是否经过了最短时间(例如,10 分钟或更长时间,由您决定)。这样,您可怜的管理员将收到的最大电子邮件数量将是<time issue has been going on> / <period>。在我之前的系统管理员工作中,这平衡了我们需要知道问题仍然存在的需要,即需要有一个电子邮件箱而不是每小时收到 1000 封电子邮件。

【讨论】:

    【解决方案3】:

    我们的一个远程应用程序中有类似的东西。它通过电子邮件向中间邮箱发送所有例外情况,并且每小时运行一个脚本来扫描邮件,并创建一个摘要电子邮件,该电子邮件会触发到我们的团队邮箱(每天最多 24 封邮件),并将其余数据保存到本地数据库供将来参考。

    它不是防弹的,但它相当快速/易于设置。

    【讨论】:

      【解决方案4】:

      检查相似性(时间戳可以使用通配符(例如??:??)避开),并首先让它们发送给您一段时间。现在检查哪个发生的次数最多。

      比如说,A 类有 1000 个异常,B 类有 964 个,C 类有 120 个,D - H 类有 7 个。

      这意味着,每 100 次 A 和 B 型异常、每 10 次 C 型异常以及发生的所有其他异常都向系统管理员发送一封电子邮件。

      专业版:
      + 准确
      + 防止系统垃圾邮件
      + 实现的代码不多

      缺点:
      - 需要时间来制定可靠的统计数据
      - 重要的异常可能会被意外忽略
      - 依赖人类,这可能总是失败

      【讨论】:

        【解决方案5】:

        我知道这已经得到了回答,但我觉得仍然发布这个很有帮助。

        Microsoft 一直在添加有关云设计模式和架构的大量信息,从微服务和带有消息队列的服务总线到更细微的细节,应有尽有。这一切都在Microsoft Docs 网站上,在Azure Architecture 下归档。处理此类问题的特定模式是Circuit Breaker pattern

        使用这种模式并不能完全解决问题;仍然存在“我们如何决定通知操作人员的时间?”的问题。一种可能的解决方案是让断路器跳闸,并增加一个内部计数器以为跳闸创建一个唯一标识符(或类似的东西)。然后,后续通知可以使用此标识符。这只是一个示例 - 您可能还有其他方法可以合理地完成此操作。关键是我将使用断路器来处理决策逻辑,方法是将一个断路器放置在您需要拥有它的服务的任何地方,然后将一些东西链接到它上面以提供您所描述的有关通知的服务。不过,至少您可以避免发送大量电子邮件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-26
          • 2020-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多