天天看點

.NET應用架構設計—面向查詢服務的參數化查詢設計(分解業務點,單獨配置各自的資料查詢契約)

.NET應用架構設計—面向查詢服務的參數化查詢設計(分解業務點,單獨配置各自的資料查詢契約)

現在越來越多的公司都在嘗試SOA架構的實踐,本人最近也在嘗試學習這方面的技術,但是在實踐過程中遇到一個問題,我想這個問題也是我們普遍實踐者都應該會遇到的問題,問題描述如下: 我們有一個SOA商品(Item)查詢接口,這個接口很通用,主要用來支撐日常很多其他系統的大量關于Item的查詢,尤其是在高峰期間該服務的壓力是很大的;我們站在SOA的角度看這個接口,這個通用的接口解決了衆多的查詢業務,确實不錯,但是我們切換一下角度,站在每一個調用接口的通路端看似乎并不是很滿意或者說犧牲了部分性能上的代價,因為我們無法幹淨利落的隻擷取目前這個業務點需要的資料項;這個Item服務接口所傳回的資料項必須同時滿足所有調用它的業務點,哪怕這次調用我隻需要用到Item的三分之一的資料字段都不行,每次都會把不需要的字段都查詢出來,不管是傳回的性能、查詢的性能,其實都是可以通過調整設計來避免的;

閱讀目錄:

  • 1.背景介紹
  • 2.對業務功能點進行邏輯劃分(如:A、B、C分别三個業務點)
    • 2.1.配置映射關系,對業務點配置查詢契約(構造VS插件友善生成查詢契約)
    • 2.2.将配置好的映射政策檔案放在調用端,與服務不耦合
  • 3.Dynamic、Dom動态構造服務端對象(Dynamic、DOM實作動态DOM)

現在越來越多的公司都在嘗試SOA架構的實踐,本人最近也在嘗試學習這方面的技術,但是在實踐過程中遇到一個問題,我想這個問題也是我們普遍實踐者都應該會遇到的問題,問題描述如下:

我們有一個SOA商品(Item)查詢接口,這個接口很通用,主要用來支撐日常很多其他系統的大量關于Item的查詢,尤其是在高峰期間該服務的壓力是很大的;我們站在SOA的角度看這個接口,這個通用的接口解決了衆多的查詢業務,确實不錯,但是我們切換一下角度,站在每一個調用接口的通路端看似乎并不是很滿意或者說犧牲了部分性能上的代價,因為我們無法幹淨利落的隻擷取目前這個業務點需要的資料項;這個Item服務接口所傳回的資料項必須同時滿足所有調用它的業務點,哪怕這次調用我隻需要用到Item的三分之一的資料字段都不行,每次都會把不需要的字段都查詢出來,不管是傳回的性能、查詢的性能,其實都是可以通過調整設計來避免的;

.NET應用架構設計—面向查詢服務的參數化查詢設計(分解業務點,單獨配置各自的資料查詢契約)

(檢視大圖)

以往我們的思路都是集中在服務端,正常做法都是提供了一個能夠容納所有查詢用戶端需求的資料實體,用戶端可選擇的餘地很有限,無法隻擷取自己所需要的幾個資料項,甚至各個業務點在不同的情況下都有可能需要兩到三個資料傳回實體;總而言之,面向資料查詢的服務接口如果要向着SOA方向發展那就必須包含SOA設計上的相關原則,如這裡的面向查詢為主的服務設計其實就是缺少SOA原則中的”服務應具有政策性“一原則;

為什麼以往一直沒有暴露出這個問題呢,是因為以往都是在本地直接調用“查詢引擎”,如:SQLSERVER,在“查詢引擎”的最後一層就是應用程式,而應用程式中可以編寫很多彼此類似的查詢方法,每個方法可能隻有一兩個字段的差異性,或者通過“企業應用架構模式—查詢對象模式”來将不同的方法合在一起通過一個可以調整查詢字段的對象來配置本次需要的查詢字段;由于現在我們已将查詢服務化,就不太可能再去為了所有用戶端在去适應性的去擴充類似沒有太大價值的接口,但是用戶端又需要将自己所需要的查詢字段讓服務知道,是以這裡的解決方案可以稱為面向SOA的”企業應用架構模式—查詢對象模式“;

本文将通過運用”關注點分離“通用設計思想來對查詢服務在服務端的強耦合進行分解,将強耦合從服務端遷移出來通過政策性的配置将關注點放入各自的用戶端,進而有效的解決服務不再臃腫的問題,如果了解上有困難可以嘗試使用面向SOA的”企業應用架構模式—查詢對象模式“概念來了解;

