閱讀目錄:
十余年的安龍網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都全網(wǎng)營銷的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整安龍建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“安龍網(wǎng)站設(shè)計(jì)”,“安龍網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
1.背景介紹
2.對(duì)業(yè)務(wù)功能點(diǎn)進(jìn)行邏輯劃分(如:A、B、C分別三個(gè)業(yè)務(wù)點(diǎn))
2.1.配置映射關(guān)系,對(duì)業(yè)務(wù)點(diǎn)配置查詢契約(構(gòu)造VS插件方便生成查詢契約)
2.2.將配置好的映射策略文件放在調(diào)用端,與服務(wù)不耦合
3.Dynamic、Dom動(dòng)態(tài)構(gòu)造服務(wù)端對(duì)象(Dynamic、DOM實(shí)現(xiàn)動(dòng)態(tài)DOM)
現(xiàn)在越來越多的公司都在嘗試SOA架構(gòu)的實(shí)踐,本人最近也在嘗試學(xué)習(xí)這方面的技術(shù),但是在實(shí)踐過程中遇到一個(gè)問題,我想這個(gè)問題也是我們普遍實(shí)踐者都應(yīng)該會(huì)遇到的問題,問題描述如下:
我們有一個(gè)SOA商品(Item)查詢接口,這個(gè)接口很通用,主要用來支撐日常很多其他系統(tǒng)的大量關(guān)于Item的查詢,尤其是在高峰期間該服務(wù)的壓力是很大的;我們站在SOA的角度看這個(gè)接口,這個(gè)通用的接口解決了眾多的查詢業(yè)務(wù),確實(shí)不錯(cuò),但是我們切換一下角度,站在每一個(gè)調(diào)用接口的訪問端看似乎并不是很滿意或者說犧牲了部分性能上的代價(jià),因?yàn)槲覀儫o法干凈利落的只獲取當(dāng)前這個(gè)業(yè)務(wù)點(diǎn)需要的數(shù)據(jù)項(xiàng);這個(gè)Item服務(wù)接口所返回的數(shù)據(jù)項(xiàng)必須同時(shí)滿足所有調(diào)用它的業(yè)務(wù)點(diǎn),哪怕這次調(diào)用我只需要用到Item的三分之一的數(shù)據(jù)字段都不行,每次都會(huì)把不需要的字段都查詢出來,不管是返回的性能、查詢的性能,其實(shí)都是可以通過調(diào)整設(shè)計(jì)來避免的;
以往我們的思路都是集中在服務(wù)端,常規(guī)做法都是提供了一個(gè)能夠容納所有查詢客戶端需求的數(shù)據(jù)實(shí)體,客戶端可選擇的余地很有限,無法只獲取自己所需要的幾個(gè)數(shù)據(jù)項(xiàng),甚至各個(gè)業(yè)務(wù)點(diǎn)在不同的情況下都有可能需要兩到三個(gè)數(shù)據(jù)返回實(shí)體;總而言之,面向數(shù)據(jù)查詢的服務(wù)接口如果要向著SOA方向發(fā)展那就必須包含SOA設(shè)計(jì)上的相關(guān)原則,如這里的面向查詢?yōu)橹鞯姆?wù)設(shè)計(jì)其實(shí)就是缺少SOA原則中的”服務(wù)應(yīng)具有策略性“一原則;
為什么以往一直沒有暴露出這個(gè)問題呢,是因?yàn)橐酝际窃诒镜刂苯诱{(diào)用“查詢引擎”,如:SQLSERVER,在“查詢引擎”的最后一層就是應(yīng)用程序,而應(yīng)用程序中可以編寫很多彼此類似的查詢方法,每個(gè)方法可能只有一兩個(gè)字段的差異性,或者通過“企業(yè)應(yīng)用架構(gòu)模式—查詢對(duì)象模式”來將不同的方法合在一起通過一個(gè)可以調(diào)整查詢字段的對(duì)象來配置本次需要的查詢字段;由于現(xiàn)在我們已將查詢服務(wù)化,就不太可能再去為了所有客戶端在去適應(yīng)性的去擴(kuò)充類似沒有太大價(jià)值的接口,但是客戶端又需要將自己所需要的查詢字段讓服務(wù)知道,所以這里的解決方案可以稱為面向SOA的”企業(yè)應(yīng)用架構(gòu)模式—查詢對(duì)象模式“;
本文將通過運(yùn)用”關(guān)注點(diǎn)分離“通用設(shè)計(jì)思想來對(duì)查詢服務(wù)在服務(wù)端的強(qiáng)耦合進(jìn)行分解,將強(qiáng)耦合從服務(wù)端遷移出來通過策略性的配置將關(guān)注點(diǎn)放入各自的客戶端,從而有效的解決服務(wù)不再臃腫的問題,如果理解上有困難可以嘗試使用面向SOA的”企業(yè)應(yīng)用架構(gòu)模式—查詢對(duì)象模式“概念來理解;
首先我們需要將相對(duì)于服務(wù)來說的客戶端中所有業(yè)務(wù)點(diǎn)進(jìn)行邏輯劃分,將原本一個(gè)高耦合的龐大數(shù)據(jù)實(shí)體分解成各自所需要的一個(gè)精簡(jiǎn)的數(shù)據(jù)實(shí)體;業(yè)務(wù)點(diǎn)的劃分目地在于可以將數(shù)據(jù)實(shí)體能與之對(duì)應(yīng)起來,這個(gè)數(shù)據(jù)實(shí)體是針對(duì)于查詢服務(wù)而言的,對(duì)于客戶端來說沒有任何的依賴和約束,也就是說本次業(yè)務(wù)點(diǎn)發(fā)起的查詢將把這個(gè)數(shù)據(jù)實(shí)體轉(zhuǎn)化成一組查詢策略中的設(shè)置帶到服務(wù)端中,然后服務(wù)端在根據(jù)這組策略信息進(jìn)行組合最終的查詢語句;
注:這里的數(shù)據(jù)實(shí)體并不是服務(wù)端定義的DTO,也不是客戶端定義的DTO,而是一個(gè)只跟本次業(yè)務(wù)查詢相關(guān)的數(shù)據(jù)查詢實(shí)體,該實(shí)體不是一個(gè)定義的類,而是一個(gè)策略,類似:
A.Business{Query field{ItemNumber、Description、PromationPrice}}
這樣一組配置信息;客戶端用來反序列化的DTO可以是一個(gè)龐大的共用的數(shù)據(jù)實(shí)體,也可以是跟業(yè)務(wù)點(diǎn)綁定的精簡(jiǎn)實(shí)體,對(duì)于查詢沒有任何影響,我們要解決的是“只查詢我所需要的數(shù)據(jù)項(xiàng),只返回我所需要的數(shù)據(jù)項(xiàng)”,而跟你在服務(wù)端、客戶端定義的用來輔助序列化的實(shí)體沒有任何關(guān)系;
將查詢的字段、返回的字段通過查詢策略帶入到服務(wù)端,我們就能夠知道本次業(yè)務(wù)點(diǎn)查詢的是需要什么樣的字段,然后就可以在構(gòu)造查詢引擎參數(shù)時(shí)將返回的字段直接加上或者過濾不需要的;
將系統(tǒng)中需要調(diào)用服務(wù)接口的所有功能點(diǎn)進(jìn)行業(yè)務(wù)點(diǎn)邏輯劃分設(shè)計(jì)后,每個(gè)業(yè)務(wù)點(diǎn)都需要在自己發(fā)起調(diào)用服務(wù)的時(shí)候能夠帶上在之前某個(gè)時(shí)間點(diǎn)設(shè)計(jì)好的查詢契約,這個(gè)用來生成查詢契約的工具最好是集成在VisualStudio中的自定義插件,在設(shè)計(jì)時(shí)用來動(dòng)態(tài)構(gòu)造一個(gè)對(duì)應(yīng)的契約配置文件,如果可以的話可以采用動(dòng)態(tài)代碼方案,將配置文件的靜態(tài)文件通過動(dòng)態(tài)生成代碼的方式嵌入到生成的代碼中去,減少不需要的配置文件,也減少查詢框架的性能開銷,一次生成后就可以直接使用;
本篇文章的解決方案最大的突破點(diǎn)就是將關(guān)注點(diǎn)從服務(wù)端轉(zhuǎn)移到所有客戶端上,將原本都集中在服務(wù)上的所有客戶端的需求分離出去,每個(gè)需要調(diào)用服務(wù)的客戶端維護(hù)好自己的一份查詢契約,在每次調(diào)用服務(wù)的時(shí)候帶上那份契約;如果處于性能考慮每次帶上契約會(huì)增加開銷,那么可以在第一次身份驗(yàn)證的時(shí)候在服務(wù)上確認(rèn),以后調(diào)用都忽略;
這樣一來服務(wù)將精簡(jiǎn)很多,通過同樣的設(shè)計(jì)方法可以用來設(shè)計(jì)很多類似的服務(wù)接口,將關(guān)注點(diǎn)從服務(wù)上轉(zhuǎn)移到客戶端上,會(huì)是一個(gè)很好的設(shè)計(jì)思路;
借助C#新特性Dynamic,我們可以在.NET平臺(tái)上進(jìn)行動(dòng)態(tài)編程,這里可以解決我們預(yù)先定義服務(wù)端實(shí)體的好處;以往我們需要在服務(wù)上定義一個(gè)至少能容納所有客戶端查詢契約中的所有數(shù)據(jù)項(xiàng)的實(shí)體,但是當(dāng)我們運(yùn)用動(dòng)態(tài)編程時(shí),我們無需事先定義一個(gè)類,而可以在運(yùn)行時(shí)動(dòng)態(tài)獲取對(duì)象屬性,當(dāng)然這得益于.NETDLR的實(shí)現(xiàn);再適當(dāng)?shù)慕Y(jié)合DOM思想,我們就可以實(shí)現(xiàn)一個(gè)動(dòng)態(tài)DOM效果,對(duì)于DOM的某個(gè)Element的訪問也無需定義映射實(shí)體然后在通過屬性獲取,中間既增加了序列化的開銷還增加了開發(fā)工作量;
using System; using System.Collections.Generic; namespace ConsoleApplication1.DynamicDom { public class ItemEntity : System.Dynamic.DynamicObject { ////// 可以使用LINQ TO XML或者將XML數(shù)據(jù)構(gòu)造在一個(gè)指定的容器中,用來判斷是否存在 /// private static DictionaryitemPropery = new Dictionary (); static ItemEntity() { itemPropery.Add("ItemNumber", 1029394); itemPropery.Add("PromationPrice", 100); } public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result) { if (itemPropery.ContainsKey(binder.Name)) { result = itemPropery[binder.Name]; return true; } result = null; return false; } } }
dynamic itemEntity = new DynamicDom.ItemEntity(); Console.WriteLine("ItemNumber:" + itemEntity.ItemNumber); Console.WriteLine("PromationPrice:" + itemEntity.PromationPrice); Console.ReadLine();
這里只是一個(gè)簡(jiǎn)單的示例,目的是想讓并不太了解Dynamic的朋友有了直觀上的認(rèn)識(shí);通過使用Dynamic、Dom可以在服務(wù)端上無需定義任何的實(shí)體,根據(jù)各個(gè)客戶端傳過來的配置直接進(jìn)行動(dòng)態(tài)訪問,可以借助LIQN TO XML;
全文僅僅是一個(gè)設(shè)計(jì)上的介紹,要想完全實(shí)現(xiàn)上面這些效果需要還是需要開發(fā)些東西的,這里只是拋磚引玉,希望對(duì)正在設(shè)計(jì)相關(guān)內(nèi)容的朋友提供一個(gè)思路;
作者:王清培
出處:http://wangqingpei557.blog.51cto.com/
本文版權(quán)歸作者和51CTO共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。