SQL Server 2008基於策略的管理,基於策略的管理(Policy Based Management),使DBA們可以制定管理策略,並將這些策略應用到伺服器、資料庫以及數據環境中的其他對象上去。基於動作策略(Action Policy)的異常處理使開發人員可以為異常處理制定策略,簡單的說,動 ...
SQL Server 2008基於策略的管理,基於策略的管理(Policy Based Management),使DBA們可以制定管理策略,並將這些策略應用到伺服器、資料庫以及數據環境中的其他對象上去。基於動作策略(Action Policy)的異常處理使開發人員可以為異常處理制定策略,簡單的說,動作策略只是一些可重覆使用的一個裝飾器,可以很容易應用與方法調用。
異常處理只是一個合乎邏輯的動作策略的一部分,動作策略決定如何對異常做出處理,微軟的Enterprise Library的異常處理模塊試圖為開發人員和policy制定者為整個企業級應用程式各層的異常處理創建一致的策略。但是,異常處理的策略是硬編碼的(也就是簡單的try-catch代碼塊)。
如下是簡單的示例代碼:
1 try
2 {
3 customersDataSet = RunQuery(“GetAllCustomers”);
4 }
5 catch(Exception ex)
6 {
7 bool rethrow = ExceptionPolicy.HandleException(ex, “Data Access Policy”);
8 if (rethrow)
9 throw;
10 }
紅色部分的Exception Policy是硬編碼的,這裡我給你介紹一種更好的基於動作策略(Action Policy)的異常處理,這個異常處理策略的的原理是充分利用C#的閉包Action<Action>,這個在園子里有很多討論:
Action<Action>其實就是一個委托:
public delegate void Action();
public delegate void ActionPolicy(Action action);
很容易我們就可以實現一個出現異常情況下重試3次的策略
1 void MyRetryPolicy(Action action)
2 {
3 int counter = 0;
4 while (true)
5 {
6 try
7 {
8 action();
9 return;
10 }
11 catch (DbException ex)
12 {
13 counter+=1;
14 if (counter==3)
15 {
16 throw;
17 }
18 Thread.Sleep(1);
19 }
20 }
21 }
這個策略可以這樣用:
1 // 沒有參數和返回值的簡單調用
2 MyRetryPolicy(() => LongRunningDbCall());
3 MyRetryPolicy(() => AnotherFragileCall());
4 // 有一個參數和返回值的調用
5 int result = 0;
6 MyRetryPolicy(() => result = CreateRecords(records));
上述代碼包含了兩部分的邏輯,異常處理和行動策略。這個代碼不夠通用,可以包裝一個行動策略。下麵介紹一下在我的項目中使用的行動策略,我使用Autofac模塊包裝了行動策略,代碼如下:
1 public class ActionPolicyModule : Module
2 {
3 protected override void Load(ContainerBuilder builder)
4 {
5 builder.Register(c => ComposeActionPolicy(c));
6 base.Load(builder);
7 }
8
9 static ActionPolicy ComposeActionPolicy(IComponentContext context)
10 {
11 ILog log = context.Resolve<ILog>();
12 var actionPolicy = ActionPolicy.With(e => CompositeExceptionHandler(e, log))
13 .Retry(3, (ex,i) =>
14 {
15 log.DebugFormat(ex, "Retrying exception for the {0} time", i);
16 SystemUtil.Sleep((0.5 + i).Seconds());
17 });
18 return actionPolicy;
19 }
20
21 static bool CompositeExceptionHandler(Exception ex, ILog log)
22 {
23 ExceptionCounters.Default.Add(ex);
24
25 if (ex.Message.Contains("Password"))
26 {
27 throw new SecuredException(ex);
28 }
29 if (ex is DbException)
30 {
31 return true;
32 }
33 log.Error(ex, "Unrecoverable exception");
34 return false;
35 }
36 }
我們的方法中對策略的調用的代碼很簡單:
1 public void AddAppliction(Application appInfo)
2 {
3 _scopes.Validate(appInfo, "AppInfo", AppRules.Appliction);
4 _log.DebugFormat("AddAppliction()");
5 _policy.Do( () => appRepository.AddAppliction(appInfo));
6 }
_policy就是一個ActionPolicy對象,來自於Autofac內的策略配置,這樣我們就可以在我們的代碼中去除類似於微軟的Enterprise Library的異常處理模塊的硬編碼代碼。細心的你註意到了紅色的代碼中使用一個Retry Action Policy,出錯的時候重試三次,每次之間間隔時間依次加長,重試了三次都不成功才拋出異常,這是一個很有用的功能,比如在資料庫發生死鎖的時候。動作策略還支持一種斷路器,我們的生活中有一種很常見的電路斷路器,在發生電涌或過載的時候保護我們的電路,我們的分散式系統中也會碰到類似的現象。
參考鏈接:http://www.cnblogs.com/shanyou/archive/2010/05/30/1747613.html