首先我們需要将相對于服務來說的用戶端中所有業務點進行邏輯劃分,将原本一個高耦合的龐大資料實體分解成各自所需要的一個精簡的資料實體;業務點的劃分目地在于可以将資料實體能與之對應起來,這個資料實體是針對于查詢服務而言的,對于用戶端來說沒有任何的依賴和限制,也就是說本次業務點發起的查詢将把這個資料實體轉化成一組查詢政策中的設定帶到服務端中,然後服務端在根據這組政策資訊進行組合最終的查詢語句;

注:這裡的資料實體并不是服務端定義的DTO,也不是用戶端定義的DTO,而是一個隻跟本次業務查詢相關的資料查詢實體,該實體不是一個定義的類,而是一個政策,類似:

A.Business{Query field{ItemNumber、Description、PromationPrice}}

這樣一組配置資訊;用戶端用來反序列化的DTO可以是一個龐大的共用的資料實體,也可以是跟業務點綁定的精簡實體,對于查詢沒有任何影響,我們要解決的是“隻查詢我所需要的資料項,隻傳回我所需要的資料項”,而跟你在服務端、用戶端定義的用來輔助序列化的實體沒有任何關系;

.NET應用架構設計—面向查詢服務的參數化查詢設計(分解業務點,單獨配置各自的資料查詢契約)

 (檢視大圖)

将查詢的字段、傳回的字段通過查詢政策帶入到服務端,我們就能夠知道本次業務點查詢的是需要什麼樣的字段,然後就可以在構造查詢引擎參數時将傳回的字段直接加上或者過濾不需要的;

将系統中需要調用服務接口的所有功能點進行業務點邏輯劃分設計後,每個業務點都需要在自己發起調用服務的時候能夠帶上在之前某個時間點設計好的查詢契約,這個用來生成查詢契約的工具最好是內建在VisualStudio中的自定義插件,在設計時用來動态構造一個對應的契約配置檔案,如果可以的話可以采用動态代碼方案,将配置檔案的靜态檔案通過動态生成代碼的方式嵌入到生成的代碼中去,減少不需要的配置檔案,也減少查詢架構的性能開銷,一次生成後就可以直接使用;

本篇文章的解決方案最大的突破點就是将關注點從服務端轉移到所有用戶端上,将原本都集中在服務上的所有用戶端的需求分離出去,每個需要調用服務的用戶端維護好自己的一份查詢契約,在每次調用服務的時候帶上那份契約;如果處于性能考慮每次帶上契約會增加開銷,那麼可以在第一次身份驗證的時候在服務上确認,以後調用都忽略;

這樣一來服務将精簡很多,通過同樣的設計方法可以用來設計很多類似的服務接口,将關注點從服務上轉移到用戶端上,會是一個很好的設計思路;

借助C#新特性Dynamic,我們可以在.NET平台上進行動态程式設計,這裡可以解決我們預先定義服務端實體的好處;以往我們需要在服務上定義一個至少能容納所有用戶端查詢契約中的所有資料項的實體,但是當我們運用動态程式設計時,我們無需事先定義一個類,而可以在運作時動态擷取對象屬性,當然這得益于.NETDLR的實作;再适當的結合DOM思想,我們就可以實作一個動态DOM效果,對于DOM的某個Element的通路也無需定義映射實體然後在通過屬性擷取,中間既增加了序列化的開銷還增加了開發工作量;

1 using System;
 2 using System.Collections.Generic; 
 3 
 4 namespace ConsoleApplication1.DynamicDom
 5 {
 6     public class ItemEntity : System.Dynamic.DynamicObject
 7     {
 8         /// <summary>
 9         /// 可以使用LINQ TO XML或者将XML資料構造在一個指定的容器中,用來判斷是否存在
10         /// </summary>
11         private static Dictionary<string, object> itemPropery = new Dictionary<string, object>();
12         static ItemEntity()
13         {
14             itemPropery.Add("ItemNumber", 1029394);
15             itemPropery.Add("PromationPrice", 100);
16         }
17         public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
18         {
19             if (itemPropery.ContainsKey(binder.Name))
20             {
21                 result = itemPropery[binder.Name];
22                 return true;
23             }
24             result = null;
25             return false;
26         }
27     }
28 }       
1 dynamic itemEntity = new DynamicDom.ItemEntity();
2 Console.WriteLine("ItemNumber:" + itemEntity.ItemNumber);
3 Console.WriteLine("PromationPrice:" + itemEntity.PromationPrice);
4 Console.ReadLine();       

這裡隻是一個簡單的示例,目的是想讓并不太了解Dynamic的朋友有了直覺上的認識;通過使用Dynamic、Dom可以在服務端上無需定義任何的實體,根據各個用戶端傳過來的配置直接進行動态通路,可以借助LIQN TO XML;

全文僅僅是一個設計上的介紹,要想完全實作上面這些效果需要還是需要開發些東西的,這裡隻是抛磚引玉,希望對正在設計相關内容的朋友提供一個思路;

作者:王清培

出處:http://www.cnblogs.com/wangiqngpei557/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面

繼續閱讀