我正在开发一项 Windows 服务,该服务每 15 秒轮询一次与启用网络的设备的连接。如果服务无法连接到设备,则会引发异常并在 15 秒后重试。所有这一切都很好。
但是,假设其中一个设备停机了一天或更长时间。我每 15 秒用相同的异常填充我的异常日志。如果抛出的异常在过去 x 小时内没有改变,是否有一种标准方法可以防止将异常写入事件日志?
我正在开发一项 Windows 服务,该服务每 15 秒轮询一次与启用网络的设备的连接。如果服务无法连接到设备,则会引发异常并在 15 秒后重试。所有这一切都很好。
但是,假设其中一个设备停机了一天或更长时间。我每 15 秒用相同的异常填充我的异常日志。如果抛出的异常在过去 x 小时内没有改变,是否有一种标准方法可以防止将异常写入事件日志?
实现所需的一种好方法是使用断路器设计模式。
我第一次读到这一点是在 Michael T. Nygard 所著的“发布它!设计和部署生产就绪软件”一书中,来自 Pragmatic Press,第 104-107 页。
断路器的想法是它位于系统之间的连接路径中,通过连接,观察“中断条件”。例如,它可能仅在连续五个连接都失败时触发。
一旦电路断开,所有通过断路器的调用都会立即失败,无需咨询外部服务。这一直持续到发生超时,此时断路器进入半开状态。尝试下一次调用 - 失败导致超时被重置,断路器闭合成功并且系统恢复操作。
一个快速的谷歌发现了蒂姆罗斯的一篇文章,读起来很好,而且更详细。
在您的情况下,您可以使用超时为 10 分钟并触发 5 次故障的断路器。然后,在全天失败的情况下,您的日志文件将包含为原始问题记录的 5 个异常,然后每小时仅记录 6 个(与 15 秒间隔的 240 个相比),表明问题仍然存在。
根据您的要求,您可以包括手动“重置”断路器,或者您可以让它在 10 分钟超时显示一切恢复正常时自动重置。这可能很有用——通常系统管理员需要做的事情越少,他们就越喜欢它。
也许有一个工作流程,如果轮询失败一定次数,轮询间隔就会增加。例如,每 15 秒轮询 3 次,如果失败则将轮询间隔增加到一分钟,如果失败 n 次则将时间增加到一小时。
老实说,上面的工作流程并没有真正解决您的问题。如果我是你,我会颠倒工作流程。而不是服务器轮询设备,为什么不反过来呢?当设备连接到联网机器时,您的客户端服务会向服务器发送消息,以便服务器知道该设备已连接并处于活动状态。
希望这可以帮助...
温迪
如果您在应用程序中使用异常处理块,我假设您这样做,您可以在不同的异常处理策略之间切换。首先是将异常信息写入事件日志的策略,然后在 n 次尝试或时间段后,您可以切换到不记录到事件日志的策略。
增加尝试连接之间的持续时间可能会解决您的问题。例如 newTimeout = n*atomicTimeout 其中 n 是尝试次数。
关于什么...
int count = 0;
while (true)
{
try
{
AttemptStuff()
}
catch (Exception ex)
{
if(count < 10)
{
EventLog.WriteEntry("my service", ex.ToString(), EventLogEntryType.Error);
count++;
}
}
}
断路器模式是个好主意,我说
查看 PHP 实现的一些设计,但可以应用于任何语言
http://artur.ejsmont.org/blog/PHP-Circuit-Breaker-initial-Zend-Framework-proposal