14

我的 Azure 角色从数据库中获取要处理的内容- 它拥有一个实例System.Data.SqlClient.SqlConnection并定期创建一个SqlCommand实例并执行 SQL 查询。

现在偶尔(通常几天一次)运行查询将触发SqlException异常

服务在处理您的请求时遇到错误。请再试一次。错误代码 40143。当前命令出现严重错误。结果,如果有的话,应该丢弃。

我已经看过很多次了,现在我的代码捕捉到它,调用Dispose()实例SqlConnection,然后重新打开连接并重试查询。后者通常会导致另一个SqlException异常

超时已过。在操作完成之前超时时间已过或服务器没有响应。

这看起来很像 SQL Azure 服务器由于某种原因没有响应或不可用。

目前我的代码没有捕捉到后一个异常,它被传播到外部RoleEntryPoint.Run()并重新启动角色。重新启动通常需要大约十分钟,一旦完成,问题就会消失一天左右。

我不喜欢我的角色重新启动 - 这需要一段时间,而且我的服务功能受到阻碍。我想做一些更聪明的事情。

解决这个问题的策略是什么?我应该多次重试查询,多少次以及间隔多长时间?我应该做点别的吗?我什么时候放弃,让角色重新开始?

4

2 回答 2

14

我强烈建议您查看SQL Azure 的瞬态故障处理框架

这将帮助您处理连接和查询尝试的重试逻辑,我在生产中使用它并且效果很好。technet 上还有一篇不错的文章,可能会有一些用处。

[编辑:2013 年 10 月 17 日]

看起来这已经被瞬态故障处理应用程序块的模式和实践团队所接受

于 2011-08-10T07:14:38.910 回答
2

我们使用 TransientFaultHandling,它不能处理所有奇怪的异常。

例如,昨天弹出了这个:

服务在处理您的请求时遇到错误。请再试一次。错误代码 40143。当前命令出现严重错误。结果,如果有的话,应该丢弃。, 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() 在 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, . . .

即使这样也可以使用的合理方法:

  1. 识别调用发生的粗粒度伪事务。
  2. 将此块包装在 try-catch 中。
  3. 在异常情况下,“回滚”伪事务。

典型工作流程示例:

  • 获取 Azure 队列消息
  • B 从 SQL Azure 查询数据
  • C处理数据,
  • D 上传结果
  • E 删除消息。

Wrap B through C together in a try-catch. If something happens during 'harmless' SQL Azure call, simply bail out without deleting the message, it will simply pop up again after visibility timeout expires.

Actually, this is very common approach: organize into transaction-like blocks, wrap block into try-catch, neatly roll back on exception. And never, never assume that some calls do not fail. All call fail from time to time.

于 2012-12-07T18:49:42.767 回答