Windows服务中的exception处理最佳实践?

我目前正在编写一个完全在后台运行的Windows服务,每天都会做一些事情。 我的想法是服务应该非常稳定,所以如果出现问题,它应该不会停止,但是第二天再次尝试,当然还要记录exception。 你能告诉我如何制作真正稳定的Windows服务的最佳实践吗?

我已经阅读了Scott Hanselman关于exception处理最佳实践的文章 ,他写道,只有少数情况下你应该吞下一个例外。 我认为Windows服务是少数情况之一,但我很乐意得到一些确认。

“吞咽”exception与“放弃特定任务而不停止整个过程”不同。 在我们的Windows服务中,我们捕获exception,记录它们的详细信息,然后优雅地降级该任务并等待下一个任务。 然后,我们可以使用日志来解决服务器仍在运行时的错误。

您应该问的问题是,您的Windows服务是否应该具有容错能力。 记住任何未处理的exception都会导致服务中断,导致其立即无法使用。 您认为您的服务应如何表现? 它应该尝试并继续提供所需的服务吗? 应该终止吗?

在我看来,你应该在不可恢复和可恢复的exception之间建立一个强有力的区别,即阻止服务延续的exception(如果你的“静态”数据结构被破坏)和仅确定当前操作失败的exception。 要明确区分exception类层次结构的区别。

这种区别应该与服务的“主管”部分(计划定期行动的部分)结构和实际执行此类定期行动的部分之间的强烈区分相关。 如果是可恢复的exception,您可以中止正在运行的操作并完全重置最后一部分,显然将exception的所有详细信息记录到系统事件日志中; 另一方面,如果你有一个不可恢复的错误(主管的结构处于不一致的状态,当然是SEHexception),你应该记录你的错误并退出,因为继续以不一致的状态运行比不运行更危险。

实际上,如果您有意外的exception一直传递到服务的顶层,则不应继续处理; 记录它并传播它。 如果您确实需要“可靠”服务,那么您将需要一个“看门狗”,在退出时重新启动原始服务。

请注意,现代操作系统充当监视程序,因此在大多数情况下您不需要监视程序服务(请查看服务属性下的“恢复”选项卡)。 从历史上看,关键服务将拥有第二个“监视”服务,其唯一目的是在失败时重新启动实际服务。

听起来你的设计可能能够利用调度程序; 让Windows负责“每天一次”部分,让您的服务一次完成任务。 如果失败,那很好; Windows负责第二天再次启动它。

最后要注意的是:很少需要服务中的这种可靠性 。 在商业代码中,我只看到它用于几个防病毒程序和网络过滤程序(必须运行,否则所有网络通信都会失败)。 我自己做了几个“看门狗”计划,但这些都是针对像汽车公司这样的客户,当他们的assembly线系统出现故障时会损失大量资金。 除软件监视器外,这些系统还具有冗余电源,RAIDed热插拔硬盘驱动器以及整个系统的完整副本,可用作自动故障转移。

只是说:你可能想重新考虑你真正需要多少来提高可靠性(记住100%的可靠性是不可能的;它只能以指数成本来处理)。

像软件开发中的许多东西很少“一刀切”。 如果您认为在以后重新尝试吞下exception是合适的,那么这是完全合理的。 真正重要的是你自己清理,记录并确定一个合理的重试政策,然后再通知某人。

企业库的exception处理块可能非常有用,因为您可以在配置中修改exception策略而无需更改代码。

服务永远不会停止。 有两类错误,服务本身存在错误,以及提供给服务的数据错误。 应报告数据错误,但不应忽略。 这两个目标可以通过提供服务日志错误,提供向用户传输错误信息的方法,以及让服务在用户(或服务器中出现错误的情况下的程序员)之后重试失败来实现。纠正了导致服务失败的原因(显然,如果纠正了程序错误,必须停止,重新安装和重新启动服务)。

吞咽exception很少是一个好主意,斯科特在他的文章中说,实际上只有少数有效案例可能是最好的选择。

我的建议是首先要知道你正在捕捉的exception并抓住它们。 如果你知道你所捕获的是什么而不是通用的(Exception e)它对你将来会更有用。

一旦你发现exception然后如上所述,将其写入日志记录服务,也许将详细信息通过电子邮件发送给代码的维护者,甚至启动另一个事件,设置重新编写代码并限制向代码维护者发出新消息之前的尝试次数。

通过捕获特定的例外,您可以对它们进行特定的处理。 您还可以捕获常规exception,以确保您实际上没有预期的exception不会导致完整的系统故障。

一旦您了解了之前未发现的exception,就可以使用更理想的方式将这些exception重构到下一个版本中。