我目前正在编写一个完全在后台运行的Windows服务,每天都会做一些事情。我的想法是服务应该非常稳定,所以如果出现问题,它应该不会停止,但是第二天再次尝试,当然要记录异常。你能建议我如何制作真正稳定的Windows服务吗?
我已经阅读了Scott Hanselman of exception handling best practice的文章,他写道,只有少数情况下你应该吞下一个例外。我认为Windows服务是少数情况之一,但我很乐意得到一些确认。
答案 0 :(得分:7)
'吞咽'异常与'放弃特定任务而不停止整个过程'不同。 在我们的Windows服务中,我们捕获异常,记录它们的详细信息,然后优雅地降级该任务并等待下一个任务。然后,我们可以使用日志来解决服务器仍在运行时的错误。
答案 1 :(得分:4)
您应该问的问题是,您的Windows服务是否应该具有容错能力。记住任何未处理的异常都会导致服务中断,导致其立即无法使用。您认为您的服务应如何表现?它应该尝试并继续提供所需的服务吗?应该终止吗?
答案 2 :(得分:2)
在我看来,你应该在不可恢复和可恢复的异常之间建立一个强有力的区别,即阻止服务延续的异常(如果你的“静态”数据结构被破坏)和仅确定当前失败的异常操作。要明确区分异常类层次结构的区别。
这种区别应与服务的“主管”部分(计划定期行动的部分)的结构和实际所做的部分之间的强烈区别相关。定期行动。如果是可恢复的异常,您可以中止正在运行的操作并完全重置最后一部分,显然将异常的所有细节记录到系统事件日志中;另一方面,如果你遇到了一个不可恢复的错误(管理员的结构处于不一致状态,当然还有SEH异常),你应该记录你的错误然后退出,因为继续以不一致的状态运行比没有运行更危险
答案 3 :(得分:2)
实际上,如果您有意外的异常一直传递到服务的顶层,那么您应该不继续处理;记录它并传播它。如果您确实需要“可靠”的服务,那么您将需要一个“看门狗”,在退出时重新启动原始服务。
请注意,现代操作系统充当监视程序,因此在大多数情况下您不需要监视程序服务(请查看“服务”属性下的“恢复”选项卡)。从历史上看,关键服务将拥有第二个“看门狗”服务,其唯一目的是在失败时重新启动实际服务。
听起来您的设计可能能够使用调度程序;让Windows负责“每天一次”部分,让您的服务一次完成任务。如果失败,那很好; Windows负责第二天再次启动它。
最后一点:很少需要服务中的可靠性级别。在商业代码中,我只看到它用于几个防病毒程序和网络过滤程序(必须运行,否则所有网络通信都会失败)。我自己做了几个“看门狗”计划,但这些都是针对汽车公司这样的客户,当他们的装配线系统出现故障时,这些公司将损失吨的资金。除软件看门狗外,这些系统还具有冗余电源,RAID热插拔硬盘驱动器以及整个系统的完整副本,可用作自动故障转移。
只是说:你可能想重新考虑你真正需要多少来提高可靠性(记住100%的可靠性是不可能的;只能以指数成本来处理它。)
答案 4 :(得分:1)
像软件开发中的许多东西很少“一刀切”。如果您认为在以后重新尝试吞下异常是合适的,那么这是完全合理的。真正重要的是你自己清理,记录并确定一个合理的重试政策,然后再通知某人。
企业库的异常处理块可能非常有用,因为您可以在配置中修改例外策略而无需更改代码。
答案 5 :(得分:1)
服务永远不会停止。有两类错误,服务本身存在错误,以及提供给服务的数据错误。应报告数据错误,但不应忽略。这两个目标可以通过提供服务日志错误,通过提供向用户传输错误信息的方法,以及让服务在用户(或服务中的错误的程序员)之后重试失败来实现。纠正导致服务失败的原因(显然,如果纠正了程序错误,必须停止,重新安装并重新启动服务)。
答案 6 :(得分:0)
吞咽异常很少是个好主意,斯科特在他的文章中说,实际上只有少数有效案例可能是最佳选择。
我的建议是首先要知道你捕获的异常并抓住它们。如果您知道自己捕获的是什么而不是通用的(Exception e)
一旦你发现异常然后如上所述,将其写入日志记录服务,也许将详细信息通过电子邮件发送给代码的维护者,或者甚至启动另一个事件,设置重新编写代码在向代码维护者发出新消息之前对尝试次数的限制。
通过捕捉特定的例外情况,您可以针对它们执行特定的操作。您还可以捕获常规异常,以确保实际不期望的异常不会导致完整的系统故障。
一旦您了解了之前未发现的异常,就可以使用更理想的方式将这些异常重构到下一个版本中。