.net函数查询_特来电智能分析平台动态查询架构创新实践
一、業(yè)務(wù)背景及痛點
?目前主流互聯(lián)網(wǎng)智能分析平臺中,數(shù)據(jù)查詢作為基礎(chǔ)的設(shè)施服務(wù)支撐著基礎(chǔ)數(shù)據(jù)及業(yè)務(wù)分析的功能展現(xiàn)。隨著數(shù)據(jù)量的增長,數(shù)據(jù)存儲方式多元化,相對靜態(tài)數(shù)據(jù)可能存儲到關(guān)系型數(shù)據(jù)庫中,訂單類動態(tài)數(shù)據(jù)可能存儲到ElasticSearch、Greenplum數(shù)據(jù)庫中,實時類數(shù)據(jù)可能存儲到Druid、Redis中,每種數(shù)據(jù)庫都有各自的優(yōu)勢及局限。
傳統(tǒng)的數(shù)據(jù)服務(wù)實現(xiàn)面臨很多需求、技術(shù)挑戰(zhàn),存在諸多痛點,數(shù)據(jù)查詢需要從多個、多種數(shù)據(jù)庫中讀取數(shù)據(jù)進(jìn)行邏輯處理,過程中存在必不可少的篩選、遍歷、關(guān)聯(lián)、合并、拼接、轉(zhuǎn)換等處理,代碼實現(xiàn)一般采用ORM組件把從數(shù)據(jù)庫中查詢的數(shù)據(jù)反射為強類型的對象列表,然后使用LINQ進(jìn)行對象列表的查詢處理,實現(xiàn)過程邏輯比較繁瑣,并且類似的業(yè)務(wù)數(shù)據(jù)在各個產(chǎn)品應(yīng)用中不可避免的存在重復(fù)冗余的處理代碼,當(dāng)業(yè)務(wù)需求發(fā)生變動后需要修改代碼并重新部署文件,而且數(shù)據(jù)量比較大時可能存在性能上的問題,這樣的軟件產(chǎn)品可維護(hù)性、靈活性、通用性、拓展性、開發(fā)效率上比較差。
為解決以上痛點,提升開發(fā)效率、降低維護(hù)成本以及提高系統(tǒng)響應(yīng)及時性,針對這類查詢業(yè)務(wù),特來電云平臺數(shù)據(jù)分析BI組設(shè)計實現(xiàn)了通用數(shù)據(jù)查詢服務(wù)平臺,通過簡單的查詢配置即可從多種、多個數(shù)據(jù)庫中拉取數(shù)據(jù),并根據(jù)配置進(jìn)行相關(guān)業(yè)務(wù)數(shù)據(jù)的篩選聯(lián)查拼接等處理,開發(fā)、部署簡單輕量,當(dāng)業(yè)務(wù)發(fā)生變化時無需編碼調(diào)整,可以快速應(yīng)對需求的變更。平臺實現(xiàn)使用C# DataTable的DataColumn.Expression表達(dá)式、DataSet的DataRelation提升了數(shù)據(jù)處理的靈活性及通用性,使用微軟開源的.Net下的Javascript腳本引擎ClearScript降低查詢條件轉(zhuǎn)換、計算字段等業(yè)務(wù)的復(fù)雜度及耦合度。
二、平臺架構(gòu)整體實現(xiàn)
1.???查詢請求請求信息中要有該查詢的內(nèi)碼或編碼,同時需要有本次查詢的參數(shù)信息,前端傳入單層結(jié)構(gòu)的json對象,后臺可轉(zhuǎn)為Dictionary,這樣參數(shù)信息的數(shù)據(jù)結(jié)構(gòu)拓展性比較好些。2.???配置讀取、校驗查詢的配置包括查詢信息、數(shù)據(jù)源信息、參數(shù)轉(zhuǎn)換信息、結(jié)果字段信息、參數(shù)轉(zhuǎn)換函數(shù)信息,配置信息設(shè)計維護(hù)時存儲到Sql Server,運行時從Redis或進(jìn)程內(nèi)存中讀取,采用定時、實時更新機(jī)制。查詢配置的數(shù)據(jù)結(jié)構(gòu)如下:3.???參數(shù)轉(zhuǎn)換查詢的參數(shù)最終需要附加到查詢SQL或結(jié)果上,報表分析、Grafana等查詢分析界面?zhèn)魅氲膮?shù)格式各異,例如開始時間,查詢的參數(shù)值可能是yyyyMMdd格式,如果從ES查詢的話需要轉(zhuǎn)為yyyy-MM-dd并附加+08:00,從Sql Server不需要轉(zhuǎn)換,等等情況,參數(shù)的轉(zhuǎn)換需要有非常靈活的機(jī)制,強識別并不明智,使用JavaScript引擎ClearScript非常完美的達(dá)到目的。4.???數(shù)據(jù)組合數(shù)據(jù)的讀取原則上采用執(zhí)行SQL語句方式,SQL字符串語句方式比較靈活通用,轉(zhuǎn)換后的參數(shù)、分頁、排序最終轉(zhuǎn)換為SQL片段附加到要執(zhí)行的SQL語句上,根據(jù)數(shù)據(jù)源類型采用工廠模式實現(xiàn)參數(shù)轉(zhuǎn)換、數(shù)據(jù)讀取,目前可以從Sql Server、ES、Druid數(shù)據(jù)庫中拉取數(shù)據(jù),后繼可再添加其它數(shù)據(jù)庫類型的支持類。5.???字段計算處理過程主要是如何把查詢字段附加到主數(shù)據(jù)源表,字段可能是直接取值、Column表達(dá)式、JavaScirpt表達(dá)式,最后進(jìn)行數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換,并根據(jù)查詢結(jié)果結(jié)構(gòu)返回。6.???轉(zhuǎn)換處理數(shù)據(jù)返回前要根據(jù)查詢設(shè)置需要的數(shù)據(jù)結(jié)構(gòu)進(jìn)行轉(zhuǎn)換,例如返回結(jié)果類似于強類型數(shù)據(jù)結(jié)構(gòu),不經(jīng)轉(zhuǎn)換DataTable無法滿足要求,另外如果主數(shù)據(jù)源為ES,可能沒有任何行的情況下返回的數(shù)據(jù)為空,不滿足前臺使用要求,等等情況下有必要進(jìn)行一次DataTable轉(zhuǎn)List>,然后再處理為查詢配置要求的數(shù)據(jù)結(jié)構(gòu)類型。三、關(guān)鍵技術(shù)亮點
1.???巧用JavaScript引擎動態(tài)語言特性,實現(xiàn)動態(tài)配置軟件實現(xiàn)平臺化時需要整合同類邏輯處理為通用的實現(xiàn)過程,例如查詢服務(wù)的參數(shù)處理,把入?yún)⑻幚頌榭蓤?zhí)行的SQL片段,業(yè)務(wù)要求非常簡單,但是邏輯處理情況非常多,整合過程中對業(yè)務(wù)的強識別并不明智,有時候強識別也不現(xiàn)實,該類邏輯處理一般都有相似的輸入及輸出,我們可以把業(yè)務(wù)處理過程寫到一個字符串然后能動態(tài)執(zhí)行后返回想要的結(jié)果,例如我們通常會用SQL來編寫一些數(shù)據(jù)庫對象如:存儲過程、觸發(fā)器之類的對象,這些對象通過腳本來描述然后被解析成一個個實實在在的可執(zhí)行體,這些可執(zhí)行體是通過一系列預(yù)處理、詞法分析、語法分析等編譯環(huán)節(jié)最終形成可執(zhí)行體,當(dāng)我們使用的時候能快速的進(jìn)行調(diào)用,這樣大大增加了我們的運行效率及軟件實現(xiàn)的通用性及靈活性。c#是靜態(tài)語言,編譯后才可以使用,所以首先想到的是動態(tài)編譯生成dll文件后反射調(diào)用,但是不能每次調(diào)用都進(jìn)行動態(tài)編譯,需要進(jìn)行規(guī)則判斷,而且第一次調(diào)用編譯時耗時較長,性能上也達(dá)不到要求,易用性、靈活性、可維護(hù)性上也差強人意,動態(tài)字符串的執(zhí)行JavaScript有一個Eval函數(shù)可以實現(xiàn),c#也可以動態(tài)執(zhí)行腳本語言,這樣我們可以編寫易讀性、靈活性強的腳本代碼實現(xiàn)不可預(yù)測的邏輯處理,然后使用ClearScript? JavaScript引擎執(zhí)行腳本動態(tài)字符串達(dá)到我們的目的。ClearScript引擎可以將腳本功能添加到 .NET 應(yīng)用程序(.NET Framework 4 或更高版本),ClearScript 支持 VBScript、JavaScript 和 V8。V8 是由 Google 創(chuàng)建的開源JavaScript 引擎,并且與 Chrome 集成。V8 是高性能的 JavaScript 引擎,且非常適用于多線程和異步操作處理。ClearScript將 JavaScript 或 VBScript 表達(dá)式傳遞到引擎,而且并不只是可以使用純腳本對象,如數(shù)組、JSON 對象和基元類型,同時可以集成外部JavaScript 庫和腳本托管的c#類庫。使用ClearScript時可以先從NuGet安裝包查找添加引用,簡單的調(diào)用示例如下:using Microsoft.ClearScript.JavaScript;object result =null;using (var engine = new JScriptEngine( )){ result = engine.Execute(@"var a = 3; var b = 5; function add(a, b) { return a + b; } return add(a, b);");}性能測試如下:ClearScript可以集成外部腳本托管的c#對象,測試代碼如下:using ( var engine = new JScriptEngine( ) ){ //添加主機(jī)的模式,以便js可以調(diào)用主機(jī)這邊的c#Console函數(shù) engine.AddHostType( "Console" ,typeof( Console ) ); engine.Execute("Console.WriteLine('{0} is an interesting number.', Math.PI)" ); //添加主機(jī)的模式,以便js可以調(diào)用主機(jī)這邊的c#random函數(shù) engine.AddHostObject( "random", new Random( ) ); engine.Execute("Console.WriteLine(random.NextDouble())" ); //添加主機(jī)的模式,以便js可以調(diào)用主機(jī)這邊的c#System.Core類庫 engine.AddHostObject( "lib" ,new HostTypeCollection( "mscorlib" , "System.Core" ) ); engine.Execute("Console.WriteLine(lib.System.DateTime.Now)" ); //創(chuàng)建C#時間對象 engine.Execute( @" birthday = newlib.System.DateTime(2007, 5, 22); Console.WriteLine(birthday.ToLongDateString()); " ); //創(chuàng)建Dictionary對象 engine.Execute( @" Dictionary =lib.System.Collections.Generic.Dictionary; dict = new Dictionary(lib.System.String,lib.System.Int32); dict.Add('foo', 123); " );}可見無論靈活性、可用性、性能上ClearScript都非常理想,參數(shù)轉(zhuǎn)換動態(tài)執(zhí)行以及特殊字段處理我們可以引入到數(shù)據(jù)查詢平臺中使用。2.???舊瓶裝新酒,重用DataColumn.Expression數(shù)據(jù)庫存儲設(shè)計一般只是對基礎(chǔ)字段進(jìn)行存儲,對于動態(tài)計算后的字段需要業(yè)務(wù)代碼邏輯實現(xiàn),例如用戶信息存儲中只是存儲用戶的出生日期,并不會存儲用戶年齡,如果界面要顯示用戶的年齡,需要后臺根據(jù)當(dāng)前時間計算,當(dāng)然關(guān)系型數(shù)據(jù)庫可用直接查詢,但是其它類型數(shù)據(jù)庫未必支持,更為復(fù)雜的業(yè)務(wù)邏輯可能數(shù)據(jù)庫SQL也不一定能編寫實現(xiàn),假設(shè)需要我們后臺邏輯處理,一般的處理邏輯是執(zhí)行SQL返回DataTable或ORM組件后的List<強類型>,然后DataTable添加需要的業(yè)務(wù)列,遍歷每一行計算賦值,或者遍歷List<強類型>計算賦值,這樣實現(xiàn)后假設(shè)業(yè)務(wù)列的計算規(guī)則調(diào)整,需要我們重新編譯代碼,然后重新部署,靈活性、可維護(hù)性非常差,而且當(dāng)數(shù)據(jù)量超出一定數(shù)值后性能上也比較差, CPU占用比較高。ORM架構(gòu)有其優(yōu)點也存在缺點,數(shù)據(jù)庫的數(shù)據(jù)到內(nèi)存首先基本都是DataSet,數(shù)據(jù)處理前的數(shù)據(jù)類型我們建議還是使用DataTable,對于計算列的處理我們采用DataColumn.Expression方式,我們可以設(shè)置計算列的表達(dá)式實現(xiàn)復(fù)雜的業(yè)務(wù)邏輯處理,該方式可以整列計算或者關(guān)聯(lián)計算,而非行遍歷處理,靈活性、可維護(hù)性、性能上非常理想。DataColumn.Expression表達(dá)式功能非常強大,除一般的計算表達(dá)式、一對多、多對一父子級關(guān)系外還支持聚合、函數(shù)等實用性非常強的功能。計算表達(dá)式:DataTable dtMain = new DataTable( );dtMain.Columns.Add( "price" ,typeof( double ) );dtMain.Rows.Add( "30");dtMain.Rows.Add( "90");dtMain.Columns.Add( "tax" ,typeof( double ) , "price * 0.0862" );dtMain.Columns.Add( "total" ,typeof( double ) , "price + tax" );父/子關(guān)系引用在表達(dá)式中,可以通過使用 Parent追加列名稱來引用父表。例如,Parent.Price 引用名為 Price的父表的列。當(dāng)子級具有多個父行時,請使用Parent (RelationName)。ColumnName. 例如,Parent (RelationName)。價格通過關(guān)系引用名為Price 的父表的列。通過使用 Child追加列名稱,可以在表達(dá)式中引用子表中的列。但是,由于子關(guān)系可能返回多行,因此必須在聚合函數(shù)中包含對子列的引用。 例如,Sum(Child.Price) 將返回子表中名為 Price 的列的總和。如果表具有多個子元素,則語法為:Child(RelationName)。3.???內(nèi)存關(guān)系型數(shù)據(jù)處理的利器:DataSet. Relations有時候我們需要的結(jié)果需要匯總多個數(shù)據(jù)源并聯(lián)查合并后才能得出,一般的處理方式還是遍歷、篩選取值計算,這種處理方式不可取,一般從數(shù)據(jù)庫中讀取的第一數(shù)據(jù)類型是DataSet,然后我們?nèi)〉谝粋€表DataTable進(jìn)行數(shù)據(jù)處理,對于DataSet我們很少利用它的特性,DataSet是從數(shù)據(jù)源檢索的數(shù)據(jù)的內(nèi)存中緩存,是ADO.NET 體系結(jié)構(gòu)的主要組件。DataSet 包含 DataTable 對象的集合,這些對象可以與 DataRelation 對象相關(guān)聯(lián),也就是DataSet相當(dāng)于是內(nèi)存中的關(guān)系型數(shù)據(jù)庫,我們可以利用這個特性,定義數(shù)據(jù)關(guān)聯(lián)表達(dá)式,動態(tài)添加DataRelation,配合DataColumn.Expression實現(xiàn)非常通用、靈活高性能的數(shù)據(jù)關(guān)聯(lián)、篩選補充計算邏輯操作。四、?案例應(yīng)用
1.? Web API數(shù)據(jù)查詢服務(wù)平臺提供了Web API服務(wù),服務(wù)的創(chuàng)建只需要進(jìn)行簡單的配置即可提供相關(guān)業(yè)務(wù)的Web服務(wù),部署只需要執(zhí)行配置SQL即可,目前已支持近20多個服務(wù)接口,支持特來電運維電站詳情、用戶詳情、訂單詳情、電站實時監(jiān)控等業(yè)務(wù)功能。2. 報表開發(fā)?????? 查詢服務(wù)已作為報表開發(fā)平臺的一種數(shù)據(jù)源提供數(shù)據(jù)支持,對于業(yè)務(wù)不是非常復(fù)雜的報表實現(xiàn)了零編碼的在線開發(fā)。【查詢數(shù)據(jù)配置】【查詢配置數(shù)據(jù)源】【在線設(shè)計數(shù)據(jù)源信息】3.? Grafana數(shù)據(jù)分析Grafana作為數(shù)據(jù)分析開發(fā)工具集成了查詢服務(wù),對于簡單設(shè)置無法實現(xiàn)的業(yè)務(wù)數(shù)據(jù),通過查詢服務(wù)配置即可實現(xiàn),并且支持聯(lián)查類功能數(shù)據(jù)。五、帶來的價值和提升
動態(tài)數(shù)據(jù)查詢服務(wù)在特來電監(jiān)控分析產(chǎn)品應(yīng)用以及報表開發(fā)平臺中已經(jīng)大量應(yīng)用,報表開發(fā)平臺中集成查詢服務(wù)作為數(shù)據(jù)源后不必再配置sql.map和編寫dll文件,實現(xiàn)了真正的零編碼報表開發(fā),開發(fā)效率有了很大提升,大數(shù)據(jù)分析平臺grafana配置界面也作為數(shù)據(jù)源集成了該服務(wù),單一配置方式無法滿足的數(shù)據(jù)業(yè)務(wù),通過查詢服務(wù)配置得到了實現(xiàn),不必再編寫部署Web API服務(wù)。采用配置化的動態(tài)查詢平臺架構(gòu),大大提升了開發(fā)、部署效率以及需求響應(yīng)速度,可維護(hù)性、性能上也有很大提升,目前該服務(wù)平臺訪問量TPS比較高,服務(wù)穩(wěn)定、可靠,表現(xiàn)良好。六、規(guī)劃和展望
目前該查詢服務(wù)平臺只支持多個數(shù)據(jù)集的關(guān)聯(lián)計算,后期規(guī)劃支持去重、合并、自定義處理等功能,并且支持Redis、HBase等數(shù)據(jù)庫中讀取數(shù)據(jù),最終打造成零編碼的數(shù)據(jù)查詢統(tǒng)一平臺。總結(jié)
以上是生活随笔為你收集整理的.net函数查询_特来电智能分析平台动态查询架构创新实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows华硕主板如何开启vt虚拟化
- 下一篇: html如何将多个复选框组织成一组_[S